thonny-3.2.7/0000755000175000017500000000000013611777205014065 5ustar annamaaannamaa00000000000000thonny-3.2.7/MANIFEST.in0000644000175000017500000000047513611773167015634 0ustar annamaaannamaa00000000000000include CHANGELOG.rst include CREDITS.rst include LICENSE.txt include README.rst include requirements.txt include licenses/ECLIPSE-ICONS-LICENSE.txt include packaging/linux/thonny.1 include packaging/icons/*.png include packaging/linux/org.thonny.Thonny.appdata.xml include packaging/linux/org.thonny.Thonny.desktop thonny-3.2.7/packaging/0000755000175000017500000000000013611777205016011 5ustar annamaaannamaa00000000000000thonny-3.2.7/packaging/icons/0000755000175000017500000000000013611777205017124 5ustar annamaaannamaa00000000000000thonny-3.2.7/packaging/icons/thonny-22x22.png0000644000175000017500000000103613611773167021731 0ustar annamaaannamaa00000000000000PNG  IHDRnbKGD̿ pHYs  tIME 5.~\IDAT(ϕ=kA3r7#FP0`΀_"E"`(Qbr{Oݽܞoy? uʊELz2eXH$ʔQ4Pwjl]C0N9KX$Q;zvFzhem#z8$DDH )ښl r8Gb{K`ϹKg2,F\Xǝ .H6! kmH ,j +Q򐔀}aaRe!0{,˰0} Ժz~?PNNɻ? =|9rj nH2yGFX^!) ?*W_.[M|7E0 ͼ3=X%zguc i~+kKIENDB`thonny-3.2.7/packaging/icons/thonny-256x256.png0000644000175000017500000000735713611773167022127 0ustar annamaaannamaa00000000000000PNG  IHDR{`gAMA a cHRMz&u0`:pQ<bKGD̿tIME \M IDATx_]EǿK[!Զ0& b "ARu'%(AM|4@"_[S&F16h`?»P] 53,:7??o؁&6y|B?(FAFn6Cs6[a|;df]F<:){/RMĥ86E.b;~Z)r-ފTMX+PR4#cfq3as?թ#Q\ʠޭ7,~يp--x ٟJ55?k)H8/M\Id]kx zڸfOxw r>"޽?IY]m w('I\UVDpM?C@1._[1oCK1Nh$#}/Ÿ0`.L"8t[E<ݘmyQHK#phh xO 5`mt꾾dOr i6_2U'U7 UFA|S|?`K,(f;zV)d6#IsG;CF$U^Wp-u:1%vGs$[>v? [, Tw\yaYEcUAR]׉CXU-hFqm[Uɱ [ jw\تYH||SJ{ ߱lt<2M|9BԗI46.x'8T`d `wch~P ھTC I/X[/O!Hz錍t~.m Dnlh/$ y;MKf $ !Ljht[8'l @U<#+{$>(ظN*03@nHb. ZN*o ~iV?E+H@|Db?@ a,o熏C&Y@}%,q9>&ĜdȲrb2`qͰʃAWȄz^N/B(,?2!6}bNrI>4#9 f:_'p-nB?a1JNBtdV܃pI)_c|o ~Iwf+# ԑn?X2(*:ȾZ)c]و'0:QlflM܆?︹d25,đN/ 1Z. ( Fy=}!N%* ,Up ;_9&",ݖǕhҨȖ@23RӑfU?-G <]eq,Y 9eMY.B*rOѾAJ)55WH脖J5BiYaI.D04MJ4fݚz;m՜<$>)7KRޅMIL\fMp\aW15;-\ ,[ΪezZH .-L@gJm-pRn 0 8nR`rUZ\,FSPTLe3t A@ި)ϕRh53E*I_E3˚j #]L9EU[w8N+ %ۡ]hm7Fa$>G˸fpZΌ!Khiճ ~wp<}@lE& |&]T u)r`:GvQY^->A3fD9r#krX5V|T͖D|x|vv3QqH@_kgcYYmEݜ6$MkIpV $$*[ Ê+z&&)5QH{k5~C#d2}Ms2oM457]Llq2/~ogFLx''ӡo2/wnNvL 5 'SlU{7<6@8lJujm(B꫼ |j )Ժ:uP8' !SmZW':eՑR4c{G:n\zDgdӰH}O4wF%kg0e ^jD4w-Vөrix8(U)Kw,usq9@#P>ww~ r Qʒrn544 q2(H9K44nʟM\QY4MM/IR{OĘ-jDϲ;CݢL븭Y.Ty^Gn%B%2ӏc~'"!u+ #S>=N@40b\+Ihj"ie~q1|Roi~]GA#3Df& )՚ 2(ɸdd6~Q}3g}LLr?GCQIwPUJ)u{W'Q&Mͤ`Psp\u/ns5|RgiYqCds^?!9k$6$_BHr)\ uf?!$c8W6L%dRz3ɏ{&`'@pnU` 7E!B!B!B!B!B!B!B!B!B!B!B!B!A4Y~O%tEXtdate:create2017-11-09T04:26:24-05:00xG%tEXtdate:modify2017-11-09T04:26:24-05:00%IENDB`thonny-3.2.7/packaging/icons/thonny-32x32.png0000644000175000017500000000116013611773167021731 0ustar annamaaannamaa00000000000000PNG  IHDR sbKGD̿ pHYs  tIME 16 \ؽIDATH;kAg/1 !,DC *BDڊ` L#bc!h!hBBl e^Zb9gμ3{3k U<6e, c.$ŕYڧG.J`ܓB3\tsưѪX ?C ^_{Y5c& #x'퇼Fa-/|}ʦB 4VxU$ _cQ0)ҴN(M;1LIxN~5 0V 6CJK+6@uB\̜;rB !Sa *WBlu;)Vc_bNo1f]D2Ge&9郉UWHW*)tcd\Й=Pi%VsPŒ9XXc϶'AV6@ד9TX KQ'KURxVqc_2BlnRfmhw)v)6V'n2?@/濰W\gcIENDB`thonny-3.2.7/packaging/icons/thonny-64x64.png0000644000175000017500000000164513611773167021753 0ustar annamaaannamaa00000000000000PNG  IHDR@@`UbKGD̿ pHYs  tIME "AA6IDAThIhAN& ACxIP! x0FAE o^rxA=(j<\&f!HQb .A4.=T86m' O!@|أPlC {(Si!,f"f!{Ix!rTAGE;/i+bT;lS?;*vތܗq@7XXW:{91 "K7SBC7_xG/_1LSjYfSٔծT!bWӕI6h S;G\EgEcJ$"Vi&0L`[z(DYZ]s󰌃J hN $QsI{Kb d<d#IRP?{?i&3)"O rWN@)LE?UjL.K Kb-'D_ڞE $ nGtDUgNHMQnWO$IB|F[m B,~^$]t `\!6>) nrv1N"+I:,;II8BT&:JI~r',%[ VI~($ ,3FoB@KQ|t%jHLC5blWM@&aO2(%qsȯ @`5ם^8]X°ܨ^p!uqǓSLVxg5|J^w7 CʈSX8{֪]u7Ѱyc_CݰK_O2=IeIENDB`thonny-3.2.7/packaging/icons/thonny-16x16.png0000644000175000017500000000032613611773167021740 0ustar annamaaannamaa00000000000000PNG  IHDR7bKGD̿ pHYs  tIME agIDAT(ϭ (CMRD"Ag|}|ۖ@n uYjPHӐ6ɚĆn:hVZȺGNOBTt#5IENDB`thonny-3.2.7/packaging/icons/thonny-192x192.png0000644000175000017500000000600513611773167022112 0ustar annamaaannamaa00000000000000PNG  IHDRդbKGD̿ pHYs  tIME;b IDATx]]lG]lݫ}zPiTTTP U%MRʛ[ו* D$JJ*ED2%ED}hԊЫ#vn;3;37{í/sf@ @ @ ]&Y+(1CC%\>f1wg(`$ ]|Gg=O"D 4 `1崙نkx'ZC@x}~X tI %uu ig@2+R n Y_a/1hۃxKgǏ)*F,߼r:L0W}㒯w:"!Cf5<]=-sfo{+ G~U/4i89\As bGCT< *oܱp>S*&ƽAp+yC*(^5#KkijF ÝDS`ۼcjMp<$Yu8gFDǒ;Ic.(o?:'`:~+md`2Jjw6Zߤ @N'Z7x j:zCP0ַM(# oizz=؅&MT)g: OM O&9T?cf$}{O  SAsZ/6R0K.){9i^Zu۽)WAt820~'13f瘛5cŠrAG=J+W.x@/:Cdg՝Muc.S7q6 G1mՙIajGTa\9JtqZczb7<lh̅|'tzR K K:zbۀZ*pBE)Z*tBG8`16S =q̽KZ$|D= wD8϶ cns)y$- )E&($ô{iBR「T/e0I}Bb.)#@( \I@6 63Ovsb;` ݜZ 8a8'4,§GkYpQ }%mh+ro惠6^< J<>3m]Tix ~D`dsPd3V=p*rͲHJW_dE_E|n0S_U|hd#_,]%e%E;֬A/aÜ염Z%y.a+X-9%[񌬙,OW#bSfT03tl:vBuRpm@#3%@~b} UUHV -C[-5mhy bnXǒcŘI.񿖛ҒhQѤAOAq rJ[ [g:%Ѹ1ꤚ(@$Tn(Ds 7&T9Pf3%TABLI 7$@h=G%p7=AQ U+SAs')cS"YVCrdc[>wkG9R0iqeFprO:-uaީCW=!XYQ@r$T]pi.x 9u*h! $:JQGNi(ZGff^U vd Ҿ~zLl܀L * %~  ;fVpx#Zwk= PQhZ,>Sp+S6_+g:fxPJ%L׺ wH^yVEߜi2FTf4C~IWT+x)55) knĬh[of4A|Mse&֡hs5kqQ#6ak3QAkbЄ`yIWmZ)9U 3Ka`g`S+j}swk:ChU.mSNY{ZHue[0nZ7$yrj%@kuެ[0nV=&lj%4Y59HJV[xdg.3⮧Qʒn$ R+^6yhPCSaʻl{"DS3@^ *RRtw`<+ӟq G < "O˚-=KULƖYݸV_Οo 1A~l/ӎI@Hp-k$ ڀJz\fawVՏ w'l"@lَ3mV#C7my.HF>lYH8Aek' {ɼ'!i A#tG JB+RGj#6`HiI,3PN4_ ,0r6|l(񽹲mTg?džo,6#0H1^͠\l/6/QQ}[Ҙsb*caWn#MHNPªl ZGUʪc"m:r`TmVo#HZS-hf#ib k*,gk#HFR֑2mLq܇>KsI~@ @ @ DY~j$OIENDB`thonny-3.2.7/packaging/icons/thonny-2.png0000644000175000017500000000050413611773167021312 0ustar annamaaannamaa00000000000000PNG  IHDR7gAMA a cHRMz&u0`:pQ<bKGD̿tIME \MLIDAT(ϭO90Mo2PPm,^U$ܲ!&T'5v91'IJ:%tEXtdate:create2017-11-09T04:26:24-05:00xG%tEXtdate:modify2017-11-09T04:26:24-05:00%IENDB`thonny-3.2.7/packaging/icons/thonny-48x48.png0000644000175000017500000000162213611773167021752 0ustar annamaaannamaa00000000000000PNG  IHDR00 1 bKGD̿ pHYs  tIME "6|*#IDATXkw?3of7$nҒڭ/$65 (xH< "|AD)-4BPH%P(%bj1m63;_YήH/wo} ; apy Iմ,]<3RHis_$pby0%7fyH]a! asw@]w໮0pĬܠ+(@ťQI1O!,b{X)C Nx:\&2ٿ`3IdN`)Kh94NひoF+8}oJ3&`qybcZs{6q6z-sCy.Zh:+ TW#*+z)jIENDB`thonny-3.2.7/packaging/icons/thonny-128x128.png0000644000175000017500000000306713611773167022115 0ustar annamaaannamaa00000000000000PNG  IHDRi7@bKGD̿ pHYs  tIME 6%IDATx_TU?Y+"kIX| &FaJQC KCж&Bpgfϝ{g9zgGs<}s~;      sfe0&I /nZ SR~ҌVf_[Zyʹf0"'y&_ Nw||ɰ^;h4/6fd\ Nt)-K/k23㬺gztі|dձ[8o6Ǩx݁Koy&~'E>Å):E+928D[gOC&:,)q++e8mn\"zyeЄ1q5ԡK|ŕ=hs wMZsoDNPr|!ew&ieW ٸHg 5i@.@j:&3lleDf\ zyZzJ{ 0V-gXS䛞iGk] 8╴(;xً^YGb&A6Ag=Xֳ0x77 *f6 A4$F706}4: uHMBE*SY_5-xhJS$ yL>Oՙ`"{RaICsh׆N}a0QgѮJ[eRLm"gD}1\~; fu @|>zZ~кeǰ+|گzS) B6wGcP=N~@KzhvG1|gBe2hӥԳQQߡ\J3 e'۾CAo`wle3%Z }&      ? M7BIENDB`thonny-3.2.7/packaging/linux/0000755000175000017500000000000013611777205017150 5ustar annamaaannamaa00000000000000thonny-3.2.7/packaging/linux/thonny.10000644000175000017500000000172013611773167020554 0ustar annamaaannamaa00000000000000.TH THONNY 1 .SH NAME thonny \- Python IDE for beginners .SH SYNOPSIS .B thonny [\fIFILE...\fR] .SH DESCRIPTION Thonny is a Python IDE for learning and teaching programming. .SH BASIC USAGE On the first run you see a code editor and the Python shell. .PP Enter some Python code (eg. .B print("Hello world") ) into the editor and save the file with Ctrl+S. .PP Now run the code by pressing F5. You should see the output of the program in the Python shell. .PP You can also enter Python code directly into the shell. .SH USING THE DEBUGGER You can see the steps Python takes to run your code. For this you need to press Ctrl+F5 to run the program in debug mode. In this mode you can advance the program either with big steps (F6) or small steps (F7). If you want to see how the steps affect program variables, then open global variables pane (View => Variables). .SH MORE INFORMATION You can find more information, screenshots and a walk-through video at https://thonny.org. thonny-3.2.7/packaging/linux/org.thonny.Thonny.desktop0000644000175000017500000000052313611773167024131 0ustar annamaaannamaa00000000000000[Desktop Entry] Type=Application Name=Thonny GenericName=Python IDE Exec=/usr/bin/thonny %F Comment=Python IDE for beginners Icon=thonny StartupWMClass=Thonny Terminal=false Categories=Development;IDE Keywords=programming;education MimeType=text/x-python; Actions=Edit; [Desktop Action Edit] Exec=/usr/bin/thonny %F Name=Edit with Thonny thonny-3.2.7/packaging/linux/org.thonny.Thonny.appdata.xml0000644000175000017500000000306313611773167024673 0ustar annamaaannamaa00000000000000 org.thonny.Thonny.desktop MIT MIT Thonny Python IDE for beginners

Thonny is a simple Python IDE with features useful for learning programming. It comes with a debugger which is able to visualize all the conceptual steps taken to run a Python program (executing statements, evaluating expressions, maintaining the call stack). There is a GUI for installing 3rd party packages and special mode for learning about references.

See the homepage for more information, screenshots and a walk-through video.

Development Education Debugger IDE ComputerScience org.thonny.Thonny.desktop https://thonny.org https://github.com/thonny/thonny/issues https://github.com/thonny/thonny/wiki https://thonny.org/img/screenshot.png Thonny stepping through a recursive function thonny
thonny-3.2.7/requirements.txt0000644000175000017500000000021413611773167017351 0ustar annamaaannamaa00000000000000jedi>=0.10 setuptools>=33.1.1 pyserial>=3.1.1 pylint>=1.6.5 astroid>=1.4.9 docutils>=0.13.1 mypy>=0.470 asttokens>=1.1.10 Send2Trash>=1.4.2 thonny-3.2.7/thonny/0000755000175000017500000000000013611777205015404 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/common.py0000644000175000017500000004331313611773167017255 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- """ Classes used both by front-end and back-end """ import os.path import platform import site import sys import tokenize from collections import namedtuple from typing import List, Optional # @UnusedImport import subprocess import logging import traceback from threading import Thread MESSAGE_MARKER = "\x02" ValueInfo = namedtuple("ValueInfo", ["id", "repr"]) FrameInfo = namedtuple( "FrameInfo", [ "id", "filename", "module_name", "code_name", "source", "lineno", "firstlineno", "in_library", "locals", "globals", "freevars", "event", "focus", "node_tags", "current_statement", "current_root_expression", "current_evaluations", ], ) TextRange = namedtuple("TextRange", ["lineno", "col_offset", "end_lineno", "end_col_offset"]) class Record: def __init__(self, **kw): self.__dict__.update(kw) def update(self, e, **kw): self.__dict__.update(e, **kw) def setdefault(self, **kw): "updates those fields that are not yet present (similar to dict.setdefault)" for key in kw: if not hasattr(self, key): setattr(self, key, kw[key]) def get(self, key, default=None): return self.__dict__.get(key, default) def __getitem__(self, key): return self.__dict__[key] def __delitem__(self, key): self.__dict__.__delitem__(key) def __setitem__(self, key, value): self.__dict__[key] = value def __contains__(self, key): return key in self.__dict__ def __repr__(self): keys = self.__dict__.keys() items = ("{}={}".format(k, repr(self.__dict__[k])) for k in keys) return "{}({})".format(self.__class__.__name__, ", ".join(items)) def __str__(self): keys = sorted(self.__dict__.keys()) items = ("{}={}".format(k, repr(self.__dict__[k])) for k in keys) return "{}({})".format(self.__class__.__name__, ", ".join(items)) def __eq__(self, other): # pylint: disable=unidiomatic-typecheck if type(self) != type(other): return False if len(self.__dict__) != len(other.__dict__): return False for key in self.__dict__: if not hasattr(other, key): return False self_value = getattr(self, key) other_value = getattr(other, key) if type(self_value) != type(other_value) or self_value != other_value: return False return True def __ne__(self, other): return not self.__eq__(other) def __hash__(self): return hash(repr(self)) def range_contains_smaller(one: TextRange, other: TextRange) -> bool: this_start = (one.lineno, one.col_offset) this_end = (one.end_lineno, one.end_col_offset) other_start = (other.lineno, other.col_offset) other_end = (other.end_lineno, other.end_col_offset) return ( this_start < other_start and this_end > other_end or this_start == other_start and this_end > other_end or this_start < other_start and this_end == other_end ) def range_contains_smaller_or_equal(one: TextRange, other: TextRange) -> bool: return range_contains_smaller(one, other) or one == other class InputSubmission(Record): """For sending data to backend's stdin""" def __init__(self, data: str, **kw) -> None: super().__init__(**kw) self.data = data class CommandToBackend(Record): """Command meant for the back-end""" def __init__(self, name: str, **kw) -> None: super().__init__(**kw) self.name = name class InterruptCommand(CommandToBackend): def __init__(self, **kw) -> None: if "name" in kw: del kw["name"] super().__init__("interrupt", **kw) class EOFCommand(CommandToBackend): def __init__(self, **kw) -> None: if "name" in kw: del kw["name"] super().__init__("eof", **kw) class ToplevelCommand(CommandToBackend): def __init__(self, name: str, argv: List[str] = [], **kw) -> None: super().__init__(name, **kw) self.argv = argv class DebuggerCommand(CommandToBackend): pass class InlineCommand(CommandToBackend): """ Can be used both during debugging and in waiting_toplevel_command state (eg. for sending variable and heap info requests) """ pass class MessageFromBackend(Record): def __init__(self, **kw) -> None: self.event_type = type(self).__name__ # allow event_type to be overridden by kw super().__init__(**kw) if not hasattr(self, "sequence"): self.sequence = self.event_type class ToplevelResponse(MessageFromBackend): pass class DebuggerResponse(MessageFromBackend): pass class BackendEvent(MessageFromBackend): def __init__(self, event_type: str, **kw) -> None: super().__init__(**kw) self.event_type = event_type class InlineResponse(MessageFromBackend): def __init__(self, command_name: str, **kw) -> None: super().__init__(**kw) self.command_name = command_name self.event_type = self.command_name + "_response" def serialize_message(msg: Record) -> str: # I want to transfer only ASCII chars because encodings are not reliable # (eg. can't find a way to specify PYTHONIOENCODING for cx_freeze'd program) return MESSAGE_MARKER + repr(msg).encode("UTF-7").decode("ASCII") def parse_message(msg_string: str) -> Record: # DataFrames may have nan # pylint: disable=unused-variable nan = float("nan") # @UnusedVariable assert msg_string[0] == MESSAGE_MARKER return eval(msg_string[1:].encode("ASCII").decode("UTF-7")) def normpath_with_actual_case(name: str) -> str: """In Windows return the path with the case it is stored in the filesystem""" assert os.path.isabs(name) or os.path.ismount(name), "Not abs nor mount: " + name assert os.path.exists(name), "Not exists: " + name if os.name == "nt": # https://stackoverflow.com/questions/2113822/python-getting-filename-case-as-stored-in-windows/2114975 name = os.path.normpath(name) from ctypes import create_unicode_buffer, windll buf = create_unicode_buffer(512) # GetLongPathNameW alone doesn't fix filename part windll.kernel32.GetShortPathNameW(name, buf, 512) # @UndefinedVariable windll.kernel32.GetLongPathNameW(buf.value, buf, 512) # @UndefinedVariable result = buf.value if result.casefold() != name.casefold(): # Sometimes GetShortPathNameW + GetLongPathNameW doesn't work # see eg. https://github.com/thonny/thonny/issues/925 windll.kernel32.GetLongPathNameW(name, buf, 512) # @UndefinedVariable result = buf.value if result.casefold() != name.casefold(): result = name if result[1] == ":": # ensure drive letter is capital return result[0].upper() + result[1:] else: return result else: # easy on Linux # too difficult on mac # https://stackoverflow.com/questions/14515073/in-python-on-osx-with-hfs-how-can-i-get-the-correct-case-of-an-existing-filenam # Hopefully only correct case comes into Thonny (eg. via open dialog) return os.path.normpath(name) def is_same_path(name1: str, name2: str) -> bool: return os.path.normpath(os.path.normcase(name1)) == os.path.normpath(os.path.normcase(name2)) def path_startswith(child_name: str, dir_name: str) -> bool: normchild = os.path.normpath(os.path.normcase(child_name)) normdir = os.path.normpath(os.path.normcase(dir_name)) return normdir == normchild or normchild.startswith(normdir.rstrip(os.path.sep) + os.path.sep) def read_source(filename): with tokenize.open(filename) as fp: return fp.read() def get_exe_dirs(): result = [] if site.ENABLE_USER_SITE: if platform.system() == "Windows": if site.getusersitepackages(): result.append(site.getusersitepackages().replace("site-packages", "Scripts")) else: if site.getuserbase(): result.append(site.getuserbase() + "/bin") main_scripts = os.path.join(sys.prefix, "Scripts") if os.path.isdir(main_scripts) and main_scripts not in result: result.append(main_scripts) if os.path.dirname(sys.executable) not in result: result.append(os.path.dirname(sys.executable)) return result def get_site_dir(symbolic_name, executable=None): if not executable or executable == sys.executable: result = getattr(site, symbolic_name, "") else: result = ( subprocess.check_output( [executable, "-m", "site", "--" + symbolic_name.lower().replace("_", "-")], universal_newlines=True, ) .decode() .strip() ) return result if result else None def get_base_executable(): if sys.exec_prefix == sys.base_exec_prefix: return sys.executable if platform.system() == "Windows": result = sys.base_exec_prefix + "\\" + os.path.basename(sys.executable) result = normpath_with_actual_case(result) else: result = sys.executable.replace(sys.exec_prefix, sys.base_exec_prefix) if not os.path.isfile(result): raise RuntimeError("Can't locate base executable") return result def get_augmented_system_path(extra_dirs): path_items = os.environ.get("PATH", "").split(os.pathsep) for d in reversed(extra_dirs): if d not in path_items: path_items.insert(0, d) return os.pathsep.join(path_items) def update_system_path(env, value): # in Windows, env keys are not case sensitive # this is important if env is a dict (not os.environ) if platform.system() == "Windows": found = False for key in env: if key.upper() == "PATH": found = True env[key] = value if not found: env["PATH"] = value else: env["PATH"] = value class UserError(RuntimeError): """Errors of this class are meant to be presented without stacktrace""" pass def is_hidden_or_system_file(path: str) -> bool: if os.path.basename(path).startswith("."): return True elif platform.system() == "Windows": from ctypes import windll FILE_ATTRIBUTE_HIDDEN = 0x2 FILE_ATTRIBUTE_SYSTEM = 0x4 return bool( windll.kernel32.GetFileAttributesW(path) # @UndefinedVariable & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM) ) else: return False def get_dirs_child_data(paths): """Used for populating local file browser's tree view. dir_paths contains full paths of the open directories. Returns information required for refreshing this view""" res = {} for path in paths: # assuming the path already has actual case res[path] = get_single_dir_child_data(path) return res def get_single_dir_child_data(path): if path == "": if platform.system() == "Windows": return {**get_windows_volumes_info(), **get_windows_network_locations()} else: return get_single_dir_child_data("/") elif os.path.isdir(path) or os.path.ismount(path): result = {} try: for child in os.listdir(path): full_child_path = os.path.join(path, child) if not os.path.exists(full_child_path): # must be broken link continue full_child_path = normpath_with_actual_case(full_child_path) if not is_hidden_or_system_file(full_child_path): st = os.stat(full_child_path, dir_fd=None, follow_symlinks=True) name = os.path.basename(full_child_path) result[name] = { "size": None if os.path.isdir(full_child_path) else st.st_size, "time": max(st.st_mtime, st.st_ctime), } except PermissionError: result[""] = {"kind": "error", "size": -1, "time": None} return result else: return None def get_windows_volumes_info(): # http://stackoverflow.com/a/2288225/261181 # http://msdn.microsoft.com/en-us/library/windows/desktop/aa364939%28v=vs.85%29.aspx import string from ctypes import windll all_drive_types = [ "DRIVE_UNKNOWN", "DRIVE_NO_ROOT_DIR", "DRIVE_REMOVABLE", "DRIVE_FIXED", "DRIVE_REMOTE", "DRIVE_CDROM", "DRIVE_RAMDISK", ] required_drive_types = ["DRIVE_REMOVABLE", "DRIVE_FIXED", "DRIVE_REMOTE", "DRIVE_RAMDISK"] result = {} bitmask = windll.kernel32.GetLogicalDrives() # @UndefinedVariable for letter in string.ascii_uppercase: if not bitmask & 1: pass else: drive_type = all_drive_types[ windll.kernel32.GetDriveTypeW("%s:\\" % letter) ] # @UndefinedVariable # NB! Drive A can be present in bitmask but actually missing. # In this case querying information about it would freeze the UI # for several seconds. # One solution is to uninstall the device in device manager, # but OS may restore the drive later. # Therefore it is safest to skip A drive (user can access it via Open dialog) if drive_type in required_drive_types and ( letter != "A" or drive_type != "DRIVE_REMOVABLE" ): drive = letter + ":" path = drive + "\\" try: st = os.stat(path) volume_name = get_windows_volume_name(path) if not volume_name: volume_name = "Disk" label = volume_name + " (" + drive + ")" result[path] = { "label": label, "size": None, "time": max(st.st_mtime, st.st_ctime), } except PermissionError: traceback.print_exc() # probably an empty cardreader slot bitmask >>= 1 return result def get_windows_volume_name(path): # https://stackoverflow.com/a/12056414/261181 import ctypes kernel32 = ctypes.windll.kernel32 volume_name_buffer = ctypes.create_unicode_buffer(1024) file_system_name_buffer = ctypes.create_unicode_buffer(1024) serial_number = None max_component_length = None file_system_flags = None result = kernel32.GetVolumeInformationW( ctypes.c_wchar_p(path), volume_name_buffer, ctypes.sizeof(volume_name_buffer), serial_number, max_component_length, file_system_flags, file_system_name_buffer, ctypes.sizeof(file_system_name_buffer), ) if result: return volume_name_buffer.value else: return None def get_windows_network_locations(): import ctypes.wintypes CSIDL_NETHOOD = 0x13 SHGFP_TYPE_CURRENT = 0 buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) ctypes.windll.shell32.SHGetFolderPathW(0, CSIDL_NETHOOD, 0, SHGFP_TYPE_CURRENT, buf) shortcuts_dir = buf.value result = {} for entry in os.scandir(shortcuts_dir): # full_path = normpath_with_actual_case(entry.path) lnk_path = os.path.join(entry.path, "target.lnk") if os.path.exists(lnk_path): try: target = get_windows_lnk_target(lnk_path) result[target] = { "label": entry.name + " (" + target + ")", "size": None, "time": None, } except: logging.getLogger("thonny").error( "Can't get target from %s", lnk_path, exc_info=True ) return result def get_windows_lnk_target(lnk_file_path): import thonny script_path = os.path.join(os.path.dirname(thonny.__file__), "res", "PrintLnkTarget.vbs") cmd = ["cscript", "/NoLogo", script_path, lnk_file_path] result = subprocess.check_output(cmd, universal_newlines=True, timeout=3) return result.strip() def execute_system_command(cmd, cwd=None, disconnect_stdin=False): env = dict(os.environ).copy() encoding = "utf-8" env["PYTHONIOENCODING"] = encoding # Make sure this python interpreter and its scripts are available # in PATH update_system_path(env, get_augmented_system_path(get_exe_dirs())) popen_kw = dict( stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, env=env, universal_newlines=True, bufsize=0, ) if cwd and os.path.isdir(cwd): popen_kw["cwd"] = cwd if disconnect_stdin: popen_kw["stdin"] = subprocess.DEVNULL if sys.version_info >= (3, 6): popen_kw["errors"] = "replace" popen_kw["encoding"] = encoding assert cmd.cmd_line.startswith("!") cmd_line = cmd.cmd_line[1:] proc = subprocess.Popen(cmd_line, **popen_kw) def copy_stream(source, target): while True: c = source.readline() if c == "": break else: target.write(c) target.flush() copy_out = Thread(target=lambda: copy_stream(proc.stdout, sys.stdout), daemon=True) copy_err = Thread(target=lambda: copy_stream(proc.stderr, sys.stderr), daemon=True) copy_out.start() copy_err.start() try: proc.wait() except KeyboardInterrupt as e: print(str(e), file=sys.stderr) copy_out.join() copy_err.join() thonny-3.2.7/thonny/__init__.py0000644000175000017500000002372013611773167017524 0ustar annamaaannamaa00000000000000import os.path import sys import platform from typing import TYPE_CHECKING, cast, Optional import traceback import logging SINGLE_INSTANCE_DEFAULT = True def _compute_thonny_user_dir(): if os.environ.get("THONNY_USER_DIR", ""): return os.path.expanduser(os.environ["THONNY_USER_DIR"]) elif is_portable(): if platform.system() == "Windows": root_dir = os.path.dirname(sys.executable) elif platform.system() == "Darwin": root_dir = os.path.join( os.path.dirname(sys.executable), "..", "..", "..", "..", "..", ".." ) else: root_dir = os.path.join(os.path.dirname(sys.executable), "..") return os.path.normpath(os.path.abspath(os.path.join(root_dir, "user_data"))) elif ( hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix or hasattr(sys, "real_prefix") and getattr(sys, "real_prefix") != sys.prefix ): # we're in a virtualenv or venv return os.path.join(sys.prefix, ".thonny") elif platform.system() == "Windows": from thonny import misc_utils return os.path.join(misc_utils.get_roaming_appdata_dir(), "Thonny") elif platform.system() == "Darwin": return os.path.expanduser("~/Library/Thonny") else: # https://specifications.freedesktop.org/basedir-spec/latest/ar01s02.html data_home = os.environ.get( "XDG_CONFIG_HOME", os.path.expanduser(os.path.join("~", ".config")) ) return os.path.join(data_home, "Thonny") def is_portable(): # it can be explicitly declared as portable or shared ... portable_marker_path = os.path.join(os.path.dirname(sys.executable), "portable_thonny.ini") shared_marker_path = os.path.join(os.path.dirname(sys.executable), "shared_thonny.ini") if os.path.exists(portable_marker_path) and not os.path.exists(shared_marker_path): return True elif not os.path.exists(portable_marker_path) and os.path.exists(shared_marker_path): return False # ... or it becomes implicitly portable if it's on a removable drive abs_location = os.path.abspath(__file__) if platform.system() == "Windows": drive = os.path.splitdrive(abs_location)[0] if drive.endswith(":"): from ctypes import windll return windll.kernel32.GetDriveTypeW(drive) == 2 # @UndefinedVariable else: return False elif platform.system() == "Darwin": # not exact heuristics return abs_location.startswith("/Volumes/") else: # not exact heuristics return abs_location.startswith("/media/") or abs_location.startswith("/mnt/") def get_version(): try: package_dir = os.path.dirname(sys.modules["thonny"].__file__) with open(os.path.join(package_dir, "VERSION"), encoding="ASCII") as fp: return fp.read().strip() except Exception: return "0.0.0" THONNY_USER_DIR = _compute_thonny_user_dir() CONFIGURATION_FILE = os.path.join(THONNY_USER_DIR, "configuration.ini") def _get_ipc_file_path(): from thonny import misc_utils import getpass if platform.system() == "Windows": base_dir = misc_utils.get_local_appdata_dir() else: base_dir = os.environ.get("XDG_RUNTIME_DIR") if not base_dir or not os.path.exists(base_dir): base_dir = os.environ.get("TMPDIR") if not base_dir or not os.path.exists(base_dir): base_dir = THONNY_USER_DIR ipc_dir = os.path.join(base_dir, "thonny-%s" % getpass.getuser()) os.makedirs(ipc_dir, exist_ok=True) if not platform.system() == "Windows": os.chmod(ipc_dir, 0o700) return os.path.join(ipc_dir, "ipc.sock") IPC_FILE = _get_ipc_file_path() def _check_welcome(): from thonny import misc_utils if not os.path.exists(CONFIGURATION_FILE) and not misc_utils.running_on_rpi(): from thonny.first_run import FirstRunWindow from thonny.config import ConfigurationManager mgr = ConfigurationManager(CONFIGURATION_FILE) win = FirstRunWindow(mgr) win.mainloop() return win.ok else: return True def launch(): import gettext import runpy if sys.executable.endswith("thonny.exe"): # otherwise some library may try to run its subprocess with thonny.exe # NB! Must be pythonw.exe not python.exe, otherwise Runner thinks console # is already allocated. sys.executable = sys.executable[: -len("thonny.exe")] + "pythonw.exe" set_dpi_aware() try: runpy.run_module("thonny.customize", run_name="__main__") except ImportError: pass gettext.install("thonny", "locale") _prepare_thonny_user_dir() if not _check_welcome(): return if _should_delegate(): try: _delegate_to_existing_instance(sys.argv[1:]) print("Delegated to an existing Thonny instance. Exiting now.") return 0 except Exception: traceback.print_exc() # Did not or could not delegate try: from thonny import workbench bench = workbench.Workbench() try: bench.mainloop() except SystemExit: bench.destroy() return 0 except SystemExit as e: from tkinter import messagebox messagebox.showerror("System exit", str(e)) return -1 except Exception: from logging import exception exception("Internal launch or mainloop error") from thonny import ui_utils dlg = ui_utils.LongTextDialog("Internal error", traceback.format_exc()) ui_utils.show_dialog(dlg, get_workbench()) return -1 finally: runner = get_runner() if runner is not None: runner.destroy_backend() return 0 def _prepare_thonny_user_dir(): if not os.path.exists(THONNY_USER_DIR): os.makedirs(THONNY_USER_DIR, mode=0o700, exist_ok=True) # user_dir_template is a post-installation means for providing # alternative default user environment in multi-user setups template_dir = os.path.join(os.path.dirname(__file__), "user_dir_template") if os.path.isdir(template_dir): import shutil def copy_contents(src_dir, dest_dir): # I want the copy to have current user permissions for name in os.listdir(src_dir): src_item = os.path.join(src_dir, name) dest_item = os.path.join(dest_dir, name) if os.path.isdir(src_item): os.makedirs(dest_item, mode=0o700) copy_contents(src_item, dest_item) else: shutil.copyfile(src_item, dest_item) os.chmod(dest_item, 0o600) copy_contents(template_dir, THONNY_USER_DIR) def _should_delegate(): if not os.path.exists(IPC_FILE): # no previous instance return from thonny.config import try_load_configuration configuration_manager = try_load_configuration(CONFIGURATION_FILE) configuration_manager.set_default("general.single_instance", SINGLE_INSTANCE_DEFAULT) return configuration_manager.get_option("general.single_instance") def _delegate_to_existing_instance(args): from thonny import workbench import socket transformed_args = [] for arg in args: if not arg.startswith("-"): arg = os.path.abspath(arg) transformed_args.append(arg) try: sock, secret = _create_client_socket() except Exception: # Maybe the lock is abandoned print("Trying to remove lock") os.remove(IPC_FILE) print("Successfully removed abandoned lock") raise data = repr((secret, transformed_args)).encode(encoding="utf_8") sock.settimeout(2.0) sock.sendall(data) sock.shutdown(socket.SHUT_WR) response = bytes([]) while len(response) < len(workbench.SERVER_SUCCESS): new_data = sock.recv(2) if len(new_data) == 0: break else: response += new_data if response.decode("UTF-8") != workbench.SERVER_SUCCESS: raise RuntimeError("Unsuccessful delegation") def _create_client_socket(): import socket timeout = 2.0 if platform.system() == "Windows": with open(IPC_FILE, "r") as fp: port = int(fp.readline().strip()) secret = fp.readline().strip() # "localhost" can be much slower than "127.0.0.1" client_socket = socket.create_connection(("127.0.0.1", port), timeout=timeout) else: client_socket = socket.socket(socket.AF_UNIX) # @UndefinedVariable client_socket.settimeout(timeout) client_socket.connect(IPC_FILE) secret = "" return client_socket, secret def set_dpi_aware(): # https://stackoverflow.com/questions/36134072/setprocessdpiaware-seems-not-to-work-under-windows-10 # https://bugs.python.org/issue33656 # https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx # https://github.com/python/cpython/blob/master/Lib/idlelib/pyshell.py if sys.platform == "win32": try: import ctypes PROCESS_SYSTEM_DPI_AWARE = 1 ctypes.OleDLL("shcore").SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE) except (ImportError, AttributeError, OSError): pass if TYPE_CHECKING: # Following imports are required for MyPy # http://mypy.readthedocs.io/en/stable/common_issues.html#import-cycles import thonny.workbench from thonny.workbench import Workbench from thonny.running import Runner from thonny.shell import ShellView _workbench = None # type: Optional[Workbench] def get_workbench() -> "Workbench": return cast("Workbench", _workbench) _runner = None # type: Optional[Runner] def get_runner() -> "Runner": return cast("Runner", _runner) def get_shell() -> "ShellView": return cast("ShellView", get_workbench().get_view("ShellView")) thonny-3.2.7/thonny/assistance.py0000644000175000017500000010263713611773167020127 0ustar annamaaannamaa00000000000000import ast import datetime import gzip import json import logging import os.path import sys import tempfile import textwrap import tkinter as tk import urllib.request import webbrowser from collections import namedtuple from tkinter import messagebox, ttk from typing import ( Dict, # pylint disable=unused-import Iterable, List, # pylint disable=unused-import Optional, # pylint disable=unused-import Tuple, # pylint disable=unused-import Type, # pylint disable=unused-import Union, # pylint disable=unused-import ) import thonny from thonny import get_workbench, rst_utils, tktextext, ui_utils, get_runner from thonny.common import ToplevelResponse, read_source from thonny.misc_utils import levenshtein_damerau_distance, running_on_mac_os from thonny.ui_utils import scrollbar_style, CommonDialog from thonny.running import CPythonProxy import subprocess Suggestion = namedtuple("Suggestion", ["symbol", "title", "body", "relevance"]) _program_analyzer_classes = [] # type: List[Type[ProgramAnalyzer]] _last_feedback_timestamps = {} # type: Dict[str, str] _error_helper_classes = {} # type: Dict[str, List[Type[ErrorHelper]]] class AssistantView(tktextext.TextFrame): def __init__(self, master): tktextext.TextFrame.__init__( self, master, text_class=AssistantRstText, vertical_scrollbar_style=scrollbar_style("Vertical"), horizontal_scrollbar_style=scrollbar_style("Horizontal"), horizontal_scrollbar_class=ui_utils.AutoScrollbar, read_only=True, wrap="word", font="TkDefaultFont", # cursor="arrow", padx=10, pady=0, insertwidth=0, ) self._analyzer_instances = [] self._snapshots_per_main_file = {} self._current_snapshot = None self._accepted_warning_sets = [] self.text.tag_configure( "section_title", spacing3=5, font="BoldTkDefaultFont", # foreground=get_syntax_options_for_tag("stderr")["foreground"] ) self.text.tag_configure( "intro", # font="ItalicTkDefaultFont", spacing3=10, ) self.text.tag_configure("relevant_suggestion_title", font="BoldTkDefaultFont") self.text.tag_configure("suggestion_title", lmargin2=16, spacing1=5, spacing3=5) self.text.tag_configure("suggestion_body", lmargin1=16, lmargin2=16) self.text.tag_configure("body", font="ItalicTkDefaultFont") main_font = tk.font.nametofont("TkDefaultFont") # Underline on font looks better than underline on tag italic_underline_font = main_font.copy() italic_underline_font.configure(slant="italic", size=main_font.cget("size"), underline=True) self.text.tag_configure("feedback_link", justify="right", font=italic_underline_font) self.text.tag_bind("feedback_link", "", self._ask_feedback, True) self.text.tag_configure("python_errors_link", justify="right", font=italic_underline_font) self.text.tag_bind( "python_errors_link", "", lambda e: get_workbench().open_url("errors.rst"), True, ) get_workbench().bind("ToplevelResponse", self.handle_toplevel_response, True) add_error_helper("*", GenericErrorHelper) def handle_toplevel_response(self, msg: ToplevelResponse) -> None: # Can be called by event system or by Workbench # (if Assistant wasn't created yet but an error came) if not msg.get("user_exception") and msg.get("command_name") in [ "execute_system_command", "execute_source", ]: # Shell commands may be used to investigate the problem, don't clear assistance return self._clear() if not isinstance(get_runner().get_backend_proxy(), CPythonProxy): # TODO: add some support for MicroPython as well return # prepare for snapshot key = msg.get("filename", "") self._current_snapshot = { "timestamp": datetime.datetime.now().isoformat()[:19], "main_file_path": key, } self._snapshots_per_main_file.setdefault(key, []) self._snapshots_per_main_file[key].append(self._current_snapshot) if msg.get("user_exception"): if not msg["user_exception"].get("message", None): msg["user_exception"]["message"] = "" self._exception_info = msg["user_exception"] self._explain_exception(msg["user_exception"]) if get_workbench().get_option("assistance.open_assistant_on_errors"): get_workbench().show_view("AssistantView", set_focus=False) else: self._exception_info = None if msg.get("filename") and os.path.exists(msg["filename"]): self.main_file_path = msg["filename"] source = read_source(msg["filename"]) self._start_program_analyses( msg["filename"], source, _get_imported_user_files(msg["filename"], source) ) else: self.main_file_path = None self._present_conclusion() def _explain_exception(self, error_info): rst = ( self._get_rst_prelude() + rst_utils.create_title( error_info["type_name"] + ": " + rst_utils.escape(error_info["message"]) ) + "\n" ) if ( error_info.get("lineno") is not None and error_info.get("filename") and os.path.exists(error_info["filename"]) ): rst += "`%s, line %d <%s>`__\n\n" % ( os.path.basename(error_info["filename"]), error_info["lineno"], self._format_file_url(error_info), ) helpers = [ helper_class(error_info) for helper_class in ( _error_helper_classes.get(error_info["type_name"], []) + _error_helper_classes["*"] ) ] best_intro = helpers[0] for helper in helpers: if helper.intro_confidence > best_intro.intro_confidence: best_intro = helper # intro if best_intro.intro_text: rst += ( ".. note::\n" + " " + best_intro.intro_text.strip().replace("\n", "\n\n ") + "\n\n" ) suggestions = [ suggestion for helper in helpers for suggestion in helper.suggestions if suggestion is not None ] suggestions = sorted(suggestions, key=lambda s: s.relevance, reverse=True) if suggestions[0].relevance > 1 or best_intro.intro_confidence > 1: relevance_threshold = 2 else: # use relevance 1 only when there is nothing better relevance_threshold = 1 suggestions = [s for s in suggestions if s.relevance >= relevance_threshold] for i, suggestion in enumerate(suggestions): rst += self._format_suggestion( suggestion, i == len(suggestions) - 1, # TODO: is it good if first is preopened? # It looks cleaner if it is not. False, # i==0 ) self._current_snapshot["exception_suggestions"] = [ dict(sug._asdict()) for sug in suggestions ] self.text.append_rst(rst) self._append_text("\n") self._current_snapshot["exception_type_name"] = error_info["type_name"] self._current_snapshot["exception_message"] = error_info["message"] self._current_snapshot["exception_file_path"] = error_info["filename"] self._current_snapshot["exception_lineno"] = error_info["lineno"] self._current_snapshot["exception_rst"] = rst # for debugging purposes def _format_suggestion(self, suggestion, last, initially_open): return ( # assuming that title is already in rst format ".. topic:: " + suggestion.title + "\n" + " :class: toggle%s%s\n" % (", open" if initially_open else "", ", tight" if not last else "") + " \n" + textwrap.indent(suggestion.body, " ") + "\n\n" ) def _append_text(self, chars, tags=()): self.text.direct_insert("end", chars, tags=tags) def _clear(self): self._accepted_warning_sets.clear() for wp in self._analyzer_instances: wp.cancel_analysis() self._analyzer_instances = [] self.text.clear() def _start_program_analyses(self, main_file_path, main_file_source, imported_file_paths): for cls in _program_analyzer_classes: analyzer = cls(self._accept_warnings) if analyzer.is_enabled(): self._analyzer_instances.append(analyzer) if not self._analyzer_instances: return self._append_text("\nAnalyzing your code ...", ("em",)) # save snapshot of current source self._current_snapshot["main_file_path"] = main_file_path self._current_snapshot["main_file_source"] = main_file_source self._current_snapshot["imported_files"] = { name: read_source(name) for name in imported_file_paths } # start the analysis for analyzer in self._analyzer_instances: analyzer.start_analysis(main_file_path, imported_file_paths) def _accept_warnings(self, analyzer, warnings): if analyzer.cancelled: return self._accepted_warning_sets.append(warnings) if len(self._accepted_warning_sets) == len(self._analyzer_instances): self._present_warnings() self._present_conclusion() def _present_conclusion(self): if not self.text.get("1.0", "end").strip(): if self.main_file_path is not None and os.path.exists(self.main_file_path): self._append_text("\n") self.text.append_rst( "The code in `%s <%s>`__ looks good.\n\n" % ( os.path.basename(self.main_file_path), self._format_file_url({"filename": self.main_file_path}), ) ) self.text.append_rst( "If it is not working as it should, " + "then consider using some general " + "`debugging techniques `__.\n\n", ("em",), ) if self.text.get("1.0", "end").strip(): self._append_feedback_link() if self._exception_info: self._append_text( "General advice on dealing with errors.\n", ("a", "python_errors_link") ) def _present_warnings(self): warnings = [w for ws in self._accepted_warning_sets for w in ws] self.text.direct_delete("end-2l linestart", "end-1c lineend") if not warnings: return if self._exception_info is None: intro = "May be ignored if you are happy with your program." else: intro = "May help you find the cause of the error." rst = ( self._get_rst_prelude() + rst_utils.create_title("Warnings") + ":remark:`%s`\n\n" % intro ) by_file = {} for warning in warnings: if warning["filename"] not in by_file: by_file[warning["filename"]] = [] if warning not in by_file[warning["filename"]]: # Pylint may give double warnings (eg. when module imports itself) by_file[warning["filename"]].append(warning) for filename in by_file: rst += "`%s <%s>`__\n\n" % ( os.path.basename(filename), self._format_file_url(dict(filename=filename)), ) file_warnings = sorted( by_file[filename], key=lambda x: (x.get("lineno", 0), -x.get("relevance", 1)) ) for i, warning in enumerate(file_warnings): rst += self._format_warning(warning, i == len(file_warnings) - 1) + "\n" rst += "\n" self.text.append_rst(rst) # save snapshot self._current_snapshot["warnings_rst"] = rst self._current_snapshot["warnings"] = warnings if get_workbench().get_option("assistance.open_assistant_on_warnings"): get_workbench().show_view("AssistantView") def _format_warning(self, warning, last): title = rst_utils.escape(warning["msg"].splitlines()[0]) if warning.get("lineno") is not None: url = self._format_file_url(warning) if warning.get("lineno"): title = "`Line %d <%s>`__ : %s" % (warning["lineno"], url, title) if warning.get("explanation_rst"): explanation_rst = warning["explanation_rst"] elif warning.get("explanation"): explanation_rst = rst_utils.escape(warning["explanation"]) else: explanation_rst = "" if warning.get("more_info_url"): explanation_rst += "\n\n`More info online <%s>`__" % warning["more_info_url"] explanation_rst = explanation_rst.strip() topic_class = "toggle" if explanation_rst else "empty" if not explanation_rst: explanation_rst = "n/a" return ( ".. topic:: %s\n" % title + " :class: " + topic_class + ("" if last else ", tight") + "\n" + " \n" + textwrap.indent(explanation_rst, " ") + "\n\n" ) def _append_feedback_link(self): self._append_text("Was it helpful or confusing?\n", ("a", "feedback_link")) def _format_file_url(self, atts): return format_file_url(atts["filename"], atts.get("lineno"), atts.get("col_offset")) def _ask_feedback(self, event=None): all_snapshots = self._snapshots_per_main_file[self._current_snapshot["main_file_path"]] # TODO: select only snapshots which are not sent yet snapshots = all_snapshots ui_utils.show_dialog(FeedbackDialog(get_workbench(), self.main_file_path, snapshots)) def _get_rst_prelude(self): return ".. default-role:: code\n\n" + ".. role:: light\n\n" + ".. role:: remark\n\n" class AssistantRstText(rst_utils.RstText): def configure_tags(self): super().configure_tags() main_font = tk.font.nametofont("TkDefaultFont") italic_font = main_font.copy() italic_font.configure(slant="italic", size=main_font.cget("size")) h1_font = main_font.copy() h1_font.configure(weight="bold", size=main_font.cget("size")) self.tag_configure("h1", font=h1_font, spacing3=0, spacing1=10) self.tag_configure("topic_title", font="TkDefaultFont") self.tag_configure("topic_body", font=italic_font, spacing1=10, lmargin1=25, lmargin2=25) self.tag_raise("sel") class Helper: def get_intro(self) -> Tuple[str, int]: raise NotImplementedError() def get_suggestions(self) -> Iterable[Suggestion]: raise NotImplementedError() class ErrorHelper(Helper): def __init__(self, error_info): # TODO: don't repeat all this for all error helpers self.error_info = error_info self.last_frame = error_info["stack"][-1] self.last_frame_ast = None if self.last_frame.source: try: self.last_frame_ast = ast.parse(self.last_frame.source, self.last_frame.filename) except SyntaxError: pass self.last_frame_module_source = None self.last_frame_module_ast = None if self.last_frame.code_name == "": self.last_frame_module_source = self.last_frame.source self.last_frame_module_ast = self.last_frame_ast elif self.last_frame.filename is not None: try: self.last_frame_module_source = read_source(self.last_frame.filename) self.last_frame_module_ast = ast.parse(self.last_frame_module_source) except Exception: pass self.intro_confidence = 1 self.intro_text = "" self.suggestions = [] class GenericErrorHelper(ErrorHelper): def __init__(self, error_info): super().__init__(error_info) self.intro_text = "No specific suggestions for this error (yet)." self.intro_confidence = 1 self.suggestions = [ Suggestion( "ask-for-specific-support", "Let Thonny developers know", "Click on the feedback link at the bottom of this panel to let Thonny developers know " + "about your problem. They may add support for " + "such cases in future Thonny versions.", 1, ) ] if error_info["message"].lower() != "invalid syntax": self.suggestions.append( Suggestion( "generic-search-the-web", "Search the web", "Try performing a web search for\n\n``Python %s: %s``" % ( self.error_info["type_name"], rst_utils.escape(self.error_info["message"].replace("\n", " ").strip()), ), 1, ) ) class ProgramAnalyzer: def __init__(self, on_completion): self.completion_handler = on_completion self.cancelled = False def is_enabled(self): return True def start_analysis(self, main_file_path, imported_file_paths): raise NotImplementedError() def cancel_analysis(self): pass class SubprocessProgramAnalyzer(ProgramAnalyzer): def __init__(self, on_completion): super().__init__(on_completion) self._proc = None def cancel_analysis(self): self.cancelled = True if self._proc is not None: self._proc.kill() class LibraryErrorHelper(ErrorHelper): """Explains exceptions, which doesn't happen in user code""" def get_intro(self): return "This error happened in library code. This may mean a bug in " def get_suggestions(self): return [] class FeedbackDialog(CommonDialog): def __init__(self, master, main_file_path, all_snapshots): super().__init__(master=master) main_frame = ttk.Frame(self) main_frame.grid(row=0, column=0, sticky="nsew") self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.main_file_path = main_file_path self.snapshots = self._select_unsent_snapshots(all_snapshots) self.title("Send feedback for Assistant") padx = 15 intro_label = ttk.Label( main_frame, text="Below are the messages Assistant gave you in response to " + ( "using the shell" if self._happened_in_shell() else "testing '" + os.path.basename(main_file_path) + "'" ) + " since " + self._get_since_str() + ".\n\n" + "In order to improve this feature, Thonny developers would love to know how " + "useful or confusing these messages were. We will only collect version " + "information and the data you enter or approve on this form.", wraplength=550, ) intro_label.grid(row=1, column=0, columnspan=3, sticky="nw", padx=padx, pady=(15, 15)) tree_label = ttk.Label( main_frame, text="Which messages were helpful (H) or confusing (C)? Click on [ ] to mark!", ) tree_label.grid(row=2, column=0, columnspan=3, sticky="nw", padx=padx, pady=(15, 0)) tree_frame = ui_utils.TreeFrame( main_frame, columns=["helpful", "confusing", "title", "group", "symbol"], displaycolumns=["helpful", "confusing", "title"], height=10, borderwidth=1, relief="groove", ) tree_frame.grid(row=3, column=0, columnspan=3, sticky="nsew", padx=padx) self.tree = tree_frame.tree self.tree.column("helpful", width=30, anchor=tk.CENTER, stretch=False) self.tree.column("confusing", width=30, anchor=tk.CENTER, stretch=False) self.tree.column("title", width=350, anchor=tk.W, stretch=True) self.tree.heading("helpful", text="H", anchor=tk.CENTER) self.tree.heading("confusing", text="C", anchor=tk.CENTER) self.tree.heading("title", text="Group / Message", anchor=tk.W) self.tree["show"] = ("headings",) self.tree.bind("<1>", self._on_tree_click, True) main_font = tk.font.nametofont("TkDefaultFont") bold_font = main_font.copy() bold_font.configure(weight="bold", size=main_font.cget("size")) self.tree.tag_configure("group", font=bold_font) self.include_thonny_id_var = tk.IntVar(value=1) include_thonny_id_check = ttk.Checkbutton( main_frame, variable=self.include_thonny_id_var, onvalue=1, offvalue=0, text="Include Thonny's installation time (allows us to group your submissions)", ) include_thonny_id_check.grid( row=4, column=0, columnspan=3, sticky="nw", padx=padx, pady=(5, 0) ) self.include_snapshots_var = tk.IntVar(value=1) include_snapshots_check = ttk.Checkbutton( main_frame, variable=self.include_snapshots_var, onvalue=1, offvalue=0, text="Include snapshots of the code and Assistant responses at each run", ) include_snapshots_check.grid( row=5, column=0, columnspan=3, sticky="nw", padx=padx, pady=(0, 0) ) comments_label = ttk.Label(main_frame, text="Any comments? Enhancement ideas?") comments_label.grid(row=6, column=0, columnspan=3, sticky="nw", padx=padx, pady=(15, 0)) self.comments_text_frame = tktextext.TextFrame( main_frame, vertical_scrollbar_style=scrollbar_style("Vertical"), horizontal_scrollbar_style=scrollbar_style("Horizontal"), horizontal_scrollbar_class=ui_utils.AutoScrollbar, wrap="word", font="TkDefaultFont", # cursor="arrow", padx=5, pady=5, height=4, borderwidth=1, relief="groove", ) self.comments_text_frame.grid(row=7, column=0, columnspan=3, sticky="nsew", padx=padx) url_font = tk.font.nametofont("TkDefaultFont").copy() url_font.configure(underline=1, size=url_font.cget("size")) preview_link = ttk.Label( main_frame, text="(Preview the data to be sent)", style="Url.TLabel", cursor="hand2", font=url_font, ) preview_link.bind("<1>", self._preview_submission_data, True) preview_link.grid(row=8, column=0, sticky="nw", padx=15, pady=15) submit_button = ttk.Button(main_frame, text="Submit", width=10, command=self._submit_data) submit_button.grid(row=8, column=0, sticky="ne", padx=0, pady=15) cancel_button = ttk.Button(main_frame, text="Cancel", width=7, command=self._close) cancel_button.grid(row=8, column=1, sticky="ne", padx=(10, 15), pady=15) self.protocol("WM_DELETE_WINDOW", self._close) self.bind("", self._close, True) main_frame.columnconfigure(0, weight=1) main_frame.rowconfigure(3, weight=3) main_frame.rowconfigure(6, weight=2) self._empty_box = "[ ]" self._checked_box = "[X]" self._populate_tree() def _happened_in_shell(self): return self.main_file_path is None or self.main_file_path.lower() == "" def _populate_tree(self): groups = {} for snap in self.snapshots: if snap.get("exception_message") and snap.get("exception_suggestions"): group = snap["exception_type_name"] groups.setdefault(group, set()) for sug in snap["exception_suggestions"]: groups[group].add((sug["symbol"], sug["title"])) # warnings group if snap.get("warnings"): group = "Warnings" groups.setdefault(group, set()) for w in snap["warnings"]: groups[group].add((w["symbol"], w["msg"])) for group in sorted(groups.keys(), key=lambda x: x.replace("Warnings", "z")): group_id = self.tree.insert("", "end", open=True, tags=("group",)) self.tree.set(group_id, "title", group) for symbol, title in sorted(groups[group], key=lambda m: m[1]): item_id = self.tree.insert("", "end") self.tree.set(item_id, "helpful", self._empty_box) self.tree.set(item_id, "confusing", self._empty_box) self.tree.set(item_id, "title", title) self.tree.set(item_id, "symbol", symbol) self.tree.set(item_id, "group", group) self.tree.see("") def _on_tree_click(self, event): item_id = self.tree.identify("item", event.x, event.y) column = self.tree.identify_column(event.x) if not item_id or not column: return value_index = int(column[1:]) - 1 values = list(self.tree.item(item_id, "values")) if values[value_index] == self._empty_box: values[value_index] = self._checked_box elif values[value_index] == self._checked_box: values[value_index] = self._empty_box else: return # update values self.tree.item(item_id, values=tuple(values)) def _preview_submission_data(self, event=None): temp_path = os.path.join( tempfile.mkdtemp(), "ThonnyAssistantFeedback_" + datetime.datetime.now().isoformat().replace(":", ".")[:19] + ".txt", ) data = self._collect_submission_data() with open(temp_path, "w", encoding="ascii") as fp: fp.write(data) if running_on_mac_os(): subprocess.Popen(["open", "-e", temp_path]) else: webbrowser.open(temp_path) def _collect_submission_data(self): tree_data = [] for iid in self.tree.get_children(): values = self.tree.item(iid, "values") tree_data.append( { "helpful": values[0] == self._checked_box, "confusing": values[1] == self._checked_box, "message": values[2], "group": values[3], "symbol": values[4], } ) submission = { "feedback_format_version": 1, "thonny_version": thonny.get_version(), "python_version": ".".join(map(str, sys.version_info[:3])), "message_feedback": tree_data, "comments": self.comments_text_frame.text.get("1.0", "end"), } try: import mypy.version submission["mypy_version"] = str(mypy.version.__version__) except ImportError: logging.exception("Could not get MyPy version") try: import pylint submission["pylint_version"] = str(pylint.__version__) except ImportError: logging.exception("Could not get Pylint version") if self.include_snapshots_var.get(): submission["snapshots"] = self.snapshots if self.include_thonny_id_var.get(): submission["thonny_timestamp"] = get_workbench().get_option( "general.configuration_creation_timestamp" ) return json.dumps(submission, indent=2) def _submit_data(self): json_data = self._collect_submission_data() compressed_data = gzip.compress(json_data.encode("ascii")) def do_work(): try: handle = urllib.request.urlopen( "https://thonny.org/store_assistant_feedback.php", data=compressed_data, timeout=10, ) return handle.read() except Exception as e: return str(e) result = ui_utils.run_with_waiting_dialog(self, do_work, description="Uploading") if result == b"OK": if self.snapshots: last_timestamp = self.snapshots[-1]["timestamp"] _last_feedback_timestamps[self.main_file_path] = last_timestamp messagebox.showinfo( "Done!", "Thank you for the feedback!\n\nLet us know again when Assistant\nhelps or confuses you!", master=self.master, ) self._close() else: messagebox.showerror( "Problem", "Something went wrong:\n%s\n\nIf you don't mind, then try again later!" % result[:1000], master=self.master, ) def _select_unsent_snapshots(self, all_snapshots): if self.main_file_path not in _last_feedback_timestamps: return all_snapshots else: return [ s for s in all_snapshots if s["timestamp"] > _last_feedback_timestamps[self.main_file_path] ] def _close(self, event=None): self.destroy() def _get_since_str(self): if not self.snapshots: assert self.main_file_path in _last_feedback_timestamps since = datetime.datetime.strptime( _last_feedback_timestamps[self.main_file_path], "%Y-%m-%dT%H:%M:%S" ) else: since = datetime.datetime.strptime(self.snapshots[0]["timestamp"], "%Y-%m-%dT%H:%M:%S") if since.date() == datetime.date.today() or ( datetime.datetime.now() - since ) <= datetime.timedelta(hours=5): since_str = since.strftime("%X") else: # date and time without yer since_str = since.strftime("%c").replace(str(datetime.date.today().year), "") # remove seconds if since_str.count(":") == 2: i = since_str.rfind(":") if ( i > 0 and len(since_str[i + 1 : i + 3]) == 2 and since_str[i + 1 : i + 3].isnumeric() ): since_str = since_str[:i] + since_str[i + 3 :] return since_str.strip() def name_similarity(a, b): # TODO: tweak the result values a = a.replace("_", "") b = b.replace("_", "") minlen = min(len(a), len(b)) if a.replace("0", "O").replace("1", "l") == b.replace("0", "O").replace("1", "l"): if minlen >= 4: return 7 else: return 6 a = a.lower() b = b.lower() if a == b: if minlen >= 4: return 7 else: return 6 if minlen <= 2: return 0 # if names differ at final isolated digits, # then they are probably different vars, even if their # distance is small (eg. location_1 and location_2) if a[-1].isdigit() and not a[-2].isdigit() and b[-1].isdigit() and not b[-2].isdigit(): return 0 # same thing with _ + single char suffixes # (eg. location_a and location_b) if a[-2] == "_" and b[-2] == "_": return 0 distance = levenshtein_damerau_distance(a, b, 5) if minlen <= 5: return max(8 - distance * 2, 0) elif minlen <= 10: return max(9 - distance * 2, 0) else: return max(10 - distance * 2, 0) def _get_imported_user_files(main_file, source=None): assert os.path.isabs(main_file) if source is None: source = read_source(main_file) try: root = ast.parse(source, main_file) except SyntaxError: return set() main_dir = os.path.dirname(main_file) module_names = set() # TODO: at the moment only considers non-package modules for node in ast.walk(root): if isinstance(node, ast.Import): for item in node.names: module_names.add(item.name) elif isinstance(node, ast.ImportFrom): module_names.add(node.module) imported_files = set() for file in {name + ext for ext in [".py", ".pyw"] for name in module_names}: possible_path = os.path.join(main_dir, file) if os.path.exists(possible_path): imported_files.add(possible_path) return imported_files # TODO: add recursion def add_program_analyzer(cls): _program_analyzer_classes.append(cls) def add_error_helper(error_type_name, helper_class): _error_helper_classes.setdefault(error_type_name, []) _error_helper_classes[error_type_name].append(helper_class) def format_file_url(filename, lineno, col_offset): s = "thonny-editor://" + rst_utils.escape(filename).replace(" ", "%20") if lineno is not None: s += "#" + str(lineno) if col_offset is not None: s += ":" + str(col_offset) return s def init(): get_workbench().set_default("assistance.open_assistant_on_errors", True) get_workbench().set_default("assistance.open_assistant_on_warnings", False) get_workbench().set_default("assistance.disabled_checks", []) get_workbench().add_view(AssistantView, _("Assistant"), "se", visible_by_default=False) thonny-3.2.7/thonny/plugins/0000755000175000017500000000000013611777205017065 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/general_config_page.py0000644000175000017500000000677713611773167023421 0ustar annamaaannamaa00000000000000import tkinter as tk from tkinter import ttk from thonny import get_workbench, languages from thonny.config_ui import ConfigurationPage class GeneralConfigurationPage(ConfigurationPage): def __init__(self, master): ConfigurationPage.__init__(self, master) self.add_checkbox( "general.single_instance", _("Allow only single Thonny instance"), row=1, columnspan=2 ) self.add_checkbox( "general.event_logging", _("Log program usage events"), row=4, columnspan=2 ) self.add_checkbox( "file.reopen_all_files", _("Reopen all files from previous session"), row=5, columnspan=2, ) self.add_checkbox( "general.disable_notification_sound", _("Disable notification sound"), row=6, columnspan=2, ) self.add_checkbox( "general.debug_mode", _("Debug mode (provides more detailed diagnostic logs)"), row=7, columnspan=2, ) # language self._language_name_var = tk.StringVar( value=languages.LANGUAGES_DICT.get(get_workbench().get_option("general.language"), "") ) self._language_label = ttk.Label(self, text=_("Language")) self._language_label.grid(row=10, column=0, sticky=tk.W, padx=(0, 10), pady=(10, 0)) self._language_combo = ttk.Combobox( self, width=20, exportselection=False, textvariable=self._language_name_var, state="readonly", height=15, values=list(languages.LANGUAGES_DICT.values()), ) self._language_combo.grid(row=10, column=1, sticky=tk.W, pady=(10, 0)) # Mode ttk.Label(self, text=_("UI mode")).grid( row=20, column=0, sticky=tk.W, padx=(0, 10), pady=(10, 0) ) self.add_combobox( "general.ui_mode", ["simple", "regular", "expert"], row=20, column=1, pady=(10, 0), width=10, ) # scaling self._scaling_label = ttk.Label(self, text=_("UI scaling factor")) self._scaling_label.grid(row=30, column=0, sticky=tk.W, padx=(0, 10), pady=(10, 0)) scalings = ["default"] + sorted({0.5, 0.75, 1.0, 1.25, 1.33, 1.5, 2.0, 2.5, 3.0, 4.0}) self.add_combobox("general.scaling", scalings, row=30, column=1, pady=(10, 0), width=10) self._font_scaling_var = get_workbench().get_variable("general.font_scaling_mode") self._font_scaling_label = ttk.Label(self, text=_("Font scaling mode")) self._font_scaling_label.grid(row=40, column=0, sticky=tk.W, padx=(0, 10), pady=(10, 0)) self.add_combobox( "general.font_scaling_mode", ["default", "extra", "automatic"], row=40, column=1, pady=(10, 0), width=10, ) reopen_label = ttk.Label( self, text=_("NB! Restart Thonny after changing these options!"), font="BoldTkDefaultFont", ) reopen_label.grid(row=100, column=0, sticky=tk.W, pady=20, columnspan=2) self.columnconfigure(1, weight=1) def apply(self): get_workbench().set_option( "general.language", languages.get_language_code_by_name(self._language_name_var.get()) ) def load_plugin() -> None: get_workbench().add_configuration_page("general", _("General"), GeneralConfigurationPage, 10) thonny-3.2.7/thonny/plugins/__init__.py0000644000175000017500000000002113611773167021172 0ustar annamaaannamaa00000000000000# Package marker thonny-3.2.7/thonny/plugins/pylint.py0000644000175000017500000037014713611773167020775 0ustar annamaaannamaa00000000000000import ast import subprocess from thonny import ui_utils, get_workbench from thonny.assistance import SubprocessProgramAnalyzer, add_program_analyzer from thonny.running import get_interpreter_for_subprocess import logging class PylintAnalyzer(SubprocessProgramAnalyzer): def is_enabled(self): return get_workbench().get_option("assistance.use_pylint") def start_analysis(self, main_file_path, imported_file_paths): relevant_symbols = { key for key in all_checks_by_symbol if all_checks_by_symbol[key]["usage"] == "warning" } if "bad-python3-import" in relevant_symbols: # https://github.com/PyCQA/pylint/issues/2453 # TODO: allow if this is fixed in current version relevant_symbols.remove("bad-python3-import") # remove user-disabled checks relevant_symbols = relevant_symbols - set( get_workbench().get_option("assistance.disabled_checks") ) ignored_modules = {"turtle"} # has dynamically generated attributes options = [ # "--rcfile=None", # TODO: make it ignore any rcfiles that can be somewhere "--persistent=n", # "--confidence=HIGH", # Leave empty to show all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED # "--disable=missing-docstring,invalid-name,trailing-whitespace,trailing-newlines,missing-final-newline,locally-disabled,suppressed-message", "--disable=all", "--enable=" + ",".join(relevant_symbols), "--ignored-modules=" + ",".join(ignored_modules), "--max-line-length=120", "--output-format=text", "--reports=n", "--msg-template={{'filename':{abspath!r}, 'lineno':{line}, 'col_offset':{column}, 'symbol':{symbol!r}, 'msg':{msg!r}, 'msg_id':{msg_id!r}, 'category' : {C!r} }}", ] # disallow unused globals only in main script """ Not good idea, because unused * imports also count as unused global vars from pylint.__pkginfo__ import numversion if not imported_file_paths and numversion >= (1, 7): # (unfortunately can't separate main script when user modules are present) options.append("--allow-global-unused-variables=no") """ self._proc = ui_utils.popen_with_ui_thread_callback( [get_interpreter_for_subprocess(), "-m", "pylint"] + options + [main_file_path] + list(imported_file_paths), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, on_completion=self._parse_and_output_warnings, ) def _parse_and_output_warnings(self, pylint_proc, out_lines, err_lines): # print("COMPL", out, err) # get rid of non-error err = ( "".join(err_lines) .replace("No config file found, using default configuration", "") .strip() ) if err: logging.getLogger("thonny").error("Pylint: " + err) warnings = [] for line in out_lines: if line.startswith("{"): try: atts = ast.literal_eval(line.strip()) except SyntaxError: logging.error("Can't parse Pylint line: " + line) continue else: check = all_checks_by_symbol[atts["symbol"]] if check.get("tho_xpln"): explanation = check["tho_xpln"] else: explanation = check["msg_xpln"] if explanation.startswith("Used when an "): explanation = "It looks like the " + explanation[(len("Used when an ")) :] elif explanation.startswith("Emitted when an "): explanation = ( "It looks like the " + explanation[(len("Emitted when an ")) :] ) elif explanation.startswith("Used when a "): explanation = "It looks like the " + explanation[(len("Used when a ")) :] elif explanation.startswith("Emitted when a "): explanation = "It looks like the " + explanation[(len("Emitted when a ")) :] elif explanation.startswith("Used when "): explanation = "It looks like " + explanation[(len("Used when ")) :] elif explanation.startswith("Emitted when "): explanation = "It looks like " + explanation[(len("Emitted when ")) :] atts["explanation"] = explanation if check.get("tho_xpln_rst"): atts["explanation_rst"] = check["tho_xpln_rst"] if atts["category"] in ("I", "F"): atts["msg"] = "INTERNAL ERROR when analyzing the code: " + atts["msg"] # atts["more_info_url"] = "http://pylint-messages.wikidot.com/messages:%s" % atts["msg_id"].lower() warnings.append(atts) self.completion_handler(self, warnings) # according to version 2.4.4 (pylint --list-msgs) all_checks = [ { "msg_id": "C0102", "msg_sym": "blacklisted-name", "msg_text": 'Black listed name "%s"', "msg_xpln": "Used when the name is listed in the black list (unauthorized names).", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0103", # TODO: usable with custom regex which allows shorter names "msg_sym": "invalid-name", "msg_text": '%s name "%s" doesn\'t conform to %s', "msg_xpln": "Used when the name doesn't conform to naming rules associated " "to its type (constant, variable, class...).", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0111", "msg_sym": "missing-docstring", "msg_text": "Missing %s docstring", "msg_xpln": "Used when a module, function, class or method has no " "docstring.Some special methods like __init__ doesn't necessary " "require a docstring.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0112", "msg_sym": "empty-docstring", "msg_text": "Empty %s docstring", "msg_xpln": "Used when a module, function, class or method has an empty " "docstring (it would be too easy ;).", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0113", "msg_sym": "unneeded-not", "msg_text": 'Consider changing "%s" to "%s"', "msg_xpln": "Used when a boolean expression contains an unneeded negation.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0114", "msg_sym": "missing-module-docstring", "msg_text": "Missing module docstring", "msg_xpln": "Used when a module has no docstring. Empty modules do not require a docstring.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0115", "msg_sym": "missing-class-docstring", "msg_text": "Missing class docstring", "msg_xpln": "Used when a class has no docstring. Even an empty class must have a docstring.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0116", "msg_sym": "missing-function-docstring", "msg_text": "Missing function or method docstring", "msg_xpln": "Used when a function or method has no docstring. Some special methods like __init__ do not require a docstring.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0121", # TODO: find out what it means. NB! Other message in wikidot "msg_sym": "singleton-comparison", "msg_text": "Comparison to %s should be %s", "msg_xpln": "Used when an expression is compared to singleton values like " "True, False or None.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0122", "msg_sym": "misplaced-comparison-constant", "msg_text": "Comparison should be %s", "msg_xpln": "Used when the constant is placed on the left side of a " "comparison. It is usually clearer in intent to place it in the " "right hand side of the comparison.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0123", "msg_sym": "unidiomatic-typecheck", "msg_text": "Using type() instead of isinstance() for a typecheck.", "msg_xpln": "The idiomatic way to perform an explicit typecheck in Python is " "to use isinstance(x, Y) rather than type(x) == Y, type(x) is Y. " "Though there are unusual situations where these give different " "results.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0200", "msg_sym": "consider-using-enumerate", "msg_text": "Consider using enumerate instead of iterating with range and len", "msg_xpln": "Emitted when code that iterates with range and len is " "encountered. Such code can be simplified by using the enumerate " "builtin.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0201", "msg_sym": "consider-iterating-dictionary", "msg_text": "Consider iterating the dictionary directly instead of calling .keys()", "msg_xpln": "Emitted when the keys of a dictionary are iterated through the " ".keys() method. It is enough to just iterate through the " 'dictionary itself, as in "for key in dictionary".', "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0202", "msg_sym": "bad-classmethod-argument", "msg_text": "Class method %s should have %s as first argument", "msg_xpln": "Used when a class method has a first argument named differently " "than the value specified in valid-classmethod-first-arg option " '(default to "cls"), recommended to easily differentiate them ' "from regular instance methods.", "tho_xpln": "", "usage": "enhancement", }, # TODO: simplify message { "msg_id": "C0203", "msg_sym": "bad-mcs-method-argument", "msg_text": "Metaclass method %s should have %s as first argument", "msg_xpln": "Used when a metaclass method has a first argument named " "differently than the value specified in " 'valid-classmethod-first-arg option (default to "cls"), ' "recommended to easily differentiate them from regular instance " "methods.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0204", "msg_sym": "bad-mcs-classmethod-argument", "msg_text": "Metaclass class method %s should have %s as first argument", "msg_xpln": "Used when a metaclass class method has a first argument named " "differently than the value specified in " "valid-metaclass-classmethod-first-arg option (default to " '"mcs"), recommended to easily differentiate them from regular ' "instance methods.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0205", "msg_sym": "single-string-used-for-slots", "msg_text": "Class __slots__ should be a non-string iterable", "msg_xpln": "Used when a class __slots__ is a simple string, rather than an iterable.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "C0301", # option: max-line-length, 100 by default "msg_sym": "line-too-long", "msg_text": "Line too long (%s/%s)", "msg_xpln": "Used when a line is longer than a given number of characters.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0302", "msg_sym": "too-many-lines", "msg_text": "Too many lines in module (%s/%s)", "msg_xpln": "Used when a module has too many lines, reducing its readability.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0303", "msg_sym": "trailing-whitespace", "msg_text": "Trailing whitespace", "msg_xpln": "Used when there is whitespace between the end of a line and the newline.", "tho_xpln": "", "usage": "skip", # TODO: implement automatic strip }, { "msg_id": "C0304", "msg_sym": "missing-final-newline", "msg_text": "Final newline missing", "msg_xpln": "Used when the last line in a file is missing a newline.", "tho_xpln": "", "usage": "skip", # TODO: manage it automatically }, { "msg_id": "C0305", "msg_sym": "trailing-newlines", "msg_text": "Trailing newlines", "msg_xpln": "Used when there are trailing blank lines in a file.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0321", "msg_sym": "multiple-statements", "msg_text": "More than one statement on a single line", "msg_xpln": "Used when more than on statement are found on the same line.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0325", "msg_sym": "superfluous-parens", "msg_text": "Unnecessary parens after %r keyword", "msg_xpln": "Used when a single item in parentheses follows an if, for, or " "other keyword.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "C0326", "msg_sym": "bad-whitespace", "msg_text": "%s space %s %s %s", "msg_xpln": "Used when a wrong number of spaces is used around an operator, " "bracket or block opener.", "tho_xpln": "", "usage": "style", }, { "msg_id": "C0327", "msg_sym": "mixed-line-endings", "msg_text": "Mixed line endings LF and CRLF", "msg_xpln": "Used when there are mixed (LF and CRLF) newline signs in a file.", "tho_xpln": "", "usage": "skip", # TODO: visualize it }, { "msg_id": "C0328", "msg_sym": "unexpected-line-ending-format", "msg_text": "Unexpected line ending format. There is '%s' while it should be '%s'.", "msg_xpln": "Used when there is different newline than expected.", "tho_xpln": "", "usage": "skip", # TODO: visualize it }, { "msg_id": "C0330", "msg_sym": "bad-continuation", "msg_text": "Wrong %s indentation%s%s.", "msg_xpln": "TODO", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0401", "msg_sym": "wrong-spelling-in-comment", "msg_text": "Wrong spelling of a word '%s' in a comment:", "msg_xpln": "Used when a word in comment is not spelled correctly.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0402", "msg_sym": "wrong-spelling-in-docstring", "msg_text": "Wrong spelling of a word '%s' in a docstring:", "msg_xpln": "Used when a word in docstring is not spelled correctly.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0403", "msg_sym": "invalid-characters-in-docstring", "msg_text": "Invalid characters %r in a docstring", "msg_xpln": "Used when a word in docstring cannot be checked by enchant.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C0410", "msg_sym": "multiple-imports", "msg_text": "Multiple imports on one line (%s)", "msg_xpln": "Used when import statement importing multiple modules is detected.", "tho_xpln": "", "usage": "style", }, { "msg_id": "C0411", "msg_sym": "wrong-import-order", "msg_text": "%s should be placed before %s", "msg_xpln": "Used when PEP8 import order is not respected (standard imports " "first, then third-party libraries, then local imports)", "tho_xpln": "", "usage": "style", }, { "msg_id": "C0412", "msg_sym": "ungrouped-imports", "msg_text": "Imports from package %s are not grouped", "msg_xpln": "Used when imports are not grouped by packages", "tho_xpln": "", "usage": "style", }, { "msg_id": "C0413", "msg_sym": "wrong-import-position", "msg_text": 'Import "%s" should be placed at the top of the module', "msg_xpln": "Used when code and imports are mixed", "tho_xpln": "", "usage": "style", }, { "msg_id": "C0414", "msg_sym": "useless-import-alias", "msg_text": "Import alias does not rename original package", "msg_xpln": "Used when an import alias is same as original package.e.g using " "import numpy as numpy instead of import numpy as np", "tho_xpln": "Used when an import alias is same as original package. e.g using " "import numpy as numpy instead of import numpy as np " "or e.g using import os.path as path instead of from os import path.", "usage": "enhancement", }, { "msg_id": "C0415", "msg_sym": "import-outside-toplevel", "msg_text": "Import outside toplevel (%s)", "msg_xpln": "Used when an import statement is used anywhere other than the module toplevel." "Move this import to the top of the file.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "C1801", "msg_sym": "len-as-condition", "msg_text": "Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty", "msg_xpln": "Used when Pylint detects that len(sequence) is being used without explicit" "comparison inside a condition to determine if a sequence is empty. Instead of" "coercing the length to a boolean, either rely on the fact that empty sequences" "are false or compare the length against a scalar.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "E0001", "msg_sym": "syntax-error", "msg_text": "", "msg_xpln": "Used when a syntax error is raised for a module.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0011", "msg_sym": "unrecognized-inline-option", "msg_text": "Unrecognized file option %r", "msg_xpln": "Used when an unknown inline option is encountered.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0012", "msg_sym": "bad-option-value", "msg_text": "Bad option value %r", "msg_xpln": "Used when a bad value for an inline option is encountered.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0100", "msg_sym": "init-is-generator", "msg_text": "__init__ method is a generator", "msg_xpln": "Used when the special class method __init__ is turned into a " "generator by a yield in its body.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0101", "msg_sym": "return-in-init", "msg_text": "Explicit return in __init__", "msg_xpln": "Used when the special class method __init__ has an explicit return value.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0102", "msg_sym": "function-redefined", "msg_text": "%s already defined line %s", "msg_xpln": "Used when a function / class / method is redefined.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0103", # Will be reported by Python "msg_sym": "not-in-loop", "msg_text": "%r not properly in loop", "msg_xpln": "Used when break or continue keywords are used outside a loop.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0104", # Will be reported by Python "msg_sym": "return-outside-function", "msg_text": "Return outside function", "msg_xpln": 'Used when a "return" statement is found outside a function or ' "method.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0105", # Will be reported by Python "msg_sym": "yield-outside-function", "msg_text": "Yield outside function", "msg_xpln": 'Used when a "yield" statement is found outside a function or ' "method.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0107", "msg_sym": "nonexistent-operator", "msg_text": "Use of the non-existent %s operator", "msg_xpln": "Used when you attempt to use the C-style pre-increment or " "pre-decrement operator -- and ++, which doesn't exist in " "Python.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0108", # Will be reported by Python "msg_sym": "duplicate-argument-name", "msg_text": "Duplicate argument name %s in function definition", "msg_xpln": "Duplicate argument names in function definitions are syntax errors.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0110", "msg_sym": "abstract-class-instantiated", "msg_text": "Abstract class %r with abstract methods instantiated", "msg_xpln": "Used when an abstract class with `abc.ABCMeta` as metaclass has " "abstract methods and is instantiated.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0111", "msg_sym": "bad-reversed-sequence", "msg_text": "The first reversed() argument is not a sequence", "msg_xpln": "Used when the first argument to reversed() builtin isn't a " "sequence (does not implement __reversed__, nor __getitem__ and " "__len__", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0112", # Will be reported by Python "msg_sym": "too-many-star-expressions", "msg_text": "More than one starred expression in assignment", "msg_xpln": "Emitted when there are more than one starred expressions (`*x`) " "in an assignment. This is a SyntaxError.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0113", # Better message than in Python "msg_sym": "invalid-star-assignment-target", "msg_text": "Starred assignment target must be in a list or tuple", "msg_xpln": "Emitted when a star expression is used as a starred assignment target.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0114", # ???? "msg_sym": "star-needs-assignment-target", "msg_text": "Can use starred expression only in assignment target", "msg_xpln": "Emitted when a star expression is not used in an assignment target.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0115", # better message than in Python "msg_sym": "nonlocal-and-global", "msg_text": "Name %r is nonlocal and global", "msg_xpln": "Emitted when a name is both nonlocal and global.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0116", # Is reported in Python "msg_sym": "continue-in-finally", "msg_text": "'continue' not supported inside 'finally' clause", "msg_xpln": "Emitted when the `continue` keyword is found inside a finally " "clause, which is a SyntaxError.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0117", # reported by Python "msg_sym": "nonlocal-without-binding", "msg_text": "nonlocal name %s found without binding", "msg_xpln": "Emitted when a nonlocal variable does not have an attached name " "somewhere in the parent scopes", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0118", # Reported by Python "msg_sym": "used-prior-global-declaration", "msg_text": "Name %r is used prior to global declaration", "msg_xpln": "Emitted when a name is used prior a global declaration, which " "results in an error since Python 3.6. This message can't be " "emitted when using Python < 3.6.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0119", "msg_sym": "misplaced-format-function", "msg_text": "format function is not called on str", "msg_xpln": "Emitted when format function is not called on str object. e.g " 'doing print("value: {}").format(123) instead of print("value: ' '{}".format(123)). This might not be what the user intended to ' "do.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0202", "msg_sym": "method-hidden", "msg_text": "An attribute defined in %s line %s hides this method", "msg_xpln": "Used when a class defines a method which is hidden by an " "instance attribute from an ancestor class or set by some client " "code.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0203", "msg_sym": "access-member-before-definition", "msg_text": "Access to member %r before its definition line %s", "msg_xpln": "Used when an instance member is accessed before it's actually assigned.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0211", "msg_sym": "no-method-argument", "msg_text": "Method has no argument", "msg_xpln": "Used when a method which should have the bound instance as " "first argument has no argument defined.", "tho_xpln": 'Methods should have "self" as first argument.', "usage": "warning", }, { "msg_id": "E0213", "msg_sym": "no-self-argument", "msg_text": 'Method should have "self" as first argument', "msg_xpln": 'Used when a method has an attribute different the "self" as ' "first argument. This is considered as an error since this is a " "so common convention that you shouldn't break it!", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0236", "msg_sym": "invalid-slots-object", "msg_text": "Invalid object %r in __slots__, must contain only non empty strings", "msg_xpln": "Used when an invalid (non-string) object occurs in __slots__.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0237", "msg_sym": "assigning-non-slot", "msg_text": "Assigning to attribute %r not defined in class slots", "msg_xpln": "Used when assigning to an attribute not defined in the class slots.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0238", "msg_sym": "invalid-slots", "msg_text": "Invalid __slots__ object", "msg_xpln": "Used when an invalid __slots__ is found in class. Only a " "string, an iterable or a sequence is permitted.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0239", "msg_sym": "inherit-non-class", "msg_text": "Inheriting %r, which is not a class.", "msg_xpln": "Used when a class inherits from something which is not a class.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0240", "msg_sym": "inconsistent-mro", "msg_text": "Inconsistent method resolution order for class %r", "msg_xpln": "Used when a class has an inconsistent method resolution order.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0241", "msg_sym": "duplicate-bases", "msg_text": "Duplicate bases for class %r", "msg_xpln": "Used when a class has duplicate bases.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0242", "msg_sym": "class-variable-slots-conflict", "msg_text": "Value %r in slots conflicts with class variable", "msg_xpln": "Used when a value in __slots__ conflicts with a class variable, property or method.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0301", "msg_sym": "non-iterator-returned", "msg_text": "__iter__ returns non-iterator", "msg_xpln": "Used when an __iter__ method returns something which is not an " "iterable (i.e. has no `__next__` method)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0302", "msg_sym": "unexpected-special-method-signature", "msg_text": "The special method %r expects %s param(s), %d %s given", "msg_xpln": "Emitted when a special method was defined with an invalid " "number of parameters. If it has too few or too many, it might " "not work at all.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0303", "msg_sym": "invalid-length-returned", "msg_text": "__len__ does not return non-negative integer", "msg_xpln": "Used when a __len__ method returns something which is not a " "non-negative integer", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0401", "msg_sym": "import-error", "msg_text": "Unable to import %s", "msg_xpln": "Used when pylint has been unable to import a module.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E0402", "msg_sym": "relative-beyond-top-level", "msg_text": "Attempted relative import beyond top-level package", "msg_xpln": "Used when a relative import tries to access too many levels in " "the current package.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0601", "msg_sym": "used-before-assignment", "msg_text": "Using variable %r before assignment", "msg_xpln": "Used when a local variable is accessed before its assignment.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0602", "msg_sym": "undefined-variable", "msg_text": "Undefined variable %r", "msg_xpln": "Used when an undefined variable is accessed.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0603", "msg_sym": "undefined-all-variable", "msg_text": "Undefined variable name %r in __all__", "msg_xpln": "Used when an undefined variable name is referenced in __all__.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0604", "msg_sym": "invalid-all-object", "msg_text": "Invalid object %r in __all__, must contain only strings", "msg_xpln": "Used when an invalid (non-string) object occurs in __all__.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0611", "msg_sym": "no-name-in-module", "msg_text": "No name %r in module %r", "msg_xpln": "Used when a name cannot be found in a module.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "W0632", # used to be an error "msg_sym": "unbalanced-tuple-unpacking", "msg_text": "Possible unbalanced tuple unpacking with sequence%s: left side " "has %d label(s), right side has %d value(s)", "msg_xpln": "Used when there is an unbalanced tuple unpacking in assignment", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0632", # is warning in later versions "msg_sym": "unbalanced-tuple-unpacking", "msg_text": "Possible unbalanced tuple unpacking with sequence%s: left side " "has %d label(s), right side has %d value(s)", "msg_xpln": "Used when there is an unbalanced tuple unpacking in assignment", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0633", # Reported by Python and MyPy "msg_sym": "unpacking-non-sequence", "msg_text": "Attempting to unpack a non-sequence%s", "msg_xpln": "Used when something which is not a sequence is used in an " "unpack assignment", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0701", "msg_sym": "bad-except-order", "msg_text": "Bad except clauses order (%s)", "msg_xpln": "Used when except clauses are not in the correct order (from the " "more specific to the more generic). If you don't fix the order, " "some exceptions may not be caught by the most specific handler.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0702", # reported by Python and MyPy "msg_sym": "raising-bad-type", "msg_text": "Raising %s while only classes or instances are allowed", "msg_xpln": "Used when something which is neither a class, an instance or a " "string is raised (i.e. a `TypeError` will be raised).", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0703", # reported by Python and MyPy "msg_sym": "bad-exception-context", "msg_text": "Exception context set to something which is not an exception, nor None", "msg_xpln": 'Used when using the syntax "raise ... from ...", where the ' "exception context is not an exception, nor None.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0704", "msg_sym": "misplaced-bare-raise", "msg_text": "The raise statement is not inside an except clause", "msg_xpln": "Used when a bare raise is not used inside an except clause. " "This generates an error, since there are no active exceptions " "to be reraised. An exception to this rule is represented by a " "bare raise inside a finally clause, which might work, as long " "as an exception is raised inside the try block, but it is " "nevertheless a code smell that must not be relied upon.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0710", "msg_sym": "raising-non-exception", "msg_text": "Raising a new style class which doesn't inherit from BaseException", "msg_xpln": "Used when a new style class which doesn't inherit from " "BaseException is raised.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E0711", "msg_sym": "notimplemented-raised", "msg_text": "NotImplemented raised - should raise NotImplementedError", "msg_xpln": "Used when NotImplemented is raised instead of NotImplementedError", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E0712", "msg_sym": "catching-non-exception", "msg_text": "Catching an exception which doesn't inherit from Exception: %s", "msg_xpln": "Used when a class which doesn't inherit from Exception is used " "as an exception in an except clause.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1003", "msg_sym": "bad-super-call", "msg_text": "Bad first argument %r given to super()", "msg_xpln": "Used when another argument than the current class is given as " "first argument of the super builtin.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1101", "msg_sym": "no-member", "msg_text": "%s %r has no %r member%s", "msg_xpln": "Used when a variable is accessed for an unexistent member.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1102", "msg_sym": "not-callable", "msg_text": "%s is not callable", "msg_xpln": "Used when an object being called has been inferred to a non " "callable object.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1111", "msg_sym": "assignment-from-no-return", "msg_text": "Assigning to function call which doesn't return", # TODO: to => from "msg_xpln": "Used when an assignment is done on a function call but the " "inferred function doesn't return anything.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1120", "msg_sym": "no-value-for-parameter", "msg_text": "No value for argument %s in %s call", "msg_xpln": "Used when a function call passes too few arguments.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1121", "msg_sym": "too-many-function-args", "msg_text": "Too many positional arguments for %s call", "msg_xpln": "Used when a function call passes too many positional arguments.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1123", "msg_sym": "unexpected-keyword-arg", "msg_text": "Unexpected keyword argument %r in %s call", "msg_xpln": "Used when a function call passes a keyword argument that " "doesn't correspond to one of the function's parameter names.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1124", "msg_sym": "redundant-keyword-arg", "msg_text": "Argument %r passed by position and keyword in %s call", "msg_xpln": "Used when a function call would result in assigning multiple " "values to a function parameter, one value from a positional " "argument and one from a keyword argument.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1125", "msg_sym": "missing-kwoa", "msg_text": "Missing mandatory keyword argument %r in %s call", "msg_xpln": "Used when a function call does not pass a mandatory keyword-only argument.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1126", "msg_sym": "invalid-sequence-index", "msg_text": "Sequence index is not an int, slice, or instance with __index__", "msg_xpln": "Used when a sequence type is indexed with an invalid type. " "Valid types are ints, slices, and objects with an __index__ " "method.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1127", "msg_sym": "invalid-slice-index", "msg_text": "Slice index is not an int, None, or instance with __index__", "msg_xpln": "Used when a slice index is not an integer, None, or an object " "with an __index__ method.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1128", "msg_sym": "assignment-from-none", "msg_text": "Assigning to function call which only returns None", "msg_xpln": "Used when an assignment is done on a function call but the " "inferred function returns nothing but None.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1129", "msg_sym": "not-context-manager", "msg_text": "Context manager '%s' doesn't implement __enter__ and __exit__.", "msg_xpln": "Used when an instance in a with statement doesn't implement the " "context manager protocol(__enter__/__exit__).", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1130", "msg_sym": "invalid-unary-operand-type", "msg_text": "", "msg_xpln": "Emitted when a unary operand is used on an object which does " "not support this type of operation.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1131", "msg_sym": "unsupported-binary-operation", "msg_text": "", "msg_xpln": "Emitted when a binary arithmetic operation between two operands " "is not supported.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1132", "msg_sym": "repeated-keyword", "msg_text": "Got multiple values for keyword argument %r in function call", "msg_xpln": "Emitted when a function call got multiple values for a keyword.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1133", "msg_sym": "not-an-iterable", "msg_text": "Non-iterable value %s is used in an iterating context", "msg_xpln": "Used when a non-iterable value is used in place where iterable is expected", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1134", "msg_sym": "not-a-mapping", "msg_text": "Non-mapping value %s is used in a mapping context", "msg_xpln": "Used when a non-mapping value is used in place where mapping is expected", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1135", "msg_sym": "unsupported-membership-test", "msg_text": "Value '%s' doesn't support membership test", "msg_xpln": "Emitted when an instance in membership test expression doesn't " "implement membership protocol " "(__contains__/__iter__/__getitem__).", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1136", "msg_sym": "unsubscriptable-object", "msg_text": "Value '%s' is unsubscriptable", "msg_xpln": "Emitted when a subscripted value doesn't support subscription " "(i.e. doesn't define __getitem__ method).", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1137", "msg_sym": "unsupported-assignment-operation", "msg_text": "%r does not support item assignment", "msg_xpln": "Emitted when an object does not support item assignment (i.e. " "doesn't define __setitem__ method).", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1138", "msg_sym": "unsupported-delete-operation", "msg_text": "%r does not support item deletion", "msg_xpln": "Emitted when an object does not support item deletion (i.e. " "doesn't define __delitem__ method).", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1139", "msg_sym": "invalid-metaclass", "msg_text": "Invalid metaclass %r used", "msg_xpln": "Emitted whenever we can detect that a class is using, as a " "metaclass, something which might be invalid for using as a " "metaclass.", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1140", "msg_sym": "unhashable-dict-key", "msg_text": "Dict key is unhashable", "msg_xpln": "Emitted when a dict key is not hashable (i.e. doesn't define " "__hash__ method).", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1141", "msg_sym": "dict-iter-missing-items", "msg_text": "Unpacking a dictionary in iteration without calling .items()", "msg_xpln": "Emitted when trying to iterate through a dict without calling .items()", "tho_xpln": "", "usage": "typing", }, { "msg_id": "E1200", "msg_sym": "logging-unsupported-format", "msg_text": "Unsupported logging format character %r (%#02x) at index %d", "msg_xpln": "Used when an unsupported format character is used in a logging " "statement format string.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1201", "msg_sym": "logging-format-truncated", "msg_text": "Logging format string ends in middle of conversion specifier", "msg_xpln": "Used when a logging statement format string terminates before " "the end of a conversion specifier.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1205", "msg_sym": "logging-too-many-args", "msg_text": "Too many arguments for logging format string", "msg_xpln": "Used when a logging format string is given too many arguments.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1206", "msg_sym": "logging-too-few-args", "msg_text": "Not enough arguments for logging format string", "msg_xpln": "Used when a logging format string is given too few arguments.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1300", "msg_sym": "bad-format-character", "msg_text": "Unsupported format character %r (%#02x) at index %d", "msg_xpln": "Used when an unsupported format character is used in a format string.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1301", "msg_sym": "truncated-format-string", "msg_text": "Format string ends in middle of conversion specifier", "msg_xpln": "Used when a format string terminates before the end of a " "conversion specifier.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1302", "msg_sym": "mixed-format-string", "msg_text": "Mixing named and unnamed conversion specifiers in format string", "msg_xpln": "Used when a format string contains both named (e.g. '%(foo)d') " "and unnamed (e.g. '%d') conversion specifiers. This is also " "used when a named conversion specifier contains * for the " "minimum field width and/or precision.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1303", "msg_sym": "format-needs-mapping", "msg_text": "Expected mapping for format string, not %s", "msg_xpln": "Used when a format string that uses named conversion specifiers " "is used with an argument that is not a mapping.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1304", "msg_sym": "missing-format-string-key", "msg_text": "Missing key %r in format string dictionary", "msg_xpln": "Used when a format string that uses named conversion specifiers " "is used with a dictionary that doesn't contain all the keys " "required by the format string.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1305", "msg_sym": "too-many-format-args", "msg_text": "Too many arguments for format string", "msg_xpln": "Used when a format string that uses unnamed conversion " "specifiers is given too many arguments.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1306", "msg_sym": "too-few-format-args", "msg_text": "Not enough arguments for format string", "msg_xpln": "Used when a format string that uses unnamed conversion " "specifiers is given too few arguments", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1310", "msg_sym": "bad-str-strip-call", "msg_text": "Suspicious argument in %s.%s call", "msg_xpln": "The argument to a str.{l,r,}strip call contains a duplicate character,", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1507", "msg_sym": "invalid-envvar-value", "msg_text": "%s does not support %s type argument", "msg_xpln": "Env manipulation functions support only string type arguments. " "See https://docs.python.org/3/library/os.html#os.getenv.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1601", "msg_sym": "print-statement", "msg_text": "print statement used", "msg_xpln": "Used when a print statement is used (`print` is a function in Python 3)", "tho_xpln": "", "usage": "skip", }, # Nice SyntaxError from Python { "msg_id": "E1602", "msg_sym": "parameter-unpacking", "msg_text": "Parameter unpacking specified", "msg_xpln": "Used when parameter unpacking is specified for a function (Python 3 doesn't allow it)", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E1603", "msg_sym": "unpacking-in-except", "msg_text": "Implicit unpacking of exceptions is not supported in Python 3", "msg_xpln": "Python3 will not allow implicit unpacking of exceptions in " "except clauses. See http://www.python.org/dev/peps/pep-3110/", "tho_xpln": "", "usage": "skip", }, { "msg_id": "E1604", "msg_sym": "old-raise-syntax", "msg_text": "Use raise ErrorClass(args) instead of raise ErrorClass, args.", "msg_xpln": "Used when the alternate raise syntax 'raise foo, bar' is used " "instead of 'raise foo(bar)'.", "tho_xpln": "", "usage": "skip", }, # Looks like this doesn't work { "msg_id": "E1605", "msg_sym": "backtick", "msg_text": "Use of the `` operator", "msg_xpln": 'Used when the deprecated "``" (backtick) operator is used ' "instead of the str() function.", "tho_xpln": "", "usage": "skip", }, # Looks like this doesn't work { "msg_id": "E1700", "msg_sym": "yield-inside-async-function", "msg_text": "Yield inside async function", "msg_xpln": "Used when an `yield` or `yield from` statement is found inside " "an async function.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "E1701", "msg_sym": "not-async-context-manager", "msg_text": "Async context manager '%s' doesn't implement __aenter__ and __aexit__.", "msg_xpln": "Used when an async context manager is used with an object that " "does not implement the async context management protocol.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "F0001", "msg_sym": "fatal", "msg_text": "", "msg_xpln": "Used when an error occurred preventing the analysis of a module " "(unable to find it for instance).", "tho_xpln": "Program analyzer internal error. Used when an error occurred preventing the analysis of a module " "(unable to find it for instance).", "usage": "warning", }, { "msg_id": "F0002", "msg_sym": "astroid-error", "msg_text": "%s: %s", "msg_xpln": "Used when an unexpected error occurred while building the " "Astroid representation. This is usually accompanied by a " "traceback. Please report such errors !", "tho_xpln": "Program analyzer internal error. Used when an unexpected error occurred while building the " "Astroid representation. This is usually accompanied by a " "traceback. Please report such errors !", "usage": "warning", }, { "msg_id": "F0010", "msg_sym": "parse-error", "msg_text": "error while code parsing: %s", "msg_xpln": "Used when an exception occurred while building the Astroid " "representation which could be handled by astroid.", "tho_xpln": "Program analyzer internal error. Used when an exception occurred while building the Astroid " "representation which could be handled by astroid.", "usage": "warning", }, { "msg_id": "F0202", "msg_sym": "method-check-failed", "msg_text": "Unable to check methods signature (%s / %s)", "msg_xpln": "Used when Pylint has been unable to check methods signature " "compatibility for an unexpected reason. Please report this kind " "if you don't make sense of it.", "tho_xpln": "Program analyzer internal error. Used when Pylint has been unable to check methods signature " "compatibility for an unexpected reason. Please report this kind " "if you don't make sense of it.", "usage": "warning", }, { "msg_id": "I0001", "msg_sym": "raw-checker-failed", "msg_text": "Unable to run raw checkers on built-in module %s", "msg_xpln": "Used to inform that a built-in module has not been checked " "using the raw checkers.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "I0010", "msg_sym": "bad-inline-option", "msg_text": "Unable to consider inline option %r", "msg_xpln": "Used when an inline option is either badly formatted or can't " "be used inside modules.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "I0011", "msg_sym": "locally-disabled", "msg_text": "Locally disabling %s (%s)", "msg_xpln": "Used when an inline option disables a message or a messages category.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "I0012", "msg_sym": "locally-enabled", "msg_text": "Locally enabling %s (%s)", "msg_xpln": "Used when an inline option enables a message or a messages category.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "I0013", "msg_sym": "file-ignored", "msg_text": "Ignoring entire file", "msg_xpln": "Used to inform that the file will not be checked", "tho_xpln": "", "usage": "skip", }, { "msg_id": "I0020", "msg_sym": "suppressed-message", "msg_text": "Suppressed %s (from line %d)", "msg_xpln": "A message was triggered on a line, but suppressed explicitly by " "a disable= comment in the file. This message is not generated " "for messages that are ignored due to configuration settings.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "I0021", "msg_sym": "useless-suppression", "msg_text": "Useless suppression of %s", "msg_xpln": "Reported when a message is explicitly disabled for a line or a " "block of code, but never triggered.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "I0022", "msg_sym": "deprecated-pragma", "msg_text": 'Pragma "%s" is deprecated, use "%s" instead', "msg_xpln": "Some inline pylint options have been renamed or reworked, only " "the most recent form should be used.", "tho_xpln": "", "usage": "style", }, { "msg_id": "I0023", "msg_sym": "use-symbolic-message-instead", "msg_text": "", "msg_xpln": "Used when a message is enabled or disabled by id.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "I1101", "msg_sym": "c-extension-no-member", "msg_text": "%s %r has no %r member%s, but source is unavailable. Consider " "adding this module to extension-pkg-whitelist if you want to " "perform analysis based on run-time introspection of living " "objects.", "msg_xpln": "Used when a variable is accessed for non-existent member of C " "extension. Due to unavailability of source static analysis is " "impossible, but it may be performed by introspecting living " "objects in run-time.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "R0123", "msg_sym": "literal-comparison", "msg_text": "Comparison to literal", "msg_xpln": "Used when comparing an object to a literal, which is usually " "what you do not want to do, since you can compare to a " "different literal than what was expected altogether.", "tho_xpln": 'Are you sure you want to compare with "is"/"is not" instead of "=="/"!=" ?', "usage": "warning", }, { "msg_id": "R0124", "msg_sym": "comparison-with-itself", "msg_text": "Redundant comparison - %s", "msg_xpln": "Used when something is compared against itself.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "R0201", "msg_sym": "no-self-use", "msg_text": "Method could be a function", "msg_xpln": "Used when a method doesn't use its bound instance, and so could " "be written as a function.", "tho_xpln": "", "usage": "style", }, { "msg_id": "R0202", "msg_sym": "no-classmethod-decorator", "msg_text": "Consider using a decorator instead of calling classmethod", "msg_xpln": "Used when a class method is defined without using the decorator syntax.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R0203", "msg_sym": "no-staticmethod-decorator", "msg_text": "Consider using a decorator instead of calling staticmethod", "msg_xpln": "Used when a static method is defined without using the decorator syntax.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R0205", "msg_sym": "useless-object-inheritance", "msg_text": "Class %r inherits from object, can be safely removed from bases in python3", "msg_xpln": "Used when a class inherit from object, which under python3 is implicit, hence " "can be safely removed from bases.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R0206", "msg_sym": "property-with-parameters", "msg_text": "Cannot have defined parameters for properties", "msg_xpln": "Used when we detect that a property also has parameters, which are useless, " "given that properties cannot be called with additional arguments.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R0401", "msg_sym": "cyclic-import", "msg_text": "Cyclic import (%s)", "msg_xpln": "Used when a cyclic import between two or more modules is detected.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "R0801", "msg_sym": "duplicate-code", "msg_text": "Similar lines in %s files", "msg_xpln": "Indicates that a set of similar lines has been detected among " "multiple file. This usually means that the code should be " "refactored to avoid this duplication.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R0901", "msg_sym": "too-many-ancestors", "msg_text": "Too many ancestors (%s/%s)", "msg_xpln": "Used when class has too many parent classes, try to reduce this " "to get a simpler (and so easier to use) class.", "tho_xpln": "", "usage": "style", }, { "msg_id": "R0902", "msg_sym": "too-many-instance-attributes", "msg_text": "Too many instance attributes (%s/%s)", "msg_xpln": "Used when class has too many instance attributes, try to reduce " "this to get a simpler (and so easier to use) class.", "tho_xpln": "", "usage": "style", }, { "msg_id": "R0903", "msg_sym": "too-few-public-methods", "msg_text": "Too few public methods (%s/%s)", "msg_xpln": "Used when class has too few public methods, so be sure it's " "really worth it.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "R0904", "msg_sym": "too-many-public-methods", "msg_text": "Too many public methods (%s/%s)", "msg_xpln": "Used when class has too many public methods, try to reduce this " "to get a simpler (and so easier to use) class.", "tho_xpln": "", "usage": "style", }, { "msg_id": "R0911", "msg_sym": "too-many-return-statements", "msg_text": "Too many return statements (%s/%s)", "msg_xpln": "Used when a function or method has too many return statement, " "making it hard to follow.", "tho_xpln": "", "usage": "style", }, { "msg_id": "R0912", "msg_sym": "too-many-branches", "msg_text": "Too many branches (%s/%s)", "msg_xpln": "Used when a function or method has too many branches, making it " "hard to follow.", "tho_xpln": "", "usage": "style", }, { "msg_id": "R0913", "msg_sym": "too-many-arguments", "msg_text": "Too many arguments (%s/%s)", "msg_xpln": "Used when a function or method takes too many arguments.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R0914", "msg_sym": "too-many-locals", "msg_text": "Too many local variables (%s/%s)", "msg_xpln": "Used when a function or method has too many local variables.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R0915", "msg_sym": "too-many-statements", "msg_text": "Too many statements (%s/%s)", "msg_xpln": "Used when a function or method has too many statements. You " "should then split it in smaller functions / methods.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R0916", "msg_sym": "too-many-boolean-expressions", "msg_text": "Too many boolean expressions in if statement (%s/%s)", "msg_xpln": "Used when an if statement contains too many boolean expressions.", "tho_xpln": "Consider simplifying the expression with helper variables or functions.", "usage": "enhancement", }, { "msg_id": "R1701", "msg_sym": "consider-merging-isinstance", "msg_text": "Consider merging these isinstance calls to isinstance(%s, (%s))", "msg_xpln": "Used when multiple consecutive isinstance calls can be merged into one.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1702", "msg_sym": "too-many-nested-blocks", "msg_text": "Too many nested blocks (%s/%s)", "msg_xpln": "Used when a function or a method has too many nested blocks. " "This makes the code less understandable and maintainable.", "tho_xpln": "Consider moving some of the code to helper functions.", "usage": "enhancement", }, { "msg_id": "R1703", "msg_sym": "simplifiable-if-statement", "msg_text": "The if statement can be replaced with %s", "msg_xpln": "Used when an if statement can be replaced with 'bool(test)'.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1704", "msg_sym": "redefined-argument-from-local", "msg_text": "Redefining argument with the local name %r", "msg_xpln": "Used when a local name is redefining an argument, which might " "suggest a potential error. This is taken in account only for a " "handful of name binding operations, such as for iteration, with " "statement assignment and exception handler assignment.", "tho_xpln": "Did you notice that an argument gets overwritten here?", "usage": "warning", }, { "msg_id": "R1705", "msg_sym": "no-else-return", "msg_text": 'Unnecessary "%s" after "return"', "msg_xpln": "Used in order to highlight an unnecessary block of code " "following an if containing a return statement. As such, it will " "warn when it encounters an else following a chain of ifs, all " "of them containing a return statement.", "tho_xpln": "", "usage": "style", }, # not sure if the recommended style is better (https://github.com/SoCo/SoCo/issues/500) { "msg_id": "R1706", "msg_sym": "consider-using-ternary", "msg_text": "Consider using ternary (%s)", "msg_xpln": "Used when one of known pre-python 2.5 ternary syntax is used.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "R1707", "msg_sym": "trailing-comma-tuple", "msg_text": "Disallow trailing comma tuple", "msg_xpln": "In Python, a tuple is actually created by the comma symbol, not " "by the parentheses. Unfortunately, one can actually create a " "tuple by misplacing a trailing comma, which can lead to " "potential weird bugs in your code. You should always use " "parentheses explicitly for creating a tuple.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "R1708", "msg_sym": "stop-iteration-return", "msg_text": "Do not raise StopIteration in generator, use return statement instead", "msg_xpln": "According to PEP479, the raise of StopIteration to end the loop " "of a generator may lead to hard to find bugs. This PEP specify " "that raise StopIteration has to be replaced by a simple return " "statement", "tho_xpln": "", "usage": "warning", }, { "msg_id": "R1709", # not sure what this means "msg_sym": "simplify-boolean-expression", "msg_text": "Boolean expression may be simplified to %s", "msg_xpln": "Emitted when redundant pre-python 2.5 ternary syntax is used.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "R1710", "msg_sym": "inconsistent-return-statements", "msg_text": "Either all return statements in a function should return an " "expression, or none of them should.", "msg_xpln": "According to PEP8, if any return statement returns an " "expression, any return statements where no value is returned " "should explicitly state this as return None, and an explicit " "return statement should be present at the end of the function " "(if reachable)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "R1711", "msg_sym": "useless-return", "msg_text": "Useless return at end of function or method", "msg_xpln": 'Emitted when a single "return" or "return None" statement is ' "found at the end of function or method definition. This " "statement can safely be removed because Python will implicitly " "return None", "tho_xpln": "", "usage": "style", }, { "msg_id": "R1712", "msg_sym": "consider-swap-variables", "msg_text": "Consider using tuple unpacking for swapping variables", "msg_xpln": "You do not have to use a temporary variable in order to swap " 'variables. Using "tuple unpacking" to directly swap variables ' "makes the intention more clear.", "tho_xpln": "You do not have to use a temporary variable in order to swap " 'variables. Using "tuple unpacking" to directly swap variables ' "makes the intention more clear. " 'Example: "a, b = b, a".', "usage": "enhancement", }, { "msg_id": "R1713", "msg_sym": "consider-using-join", "msg_text": "Consider using str.join(sequence) for concatenating strings " "from an iterable", "msg_xpln": "Using str.join(sequence) is faster, uses less memory and " "increases readability compared to for-loop iteration.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1714", "msg_sym": "consider-using-in", "msg_text": 'Consider merging these comparisons with "in" to %r', "msg_xpln": "To check if a variable is equal to one of many values,combine " "the values into a tuple and check if the variable is contained " '"in" it instead of checking for equality against each of the ' "values.This is faster and less verbose.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1715", "msg_sym": "consider-using-get", "msg_text": "Consider using dict.get for getting values from a dict if a key " "is present or a default if not", "msg_xpln": "Using the builtin dict.get for getting a value from a " "dictionary if a key is present or a default if not, is simpler " "and considered more idiomatic, although sometimes a bit slower", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1716", "msg_sym": "chained-comparison", "msg_text": "Simplify chained comparison between the operands", "msg_xpln": "This message is emitted when pylint encounters boolean " 'operation like"a < b and b < c", suggesting instead to refactor ' 'it to "a < b < c"', "tho_xpln": "", "usage": "style", }, # IMO this is confusing syntax if one expects < to be binary op { "msg_id": "R1717", "msg_sym": "consider-using-dict-comprehension", "msg_text": "Consider using a dictionary comprehension", "msg_xpln": "Emitted when we detect the creation of a dictionary using the dict() callable " "and a transient list. Although there is nothing syntactically wrong with this " "code, it is hard to read and can be simplified to a dict comprehension.Also it " "is faster since you don't need to create another transient list", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1718", "msg_sym": "consider-using-set-comprehension", "msg_text": "Consider using a set comprehension", "msg_xpln": "Although there is nothing syntactically wrong with this code, " "it is hard to read and can be simplified to a set " "comprehension. Also it is faster since you don't need to create " "another transient list", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1719", "msg_sym": "simplifiable-if-expression", "msg_text": "The if expression can be replaced with %s", "msg_xpln": "Used when an if expression can be replaced with 'bool(test)'", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1720", "msg_sym": "no-else-raise", "msg_text": 'Unnecessary "%s" after "raise"', "msg_xpln": "Used in order to highlight an unnecessary block of code following an if " "containing a raise statement. As such, it will warn when it encounters an else " "following a chain of ifs, all of them containing a raise statement.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1721", "msg_sym": "unnecessary-comprehension", "msg_text": "Unnecessary use of a comprehension", "msg_xpln": "Instead of using an identitiy comprehension, consider using the list, dict or " "set constructor. It is faster and simpler.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1722", "msg_sym": "consider-using-sys-exit", "msg_text": "Consider using sys.exit()", "msg_xpln": "Instead of using exit() or quit(), consider using the sys.exit().", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1723", "msg_sym": "no-else-break", "msg_text": 'Unnecessary "%s" after "break"', "msg_xpln": "Used in order to highlight an unnecessary block of code following an if " "containing a break statement. As such, it will warn when it encounters an else " "following a chain of ifs, all of them containing a break statement.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "R1724", "msg_sym": "no-else-continue", "msg_text": 'Unnecessary "%s" after "continue"', "msg_xpln": "Used in order to highlight an unnecessary block of code following an if " "containing a continue statement. As such, it will warn when it encounters an " "else following a chain of ifs, all of them containing a continue statement.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W0101", "msg_sym": "unreachable", "msg_text": "Unreachable code", "msg_xpln": 'Used when there is some code behind a "return" or "raise" ' "statement, which will never be accessed.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0102", "msg_sym": "dangerous-default-value", "msg_text": "Dangerous default value %s as argument", "msg_xpln": "Used when a mutable value as list or dictionary is detected in " "a default value for an argument.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0104", "msg_sym": "pointless-statement", "msg_text": "Statement seems to have no effect", "msg_xpln": "Used when a statement doesn't have any effect.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0105", "msg_sym": "pointless-string-statement", "msg_text": "String statement has no effect", "msg_xpln": "Used when a string is used as a statement (which of course has " "no effect). This is a particular case of W0104 with its own " "message so you can easily disable it if you're using those " "strings as documentation, instead of comments.", "tho_xpln": "", "usage": "skip", }, # string is useful for commenting out. Hard to misread such cases. { "msg_id": "W0106", "msg_sym": "expression-not-assigned", "msg_text": 'Expression "%s" is assigned to nothing', "msg_xpln": "Used when an expression that is not a function call is assigned " "to nothing. Probably something else was intended.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0107", "msg_sym": "unnecessary-pass", "msg_text": "Unnecessary pass statement", "msg_xpln": 'Used when a "pass" statement that can be avoided is ' "encountered.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W0108", "msg_sym": "unnecessary-lambda", "msg_text": "Lambda may not be necessary", "msg_xpln": "Used when the body of a lambda expression is a function call on " "the same argument list as the lambda itself; such lambda " "expressions are in all but a few cases replaceable with the " "function being called in the body of the lambda.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0109", "msg_sym": "duplicate-key", "msg_text": "Duplicate key %r in dictionary", "msg_xpln": "Used when a dictionary expression binds the same key multiple times.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0111", "msg_sym": "assign-to-new-keyword", "msg_text": "Name %s will become a keyword in Python %s", "msg_xpln": "Used when assignment will become invalid in future Python " "release due to introducing new keyword.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0120", "msg_sym": "useless-else-on-loop", "msg_text": "Else clause on loop without a break statement", "msg_xpln": "Loops should only have an else clause if they can exit early " "with a break statement, otherwise the statements under else " "should be on the same scope as the loop itself.", "tho_xpln": "", "usage": "enhancement", }, # See https://github.com/PyCQA/pylint/issues/1272 { "msg_id": "W0122", "msg_sym": "exec-used", "msg_text": "Use of exec", "msg_xpln": 'Used when you use the "exec" statement (function for Python 3), ' "to discourage its usage. That doesn't mean you cannot use it !", "tho_xpln": "", "usage": "skip", }, { "msg_id": "W0123", "msg_sym": "eval-used", "msg_text": "Use of eval", "msg_xpln": 'Used when you use the "eval" function, to discourage its usage. ' "Consider using `ast.literal_eval` for safely evaluating strings " "containing Python expressions from untrusted sources.", "tho_xpln": "", "usage": "skip", }, { "msg_id": "W0124", "msg_sym": "confusing-with-statement", "msg_text": 'Following "as" with another context manager looks like a tuple.', "msg_xpln": "Emitted when a `with` statement component returns multiple " "values and uses name binding with `as` only for a part of those " "values, as in with ctx() as a, b. This can be misleading, since " "it's not clear if the context manager returns a tuple or if the " "node without a name binding is another context manager.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0125", "msg_sym": "using-constant-test", "msg_text": "Using a conditional statement with a constant value", "msg_xpln": "Emitted when a conditional statement (if or ternary if) uses a " "constant value for its test. This might not be what the user " "intended to do.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0143", "msg_sym": "comparison-with-callable", "msg_text": "Comparing against a callable, did you omit the parenthesis?", "msg_xpln": "This message is emitted when pylint detects that a comparison " "with a callable was made, which might suggest that some " "parenthesis were omitted, resulting in potential unwanted " "behaviour.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0150", "msg_sym": "lost-exception", "msg_text": "%s statement in finally block may swallow exception", "msg_xpln": "Used when a break or a return statement is found inside the " "finally clause of a try...finally block: the exceptions raised " "in the try clause will be silently swallowed instead of being " "re-raised.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0199", "msg_sym": "assert-on-tuple", "msg_text": "Assert called on a 2-item-tuple. Did you mean 'assert x,y'?", "msg_xpln": "A call of assert on a tuple will always evaluate to true if the " "tuple is not empty, and will always evaluate to false if it is.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0201", "msg_sym": "attribute-defined-outside-init", "msg_text": "Attribute %r defined outside __init__", "msg_xpln": "Used when an instance attribute is defined outside the __init__ method.", "tho_xpln": "", "usage": "style", }, { "msg_id": "W0211", "msg_sym": "bad-staticmethod-argument", "msg_text": "Static method with %r as first argument", "msg_xpln": 'Used when a static method has "self" or a value specified in ' "valid- classmethod-first-arg option or " "valid-metaclass-classmethod-first-arg option as first argument.", "tho_xpln": 'Static methods should not have "self" as first argument.', "usage": "warning", }, { "msg_id": "W0212", "msg_sym": "protected-access", "msg_text": "Access to a protected member %s of a client class", "msg_xpln": "Used when a protected member (i.e. class member with a name " "beginning with an underscore) is access outside the class or a " "descendant of the class where it's defined.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0221", "msg_sym": "arguments-differ", "msg_text": "Parameters differ from %s %r method", "msg_xpln": "Used when a method has a different number of arguments than in " "the implemented interface or in an overridden method.", "tho_xpln": "", "usage": "warning", }, # looks like MyPy 0.620 doesn't catch this { "msg_id": "W0222", "msg_sym": "signature-differs", "msg_text": "Signature differs from %s %r method", "msg_xpln": "Used when a method signature is different than in the " "implemented interface or in an overridden method.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0223", "msg_sym": "abstract-method", "msg_text": "Method %r is abstract in class %r but is not overridden", "msg_xpln": "Used when an abstract method (i.e. raise NotImplementedError) " "is not overridden in concrete class.", "tho_xpln": "", "usage": "skip", }, # Can't decide if it's OK to leave abstract. https://stackoverflow.com/questions/30884804/pylint-for-half-implemented-abstract-classes { "msg_id": "W0231", "msg_sym": "super-init-not-called", "msg_text": "__init__ method from base class %r is not called", "msg_xpln": "Used when an ancestor class method has an __init__ method which " "is not called by a derived class.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0232", "msg_sym": "no-init", "msg_text": "Class has no __init__ method", "msg_xpln": "Used when a class has no __init__ method, neither its parent classes.", "tho_xpln": "", "usage": "skip", }, # so what? { "msg_id": "W0233", "msg_sym": "non-parent-init-called", "msg_text": "__init__ method from a non direct base class %r is called", "msg_xpln": "Used when an __init__ method is called on a class which is not " "in the direct ancestors for the analysed class.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0235", "msg_sym": "useless-super-delegation", "msg_text": "Useless super delegation in method %r", "msg_xpln": "Used whenever we can detect that an overridden method is " "useless, relying on super() delegation to do the same thing as " "another method from the MRO.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W0236", "msg_sym": "invalid-overridden-method", "msg_text": "Method %r was expected to be %r, found it instead as %r", "msg_xpln": "Used when we detect that a method was overridden as a property or the other " "way around, which could result in potential bugs at runtime.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W0301", "msg_sym": "unnecessary-semicolon", "msg_text": "Unnecessary semicolon", "msg_xpln": 'Used when a statement is ended by a semi-colon (";"), which ' "isn't necessary (that's python, not C ;).", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W0311", "msg_sym": "bad-indentation", "msg_text": "Bad indentation. Found %s %s, expected %s", "msg_xpln": "Used when an unexpected number of indentation's tabulations or " "spaces has been found.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0312", "msg_sym": "mixed-indentation", "msg_text": "Found indentation with %ss instead of %ss", "msg_xpln": "Used when there are some mixed tabs and spaces in a module.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0401", "msg_sym": "wildcard-import", "msg_text": "Wildcard import %s", "msg_xpln": "Used when `from module import *` is detected.", "tho_xpln": '"from ____ import *" is not recommended. It\'s better to import only required names from the module', "usage": "enhancement", }, { "msg_id": "W0402", "msg_sym": "deprecated-module", "msg_text": "Uses of a deprecated module %r", "msg_xpln": "Used a module marked as deprecated is imported.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0404", "msg_sym": "reimported", "msg_text": "Reimport %r (imported line %s)", "msg_xpln": "Used when a module is reimported multiple times.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0406", "msg_sym": "import-self", "msg_text": "Module import itself", "msg_xpln": "This usually happens when you give your script the same " "as name a library module you are trying to import. " "This won't work, because your module will shadow the library module.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0407", "msg_sym": "preferred-module", "msg_text": "Prefer importing %r instead of %r", "msg_xpln": "Used when a module imported has a preferred replacement module.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W0410", "msg_sym": "misplaced-future", "msg_text": "__future__ import is not the first non docstring statement", "msg_xpln": "Python 2.5 and greater require __future__ import to be the " "first non docstring statement in the module.", "tho_xpln": "", "usage": "skip", }, # Python explains it in SyntaxError { "msg_id": "W0511", "msg_sym": "fixme", "msg_text": "", "msg_xpln": "Used when a warning note as FIXME or XXX is detected.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W0601", "msg_sym": "global-variable-undefined", "msg_text": "Global variable %r undefined at the module level", "msg_xpln": 'Used when a variable is defined through the "global" statement ' "but the variable is not defined in the module scope.", "tho_xpln": "", "usage": "warning", }, # Better message than MyPy { "msg_id": "W0602", "msg_sym": "global-variable-not-assigned", "msg_text": "Using global for %r but no assignment is done", "msg_xpln": 'Used when a variable is defined through the "global" statement ' "but no assignment to this variable is done.", "tho_xpln": "You don't need \"global\" statement if you don't want to update the variable.", "usage": "warning", }, { "msg_id": "W0603", "msg_sym": "global-statement", "msg_text": "Using the global statement", "msg_xpln": 'Used when you use the "global" statement to update a global ' "variable. Pylint just tries to discourage this usage. That " "doesn't mean you cannot use it !", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W0604", "msg_sym": "global-at-module-level", "msg_text": "Using the global statement at the module level", "msg_xpln": 'Used when you use the "global" statement at the module level ' "since it has no effect", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0611", "msg_sym": "unused-import", "msg_text": "Unused %s", "msg_xpln": "Used when an imported module or variable is not used.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0612", "msg_sym": "unused-variable", "msg_text": "Unused variable %r", "msg_xpln": "Used when a variable is defined but not used.", "tho_xpln": "Looks like the variable is defined (or imported) but not used.", "usage": "warning", }, # NB! Only applies to local variables { "msg_id": "W0613", "msg_sym": "unused-argument", "msg_text": "Unused argument %r", "msg_xpln": "Used when a function or method argument is not used.", "tho_xpln": "If you want to keep the argument and silence this warning, " 'then add comment "#pylint: disable=unused-argument" as first line in your function body.', "usage": "warning", }, { "msg_id": "W0614", "msg_sym": "unused-wildcard-import", "msg_text": "Unused import %s from wildcard import", "msg_xpln": "Used when an imported module or variable is not used from a " "`'from X import *'` style import.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W0621", "msg_sym": "redefined-outer-name", "msg_text": "Redefining name %r from outer scope (line %s)", "msg_xpln": "Used when a variable's name hides a name defined in the outer scope.", "tho_xpln": "It looks like the local variable is " "hiding a global variable with the same name.\n\n" "Most likely there is nothing wrong with this. " "I just wanted to remind you that you can't access the global variable like this. " "If you knew it then please ignore the warning.\n\n" "If you don't want to see this reminder in the future, then add " '"redefined-outer-name" (without quotes) into "Tools → Options → Assistant → Disabled checks".', "usage": "warning", }, { "msg_id": "W0622", "msg_sym": "redefined-builtin", "msg_text": "Redefining built-in %r", "msg_xpln": "Used when a variable or function override a built-in.", "tho_xpln": "", "usage": "enhancement", }, # warning about "list", "min" and "max" would cause too much confusion { "msg_id": "W0623", "msg_sym": "redefine-in-handler", "msg_text": "Redefining name %r from %s in exception handler", "msg_xpln": "Used when an exception handler assigns the exception to an existing name", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0631", "msg_sym": "undefined-loop-variable", "msg_text": "Using possibly undefined loop variable %r", "msg_xpln": "Used when a loop variable (i.e. defined by a for loop or a list " "comprehension or a generator expression) is used outside the " "loop.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0640", "msg_sym": "cell-var-from-loop", "msg_text": "Cell variable %s defined in loop", "msg_xpln": "A variable used in a closure is defined in a loop. This will " "result in all closures using the same value for the closed-over " "variable.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0641", "msg_sym": "possibly-unused-variable", "msg_text": "Possibly unused variable %r", "msg_xpln": "Used when a variable is defined but might not be used. The " "possibility comes from the fact that locals() might be used, " "which could consume or not the said variable", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0642", "msg_sym": "self-cls-assignment", "msg_text": "Invalid assignment to %s in method", "msg_xpln": "Invalid assignment to self or cls in instance or class method " "respectively.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0702", "msg_sym": "bare-except", "msg_text": "No exception type(s) specified", "msg_xpln": "Used when an except clause doesn't specify exceptions type to catch.", "tho_xpln": "Used when an except clause doesn't specify exceptions type to catch. " "Did you mean to catch also SystemExit and KeyboardInterrupt? " 'If not then prefer "except Exception:".', "usage": "enhancement", }, { "msg_id": "W0703", "msg_sym": "broad-except", "msg_text": "Catching too general exception %s", "msg_xpln": "Used when an except catches a too general exception, possibly " "burying unrelated errors.", "tho_xpln": "This may silence unrelated errors. Consider using more narrow " ' type or several types, eg. "except (ZeroDivisionError, IndexError):".', "usage": "enhancement", }, { "msg_id": "W0705", "msg_sym": "duplicate-except", "msg_text": "Catching previously caught exception type %s", "msg_xpln": "Used when an except catches a type that was already caught by a " "previous handler.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0706", "msg_sym": "try-except-raise", "msg_text": "The except handler raises immediately", "msg_xpln": "Used when an except handler uses raise as its first or only " "operator. This is useless because it raises back the exception " "immediately. Remove the raise operator or the entire " "try-except-raise block!", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0711", "msg_sym": "binary-op-exception", "msg_text": 'Exception to catch is the result of a binary "%s" operation', "msg_xpln": 'Used when the exception to catch is of the form "except A or ' 'B:". If intending to catch multiple, rewrite as "except (A, ' 'B):"', "tho_xpln": "", "usage": "warning", }, { "msg_id": "W0715", "msg_sym": "raising-format-tuple", "msg_text": "Exception arguments suggest string formatting might be intended", "msg_xpln": "Used when passing multiple arguments to an exception " "constructor, the first of them a string literal containing what " "appears to be placeholders intended for formatting", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1113", "msg_sym": "keyword-arg-before-vararg", "msg_text": "Keyword argument before variable positional arguments list in " "the definition of %s function", "msg_xpln": "When defining a keyword argument before variable positional " "arguments, one can end up in having multiple values passed for " "the aforementioned parameter in case the method is called with " "keyword arguments.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1114", "msg_sym": "arguments-out-of-order", "msg_text": "Positional arguments appear to be out of order", "msg_xpln": "Emitted when the caller's argument names fully match the parameter names in " "the function signature but do not have the same order.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1201", "msg_sym": "logging-not-lazy", "msg_text": "Specify string format arguments as logging function parameters", "msg_xpln": "Used when a logging statement has a call form of " '"logging.(format_string % (format_args...))". ' "Such calls should leave string interpolation to the logging " 'method itself and be written "logging.(format_string, format_args...)" so that the program may ' "avoid incurring the cost of the interpolation in those cases in " "which no message will be logged. For more, see " "http://www.python.org/dev/peps/pep-0282/.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W1202", "msg_sym": "logging-format-interpolation", "msg_text": "Use % formatting in logging functions and pass the % parameters as arguments", "msg_xpln": 'Used when a logging statement has a call form of "logging.()". with invalid string formatting. Use another way ' "for format the string instead.", "tho_xpln": "", "usage": "enhancement", }, # Don't want to force this { "msg_id": "W1203", "msg_sym": "logging-fstring-interpolation", "msg_text": "Use % formatting in logging functions and pass the % parameters " "as arguments", "msg_xpln": "Used when a logging statement has a call form of " '"logging.method(f"..."))". Such calls should use % formatting ' "instead, but leave interpolation to the logging function by " "passing the parameters as arguments.", "tho_xpln": "", "usage": "style", }, { "msg_id": "W1300", "msg_sym": "bad-format-string-key", "msg_text": "Format string dictionary key should be a string, not %s", "msg_xpln": "Used when a format string that uses named conversion specifiers " "is used with a dictionary whose keys are not all strings.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1301", "msg_sym": "unused-format-string-key", "msg_text": "Unused key %r in format string dictionary", "msg_xpln": "Used when a format string that uses named conversion specifiers " "is used with a dictionary that contains keys not required by " "the format string.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1302", "msg_sym": "bad-format-string", "msg_text": "Invalid format string", "msg_xpln": "Used when a PEP 3101 format string is invalid. This message " "can't be emitted when using Python < 2.7.", "tho_xpln": "Used when a PEP 3101 format string is invalid.", "usage": "warning", }, { "msg_id": "W1303", "msg_sym": "missing-format-argument-key", "msg_text": "Missing keyword argument %r for format string", "msg_xpln": "Used when a PEP 3101 format string that uses named fields " "doesn't receive one or more required keywords. This message " "can't be emitted when using Python < 2.7.", "tho_xpln": "Used when a PEP 3101 format string that uses named fields " "doesn't receive one or more required keywords.", "usage": "warning", }, { "msg_id": "W1304", "msg_sym": "unused-format-string-argument", "msg_text": "Unused format argument %r", "msg_xpln": "Used when a PEP 3101 format string that uses named fields is " "used with an argument that is not required by the format " "string. This message can't be emitted when using Python < 2.7.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1305", "msg_sym": "format-combined-specification", "msg_text": "Format string contains both automatic field numbering and " "manual field specification", "msg_xpln": "Used when a PEP 3101 format string contains both automatic " "field numbering (e.g. '{}') and manual field specification " "(e.g. '{0}'). This message can't be emitted when using Python < " "2.7.", "tho_xpln": "Used when a PEP 3101 format string contains both automatic " "field numbering (e.g. '{}') and manual field specification " "(e.g. '{0}').", "usage": "warning", }, { "msg_id": "W1306", "msg_sym": "missing-format-attribute", "msg_text": "Missing format attribute %r in format specifier %r", "msg_xpln": "Used when a PEP 3101 format string uses an attribute specifier " "({0.length}), but the argument passed for formatting doesn't " "have that attribute. This message can't be emitted when using " "Python < 2.7.", "tho_xpln": "Used when a PEP 3101 format string uses an attribute specifier " "({0.length}), but the argument passed for formatting doesn't " "have that attribute.", "usage": "warning", }, { "msg_id": "W1307", "msg_sym": "invalid-format-index", "msg_text": "Using invalid lookup key %r in format specifier %r", "msg_xpln": "Used when a PEP 3101 format string uses a lookup specifier " "({a[1]}), but the argument passed for formatting doesn't " "contain or doesn't have that key as an attribute. This message " "can't be emitted when using Python < 2.7.", "tho_xpln": "Used when a PEP 3101 format string uses a lookup specifier " "({a[1]}), but the argument passed for formatting doesn't " "contain or doesn't have that key as an attribute.", "usage": "warning", }, { "msg_id": "W1308", "msg_sym": "duplicate-string-formatting-argument", "msg_text": "Duplicate string formatting argument %r, consider passing as named argument", "msg_xpln": "Used when we detect that a string formatting is repeating an argument instead " "of using named string arguments", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1401", "msg_sym": "anomalous-backslash-in-string", "msg_text": "Anomalous backslash in string: '%s'. String constant might be " "missing an r prefix.", "msg_xpln": "Used when a backslash is in a literal string but not as an escape.", "tho_xpln_rst": "In regular string literals backslash is treated as a special character. " "If you meant to represent backslash itself, " """then you should double it, eg:\n\n``'C:\\\\Users\\\\Tim'``\n\n""" """or use raw-string literal, eg:\n\n``r'C:\\Users\\Tim'``""", "usage": "warning", }, { "msg_id": "W1402", "msg_sym": "anomalous-unicode-escape-in-string", "msg_text": "Anomalous Unicode escape in byte string: '%s'. String constant " "might be missing an r or u prefix.", "msg_xpln": "Used when an escape like \\u is encountered in a byte string " "where it has no effect.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1403", "msg_sym": "implicit-str-concat-in-sequence", "msg_text": "Implicit string concatenation found in %s", "msg_xpln": "String literals are implicitly concatenated in a literal iterable definition : " "maybe a comma is missing ?", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1501", "msg_sym": "bad-open-mode", "msg_text": '"%s" is not a valid mode for open.', "msg_xpln": "Python supports: r, w, a[, x] modes with b, +, and U (only with " "r) options. See " "http://docs.python.org/3/library/functions.html#open", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1503", "msg_sym": "redundant-unittest-assert", "msg_text": "Redundant use of %s with constant value %r", "msg_xpln": "The first argument of assertTrue and assertFalse is a " "condition. If a constant is passed as parameter, that condition " "will be always true. In this case a warning should be emitted.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1505", "msg_sym": "deprecated-method", "msg_text": "Using deprecated method %s()", "msg_xpln": "The method is marked as deprecated and will be removed in a " "future version of Python. Consider looking for an alternative " "in the documentation.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1506", "msg_sym": "bad-thread-instantiation", "msg_text": "threading.Thread needs the target function", "msg_xpln": "The warning is emitted when a threading.Thread class is " "instantiated without the target function being passed. By " "default, the first parameter is the group param, not the target " "param.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1507", "msg_sym": "shallow-copy-environ", "msg_text": "Using copy.copy(os.environ). Use os.environ.copy() instead.", "msg_xpln": "os.environ is not a dict object but proxy object, so shallow " "copy has still effects on original object. See " "https://bugs.python.org/issue15373 for reference.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1508", "msg_sym": "invalid-envvar-default", "msg_text": "%s default type is %s. Expected str or None.", "msg_xpln": "Env manipulation functions return None or str values. Supplying " "anything different as a default may cause bugs. See " "https://docs.python.org/3/library/os.html#os.getenv.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1509", "msg_sym": "subprocess-popen-preexec-fn", "msg_text": "Using preexec_fn keyword which may be unsafe in the presence of threads", "msg_xpln": "The preexec_fn parameter is not safe to use in the presence of " "threads in your application. The child process could deadlock " "before exec is called. If you must use it, keep it trivial! " "Minimize the number of libraries you call " "into.https://docs.python.org/3/library/subprocess.html#popen-constructor", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1510", "msg_sym": "subprocess-run-check", "msg_text": "Using subprocess.run without explicitly set `check` is not recommended.", "msg_xpln": "The check parameter should always be used with explicitly set `check` keyword " "to make clear what the error-handling behavior " "is.https://docs.python.org/3/library/subprocess.html#subprocess.runs", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W1601", "msg_sym": "apply-builtin", "msg_text": "apply built-in referenced", "msg_xpln": "Used when the apply built-in function is referenced (missing " "from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1602", "msg_sym": "basestring-builtin", "msg_text": "basestring built-in referenced", "msg_xpln": "Used when the basestring built-in function is referenced " "(missing from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1603", "msg_sym": "buffer-builtin", "msg_text": "buffer built-in referenced", "msg_xpln": "Used when the buffer built-in function is referenced (missing " "from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1604", "msg_sym": "cmp-builtin", "msg_text": "cmp built-in referenced", "msg_xpln": "Used when the cmp built-in function is referenced (missing from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1605", "msg_sym": "coerce-builtin", "msg_text": "coerce built-in referenced", "msg_xpln": "Used when the coerce built-in function is referenced (missing " "from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1606", "msg_sym": "execfile-builtin", "msg_text": "execfile built-in referenced", "msg_xpln": "Used when the execfile built-in function is referenced (missing " "from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1607", "msg_sym": "file-builtin", "msg_text": "file built-in referenced", "msg_xpln": "Used when the file built-in function is referenced (missing from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1608", "msg_sym": "long-builtin", "msg_text": "long built-in referenced", "msg_xpln": "Used when the long built-in function is referenced (missing from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1609", "msg_sym": "raw_input-builtin", "msg_text": "raw_input built-in referenced", "msg_xpln": "Used when the raw_input built-in function is referenced " "(missing from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1610", "msg_sym": "reduce-builtin", "msg_text": "reduce built-in referenced", "msg_xpln": "Used when the reduce built-in function is referenced (missing " "from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1611", "msg_sym": "standarderror-builtin", "msg_text": "StandardError built-in referenced", "msg_xpln": "Used when the StandardError built-in function is referenced " "(missing from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1612", "msg_sym": "unicode-builtin", "msg_text": "unicode built-in referenced", "msg_xpln": "Used when the unicode built-in function is referenced (missing " "from Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1613", "msg_sym": "xrange-builtin", "msg_text": "xrange built-in referenced", "msg_xpln": "Used when the xrange built-in function is referenced (missing " "from Python 3)", "tho_xpln": "Used when the xrange built-in function is referenced (missing " "from Python 3). Use range instead.", "usage": "warning", }, { "msg_id": "W1614", "msg_sym": "coerce-method", "msg_text": "__coerce__ method defined", "msg_xpln": "Used when a __coerce__ method is defined (method is not used by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1615", "msg_sym": "delslice-method", "msg_text": "__delslice__ method defined", "msg_xpln": "Used when a __delslice__ method is defined (method is not used " "by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1616", "msg_sym": "getslice-method", "msg_text": "__getslice__ method defined", "msg_xpln": "Used when a __getslice__ method is defined (method is not used " "by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1617", "msg_sym": "setslice-method", "msg_text": "__setslice__ method defined", "msg_xpln": "Used when a __setslice__ method is defined (method is not used " "by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1618", "msg_sym": "no-absolute-import", "msg_text": "import missing `from __future__ import absolute_import`", "msg_xpln": "Used when an import is not accompanied by ``from __future__ " "import absolute_import`` (default behaviour in Python 3)", "tho_xpln": "", "usage": "skip", }, # Not relevant anymore { "msg_id": "W1619", "msg_sym": "old-division", "msg_text": "division w/o __future__ statement", "msg_xpln": "Used for non-floor division w/o a float literal or ``from " "__future__ import division`` (Python 3 returns a float for int " "division unconditionally)", "tho_xpln": "", "usage": "skip", }, { "msg_id": "W1620", "msg_sym": "dict-iter-method", "msg_text": "Calling a dict.iter*() method", "msg_xpln": "Used for calls to dict.iterkeys(), itervalues() or iteritems() " "(Python 3 lacks these methods)", "tho_xpln": "Used for calls to dict.iterkeys(), itervalues() or iteritems(). " "Python 3 lacks these methods, use dict.keys(), values() or items().", "usage": "warning", }, { "msg_id": "W1621", "msg_sym": "dict-view-method", "msg_text": "Calling a dict.view*() method", "msg_xpln": "Used for calls to dict.viewkeys(), viewvalues() or viewitems() " "(Python 3 lacks these methods)", "tho_xpln": "Used for calls to dict.viewkeys(), viewvalues() or viewitems(). " "Python 3 lacks these methods, use dict.keys(), values() or items().", "usage": "warning", }, { "msg_id": "W1622", "msg_sym": "next-method-called", "msg_text": "Called a next() method on an object", "msg_xpln": "Used when an object's next() method is called (Python 3 uses " "the next() built- in function)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1623", "msg_sym": "metaclass-assignment", "msg_text": "Assigning to a class's __metaclass__ attribute", "msg_xpln": "Used when a metaclass is specified by assigning to " "__metaclass__ (Python 3 specifies the metaclass as a class " "statement argument)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1624", "msg_sym": "indexing-exception", "msg_text": "Indexing exceptions will not work on Python 3", "msg_xpln": "Indexing exceptions will not work on Python 3. Use " "`exception.args[index]` instead.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1625", "msg_sym": "raising-string", "msg_text": "Raising a string exception", "msg_xpln": "Used when a string exception is raised. This will not work on Python 3.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1626", "msg_sym": "reload-builtin", "msg_text": "reload built-in referenced", "msg_xpln": "Used when the reload built-in function is referenced (missing " "from Python 3). You can use instead imp.reload or " "importlib.reload.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1627", "msg_sym": "oct-method", "msg_text": "__oct__ method defined", "msg_xpln": "Used when an __oct__ method is defined (method is not used by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1628", "msg_sym": "hex-method", "msg_text": "__hex__ method defined", "msg_xpln": "Used when a __hex__ method is defined (method is not used by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1629", "msg_sym": "nonzero-method", "msg_text": "__nonzero__ method defined", "msg_xpln": "Used when a __nonzero__ method is defined (method is not used by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1630", "msg_sym": "cmp-method", "msg_text": "__cmp__ method defined", "msg_xpln": "Used when a __cmp__ method is defined (method is not used by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1632", "msg_sym": "input-builtin", "msg_text": "input built-in referenced", "msg_xpln": "Used when the input built-in is referenced " "(backwards-incompatible semantics in Python 3)", "tho_xpln": "", "usage": "skip", }, { "msg_id": "W1633", "msg_sym": "round-builtin", "msg_text": "round built-in referenced", "msg_xpln": "Used when the round built-in is referenced " "(backwards-incompatible semantics in Python 3)", "tho_xpln": "", "usage": "skip", }, { "msg_id": "W1634", "msg_sym": "intern-builtin", "msg_text": "intern built-in referenced", "msg_xpln": "Used when the intern built-in is referenced (Moved to " "sys.intern in Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1635", "msg_sym": "unichr-builtin", "msg_text": "unichr built-in referenced", "msg_xpln": "Used when the unichr built-in is referenced (Use chr in Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1636", "msg_sym": "map-builtin-not-iterating", "msg_text": "map built-in referenced when not iterating", "msg_xpln": "Used when the map built-in is referenced in a non-iterating " "context (returns an iterator in Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1637", "msg_sym": "zip-builtin-not-iterating", "msg_text": "zip built-in referenced when not iterating", "msg_xpln": "Used when the zip built-in is referenced in a non-iterating " "context (returns an iterator in Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1638", "msg_sym": "range-builtin-not-iterating", "msg_text": "range built-in referenced when not iterating", "msg_xpln": "Used when the range built-in is referenced in a non-iterating " "context (returns a range in Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1639", "msg_sym": "filter-builtin-not-iterating", "msg_text": "filter built-in referenced when not iterating", "msg_xpln": "Used when the filter built-in is referenced in a non-iterating " "context (returns an iterator in Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1640", "msg_sym": "using-cmp-argument", "msg_text": "Using the cmp argument for list.sort / sorted", "msg_xpln": "Using the cmp argument for list.sort or the sorted builtin " "should be avoided, since it was removed in Python 3. Using " "either `key` or `functools.cmp_to_key` should be preferred.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1641", "msg_sym": "eq-without-hash", "msg_text": "Implementing __eq__ without also implementing __hash__", "msg_xpln": "Used when a class implements __eq__ but not __hash__. In Python " "2, objects get object.__hash__ as the default implementation, " "in Python 3 objects get None as their default __hash__ " "implementation if they also implement __eq__.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1642", "msg_sym": "div-method", "msg_text": "__div__ method defined", "msg_xpln": "Used when a __div__ method is defined. Using `__truediv__` and " "setting__div__ = __truediv__ should be preferred.(method is not " "used by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1643", "msg_sym": "idiv-method", "msg_text": "__idiv__ method defined", "msg_xpln": "Used when an __idiv__ method is defined. Using `__itruediv__` " "and setting__idiv__ = __itruediv__ should be preferred.(method " "is not used by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1644", "msg_sym": "rdiv-method", "msg_text": "__rdiv__ method defined", "msg_xpln": "Used when a __rdiv__ method is defined. Using `__rtruediv__` " "and setting__rdiv__ = __rtruediv__ should be preferred.(method " "is not used by Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1645", "msg_sym": "exception-message-attribute", "msg_text": "Exception.message removed in Python 3", "msg_xpln": "Used when the message attribute is accessed on an Exception. " "Use str(exception) instead.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1646", "msg_sym": "invalid-str-codec", "msg_text": "non-text encoding used in str.decode", "msg_xpln": "Used when using str.encode or str.decode with a non-text " "encoding. Use codecs module to handle arbitrary codecs.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1647", "msg_sym": "sys-max-int", "msg_text": "sys.maxint removed in Python 3", "msg_xpln": "Used when accessing sys.maxint. Use sys.maxsize instead.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1648", "msg_sym": "bad-python3-import", "msg_text": "Module moved in Python 3", "msg_xpln": "Used when importing a module that no longer exists in Python 3.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1649", "msg_sym": "deprecated-string-function", "msg_text": "Accessing a deprecated function on the string module", "msg_xpln": "Used when accessing a string function that has been deprecated " "in Python 3.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1650", "msg_sym": "deprecated-str-translate-call", "msg_text": "Using str.translate with deprecated deletechars parameters", "msg_xpln": "Used when using the deprecated deletechars parameters from " "str.translate. Use re.sub to remove the desired characters", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1651", "msg_sym": "deprecated-itertools-function", "msg_text": "Accessing a deprecated function on the itertools module", "msg_xpln": "Used when accessing a function on itertools that has been " "removed in Python 3.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1652", "msg_sym": "deprecated-types-field", "msg_text": "Accessing a deprecated fields on the types module", "msg_xpln": "Used when accessing a field on types that has been removed in Python 3.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1653", "msg_sym": "next-method-defined", "msg_text": "next method defined", "msg_xpln": "Used when a next method is defined that would be an iterator in " "Python 2 but is treated as a normal function in Python 3.", "tho_xpln": "", "usage": "enhancement", }, { "msg_id": "W1654", "msg_sym": "dict-items-not-iterating", "msg_text": "dict.items referenced when not iterating", "msg_xpln": "Used when dict.items is referenced in a non-iterating context " "(returns an iterator in Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1655", "msg_sym": "dict-keys-not-iterating", "msg_text": "dict.keys referenced when not iterating", "msg_xpln": "Used when dict.keys is referenced in a non-iterating context " "(returns an iterator in Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1656", "msg_sym": "dict-values-not-iterating", "msg_text": "dict.values referenced when not iterating", "msg_xpln": "Used when dict.values is referenced in a non-iterating context " "(returns an iterator in Python 3)", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1657", "msg_sym": "deprecated-operator-function", "msg_text": "Accessing a removed attribute on the operator module", "msg_xpln": "Used when accessing a field on operator module that has been " "removed in Python 3.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1658", "msg_sym": "deprecated-urllib-function", "msg_text": "Accessing a removed attribute on the urllib module", "msg_xpln": "Used when accessing a field on urllib module that has been " "removed or moved in Python 3.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1659", "msg_sym": "xreadlines-attribute", "msg_text": "Accessing a removed xreadlines attribute", "msg_xpln": "Used when accessing the xreadlines() function on a file stream, " "removed in Python 3.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1660", "msg_sym": "deprecated-sys-function", "msg_text": "Accessing a removed attribute on the sys module", "msg_xpln": "Used when accessing a field on sys module that has been removed " "in Python 3.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1661", "msg_sym": "exception-escape", "msg_text": "Using an exception object that was bound by an except handler", "msg_xpln": "Emitted when using an exception, that was bound in an except " "handler, outside of the except handler. On Python 3 these " "exceptions will be deleted once they get out of the except " "handler.", "tho_xpln": "", "usage": "warning", }, { "msg_id": "W1662", "msg_sym": "comprehension-escape", "msg_text": "Using a variable that was bound inside a comprehension", "msg_xpln": "Emitted when using a variable, that was bound in a " "comprehension handler, outside of the comprehension itself. On " "Python 3 these variables will be deleted outside of the " "comprehension.", "tho_xpln": "", "usage": "warning", }, ] all_checks_by_symbol = {c["msg_sym"]: c for c in all_checks} def load_plugin(): add_program_analyzer(PylintAnalyzer) get_workbench().set_default("assistance.use_pylint", True) thonny-3.2.7/thonny/plugins/locals_marker.py0000644000175000017500000001002513611773167022256 0ustar annamaaannamaa00000000000000import logging import tkinter as tk from thonny import get_workbench, jedi_utils class LocalsHighlighter: def __init__(self, text): self.text = text self._update_scheduled = False def get_positions(self): tree = jedi_utils.import_python_tree() locs = [] def process_scope(scope): if isinstance(scope, tree.Function): # process all children after name node, # (otherwise name of global function will be marked as local def) local_names = set() global_names = set() for child in scope.children[2:]: process_node(child, local_names, global_names) else: if hasattr(scope, "subscopes"): for child in scope.subscopes: process_scope(child) elif hasattr(scope, "children"): for child in scope.children: process_scope(child) def process_node(node, local_names, global_names): if isinstance(node, tree.GlobalStmt): global_names.update([n.value for n in node.get_global_names()]) elif isinstance(node, tree.Name): if node.value in global_names: return if node.is_definition(): # local def locs.append(node) local_names.add(node.value) elif node.value in local_names: # use of local locs.append(node) elif isinstance(node, tree.BaseNode): # ref: jedi/parser/grammar*.txt if node.type == "trailer" and node.children[0].value == ".": # this is attribute return if isinstance(node, tree.Function): global_names = set() # outer global statement doesn't have effect anymore for child in node.children: process_node(child, local_names, global_names) source = self.text.get("1.0", "end") module = jedi_utils.parse_source(source) for child in module.children: if isinstance(child, tree.BaseNode) and jedi_utils.is_scope(child): process_scope(child) loc_pos = set( ( "%d.%d" % (usage.start_pos[0], usage.start_pos[1]), "%d.%d" % (usage.start_pos[0], usage.start_pos[1] + len(usage.value)), ) for usage in locs ) return loc_pos def _highlight(self, pos_info): for pos in pos_info: start_index, end_index = pos[0], pos[1] self.text.tag_add("local_name", start_index, end_index) def schedule_update(self): def perform_update(): try: self.update() finally: self._update_scheduled = False if not self._update_scheduled: self._update_scheduled = True self.text.after_idle(perform_update) def update(self): self.text.tag_remove("local_name", "1.0", "end") if get_workbench().get_option("view.locals_highlighting"): try: highlight_positions = self.get_positions() self._highlight(highlight_positions) except Exception: logging.exception("Problem when updating local variable tags") def update_highlighting(event): assert isinstance(event.widget, tk.Text) text = event.widget if not hasattr(text, "local_highlighter"): text.local_highlighter = LocalsHighlighter(text) text.local_highlighter.schedule_update() def load_plugin() -> None: if jedi_utils.get_version_tuple() < (0, 9): logging.warning("Jedi version is too old. Disabling locals marker") return wb = get_workbench() wb.set_default("view.locals_highlighting", False) wb.bind_class("CodeViewText", "<>", update_highlighting, True) wb.bind("<>", update_highlighting, True) thonny-3.2.7/thonny/plugins/goto_definition.py0000644000175000017500000000215113611773167022621 0ustar annamaaannamaa00000000000000import tkinter as tk from jedi import Script from thonny import get_workbench from thonny.ui_utils import control_is_pressed def goto_definition(event): if not control_is_pressed(event.state): return assert isinstance(event.widget, tk.Text) text = event.widget source = text.get("1.0", "end") index = text.index("insert") index_parts = index.split(".") line, column = int(index_parts[0]), int(index_parts[1]) # TODO: find current editor filename script = Script(source, line=line, column=column, path="") defs = script.goto_definitions() if len(defs) > 0: module_path = defs[0].module_path module_name = defs[0].module_name line = defs[0].line if module_path and line is not None: get_workbench().get_editor_notebook().show_file(module_path, line) elif module_name == "" and line is not None: # current editor get_workbench().get_editor_notebook().get_current_editor().select_range(line) def load_plugin() -> None: wb = get_workbench() wb.bind_class("CodeViewText", "<1>", goto_definition, True) thonny-3.2.7/thonny/plugins/stdlib_error_helpers.py0000644000175000017500000006207613611773167023671 0ustar annamaaannamaa00000000000000import ast import builtins import re import token import tokenize import os.path from thonny.assistance import ErrorHelper, Suggestion, name_similarity, add_error_helper from thonny import assistance from thonny.misc_utils import running_on_linux, running_on_windows class SyntaxErrorHelper(ErrorHelper): def __init__(self, error_info): super().__init__(error_info) self.tokens = [] self.token_error = None if self.error_info["message"] == "EOL while scanning string literal": self.intro_text = ( "You haven't properly closed the string on line %s." % self.error_info["lineno"] + "\n(If you want a multi-line string, then surround it with" + " `'''` or `\"\"\"` at both ends.)" ) elif self.error_info["message"] == "EOF while scanning triple-quoted string literal": # lineno is not useful, as it is at the end of the file and user probably # didn't want the string to end there self.intro_text = "You haven't properly closed a triple-quoted string" else: if self.error_info["filename"] and os.path.isfile(self.error_info["filename"]): with open(self.error_info["filename"], mode="rb") as fp: try: for t in tokenize.tokenize(fp.readline): self.tokens.append(t) except tokenize.TokenError as e: self.token_error = e except IndentationError as e: self.indentation_error = e if not self.tokens or self.tokens[-1].type not in [ token.ERRORTOKEN, token.ENDMARKER, ]: self.tokens.append(tokenize.TokenInfo(token.ERRORTOKEN, "", None, None, "")) else: self.tokens = [] unbalanced = self._sug_unbalanced_parens() if unbalanced: self.intro_text = ( "Unbalanced parentheses, brackets or braces:\n\n" + unbalanced.body ) self.intro_confidence = 5 else: self.intro_text = "Python doesn't know how to read your program." if "^" in str(self.error_info): self.intro_text += ( "\n\nSmall `^` in the original error message shows where it gave up," + " but the actual mistake can be before this." ) self.suggestions = [self._sug_missing_or_misplaced_colon()] def _sug_missing_or_misplaced_colon(self): i = 0 title = "Did you forget the colon?" relevance = 0 body = "" while i < len(self.tokens) and self.tokens[i].type != token.ENDMARKER: t = self.tokens[i] if t.string in [ "if", "elif", "else", "while", "for", "with", "try", "except", "finally", "class", "def", ]: keyword_pos = i while ( self.tokens[i].type not in [ token.NEWLINE, token.ENDMARKER, token.COLON, # colon may be OP token.RBRACE, ] and self.tokens[i].string != ":" ): old_i = i if self.tokens[i].string in "([{": i = self._skip_braced_part(i) assert i > old_i if i == len(self.tokens): return None else: i += 1 if self.tokens[i].string != ":": relevance = 9 body = "`%s` header must end with a colon." % t.string break # Colon was present, but maybe it should have been right # after the keyword. if ( t.string in ["else", "try", "finally"] and self.tokens[keyword_pos + 1].string != ":" ): title = "Incorrect use of `%s`" % t.string body = "Nothing is allowed between `%s` and colon." % t.string relevance = 9 if ( self.tokens[keyword_pos + 1].type not in (token.NEWLINE, tokenize.COMMENT) and t.string == "else" ): body = "If you want to specify a conditon, then use `elif` or nested `if`." break i += 1 return Suggestion("missing-or-misplaced-colon", title, body, relevance) def _sug_unbalanced_parens(self): problem = self._find_first_braces_problem() if not problem: return None return Suggestion("missing-or-misplaced-colon", "Unbalanced brackets", problem[1], 8) def _sug_wrong_increment_op(self): pass def _sug_wrong_decrement_op(self): pass def _sug_wrong_comparison_op(self): pass def _sug_switched_assignment_sides(self): pass def _skip_braced_part(self, token_index): assert self.tokens[token_index].string in ["(", "[", "{"] level = 1 token_index += 1 while token_index < len(self.tokens): if self.tokens[token_index].string in ["(", "[", "{"]: level += 1 elif self.tokens[token_index].string in [")", "]", "}"]: level -= 1 token_index += 1 if level <= 0: return token_index assert token_index == len(self.tokens) return token_index def _find_first_braces_problem(self): # closers = {'(':')', '{':'}', '[':']'} openers = {")": "(", "}": "{", "]": "["} brace_stack = [] for t in self.tokens: if t.string in ["(", "[", "{"]: brace_stack.append(t) elif t.string in [")", "]", "}"]: if not brace_stack: return ( t, "Found '`%s`' at `line %d <%s>`_ without preceding matching '`%s`'" % ( t.string, t.start[0], assistance.format_file_url( self.error_info["filename"], t.start[0], t.start[1] ), openers[t.string], ), ) elif brace_stack[-1].string != openers[t.string]: return ( t, "Found '`%s`' at `line %d <%s>`__ when last unmatched opener was '`%s`' at `line %d <%s>`__" % ( t.string, t.start[0], assistance.format_file_url( self.error_info["filename"], t.start[0], t.start[1] ), brace_stack[-1].string, brace_stack[-1].start[0], assistance.format_file_url( self.error_info["filename"], brace_stack[-1].start[0], brace_stack[-1].start[1], ), ), ) else: brace_stack.pop() if brace_stack: return ( brace_stack[-1], "'`%s`' at `line %d <%s>`_ is not closed by the end of the program" % ( brace_stack[-1].string, brace_stack[-1].start[0], assistance.format_file_url( self.error_info["filename"], brace_stack[-1].start[0], brace_stack[-1].start[1], ), ), ) return None class NameErrorHelper(ErrorHelper): def __init__(self, error_info): super().__init__(error_info) names = re.findall(r"\'.*\'", error_info["message"]) assert len(names) == 1 self.name = names[0].strip("'") self.intro_text = "Python doesn't know what `%s` stands for." % self.name self.suggestions = [ self._sug_bad_spelling(), self._sug_missing_quotes(), self._sug_missing_import(), self._sug_local_from_global(), self._sug_not_defined_yet(), ] def _sug_missing_quotes(self): if self._is_attribute_value() or self._is_call_function() or self._is_subscript_value(): relevance = 0 else: relevance = 5 return Suggestion( "missing-quotes", "Did you actually mean string (text)?", 'If you didn\'t mean a variable but literal text "%s", then surround it with quotes.' % self.name, relevance, ) def _sug_bad_spelling(self): # Yes, it would be more proper to consult builtins from the backend, # but it's easier this way... all_names = {name for name in dir(builtins) if not name.startswith("_")} all_names |= {"pass", "break", "continue", "return", "yield"} if self.last_frame.globals is not None: all_names |= set(self.last_frame.globals.keys()) if self.last_frame.locals is not None: all_names |= set(self.last_frame.locals.keys()) similar_names = {self.name} if all_names: relevance = 0 for name in all_names: sim = name_similarity(name, self.name) if sim > 4: similar_names.add(name) relevance = max(sim, relevance) else: relevance = 3 if len(similar_names) > 1: body = "I found similar names. Are all of them spelled correctly?\n\n" for name in sorted(similar_names, key=lambda x: x.lower()): # TODO: add location info body += "* `%s`\n\n" % name else: body = ( "Compare the name with corresponding definition / assignment / documentation." + " Don't forget that case of the letters matters!" ) return Suggestion("bad-spelling-name", "Did you misspell it (somewhere)?", body, relevance) def _sug_missing_import(self): likely_importable_functions = { "math": {"ceil", "floor", "sqrt", "sin", "cos", "degrees"}, "random": {"randint"}, "turtle": { "left", "right", "forward", "fd", "goto", "setpos", "Turtle", "penup", "up", "pendown", "down", "color", "pencolor", "fillcolor", "begin_fill", "end_fill", "pensize", "width", }, "re": {"search", "match", "findall"}, "datetime": {"date", "time", "datetime", "today"}, "statistics": { "mean", "median", "median_low", "median_high", "mode", "pstdev", "pvariance", "stdev", "variance", }, "os": {"listdir"}, "time": {"time", "sleep"}, } body = None if self._is_call_function(): relevance = 5 for mod in likely_importable_functions: if self.name in likely_importable_functions[mod]: relevance += 3 body = ( "If you meant `%s` from module `%s`, then add\n\n`from %s import %s`\n\nto the beginning of your script." % (self.name, mod, mod, self.name) ) break elif self._is_attribute_value(): relevance = 5 body = ( "If you meant module `%s`, then add `import %s` to the beginning of your script" % (self.name, self.name) ) if self.name in likely_importable_functions: relevance += 3 elif self._is_subscript_value() and self.name != "argv": relevance = 0 elif self.name == "pi": body = "If you meant the constant π, then add `from math import pi` to the beginning of your script." relevance = 8 elif self.name == "argv": body = "If you meant the list with program arguments, then add `from sys import argv` to the beginning of your script." relevance = 8 else: relevance = 3 if body is None: body = "Some functions/variables need to be imported before they can be used." return Suggestion("missing-import", "Did you forget to import it?", body, relevance) def _sug_local_from_global(self): relevance = 0 body = None if self.last_frame.code_name == "" and self.last_frame_module_ast is not None: function_names = set() for node in ast.walk(self.last_frame_module_ast): if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): if self.name in map(lambda x: x.arg, node.args.args): function_names.add(node.name) # TODO: varargs, kw, ... declared_global = False for localnode in ast.walk(node): # print(node.name, localnode) if ( isinstance(localnode, ast.Name) and localnode.id == self.name and isinstance(localnode.ctx, ast.Store) ): function_names.add(node.name) elif isinstance(localnode, ast.Global) and self.name in localnode.names: declared_global = True if node.name in function_names and declared_global: function_names.remove(node.name) if function_names: relevance = 9 body = ( ( "Name `%s` defined in `%s` is not accessible in the global/module level." % (self.name, " and ".join(function_names)) ) + "\n\nIf you need that data at the global level, then consider changing the function so that it `return`-s the value." ) return Suggestion( "local-from-global", "Are you trying to acces a local variable outside of the function?", body, relevance, ) def _sug_not_defined_yet(self): return Suggestion( "not-defined-yet", "Has Python executed the definition?", ( "Don't forget that name becomes defined when corresponding definition ('=', 'def' or 'import') gets executed." + " If the definition comes later in code or is inside an if-statement, Python may not have executed it (yet)." + "\n\n" + "Make sure Python arrives to the definition before it arrives to this line. When in doubt, " + "`use the debugger `_." ), 2, ) def _sug_maybe_attribute(self): "TODO:" def _sug_synonym(self): "TODO:" def _is_call_function(self): return self.name + "(" in ( self.error_info["line"].replace(" ", "").replace("\n", "").replace("\r", "") ) def _is_subscript_value(self): return self.name + "[" in ( self.error_info["line"].replace(" ", "").replace("\n", "").replace("\r", "") ) def _is_attribute_value(self): return self.name + "." in ( self.error_info["line"].replace(" ", "").replace("\n", "").replace("\r", "") ) class AttributeErrorHelper(ErrorHelper): def __init__(self, error_info): super().__init__(error_info) names = re.findall(r"\'.*?\'", error_info["message"]) assert len(names) == 2 self.type_name = names[0].strip("'") self.att_name = names[1].strip("'") self.intro_text = ( "Your program tries to " + ("call method " if self._is_call_function() else "access attribute ") + "`%s` of " % self.att_name + _get_phrase_for_object(self.type_name) + ", but this type doesn't have such " + ("method." if self._is_call_function() else "attribute.") ) self.suggestions = [ self._sug_wrong_attribute_instead_of_len(), self._sug_bad_spelling(), self._sug_bad_type(), ] def _sug_wrong_attribute_instead_of_len(self): if self.type_name == "str": goal = "length" elif self.type_name == "bytes": goal = "number of bytes" elif self.type_name == "list": goal = "number of elements" elif self.type_name == "tuple": goal = "number of elements" elif self.type_name == "set": goal = "number of elements" elif self.type_name == "dict": goal = "number of entries" else: return return Suggestion( "wrong-attribute-instead-of-len", "Did you mean to ask the %s?" % goal, "This can be done with function `len`, eg:\n\n`len(%s)`" % _get_sample_for_type(self.type_name), (9 if self.att_name.lower() in ("len", "length", "size") else 0), ) def _sug_bad_spelling(self): # TODO: compare with attributes of known types return Suggestion( "bad-spelling-attribute", "Did you misspell the name?", "Don't forget that case of the letters matters too!", 3, ) def _sug_bad_type(self): if self._is_call_function(): action = "call this function on" else: action = "ask this attribute from" return Suggestion( "wrong-type-attribute", "Did you expect another type?", "If you didn't mean %s %s, " % (action, _get_phrase_for_object(self.type_name)) + "then step through your program to see " + "why this type appears here.", 3, ) def _is_call_function(self): return "." + self.att_name + "(" in ( self.error_info["line"].replace(" ", "").replace("\n", "").replace("\r", "") ) class OSErrorHelper(ErrorHelper): def __init__(self, error_info): super().__init__(error_info) if "Address already in use" in self.error_info["message"]: self.intro_text = "Your programs tries to listen on a port which is already taken." self.suggestions = [ Suggestion( "kill-by-port-type-error", "Want to close the other process?", self.get_kill_process_instructions(), 5, ), Suggestion( "use-another-type-error", "Can you use another port?", "If you don't want to mess with the other process, then check whether" + " you can configure your program to use another port.", 3, ), ] else: self.intro_text = "No specific information is available for this error." def get_kill_process_instructions(self): s = ( "Let's say you need port 5000. If you don't know which process is using it," + " then enter following system command into Thonny's Shell:\n\n" ) if running_on_windows(): s += ( "``!netstat -ano | findstr :5000``\n\n" + "You should see the process ID in the last column.\n\n" ) else: s += ( "``!lsof -i:5000``\n\n" + "You should see the process ID under the heading PID.\n\n" ) s += ( "Let's pretend the ID is 12345." " You can try hard-killing the process with following command:\n\n" ) if running_on_windows(): s += "``!tskill 12345``\n" else: s += ( "``!kill -9 12345``\n\n" + "Both steps can be combined into single command:\n\n" + "``!kill -9 $(lsof -t -i:5000)``\n\n" ) return s class TypeErrorHelper(ErrorHelper): def __init__(self, error_info): super().__init__(error_info) self.intro_text = ( "Python was asked to do an operation with an object which " + "doesn't support it." ) self.suggestions = [ Suggestion( "step-to-find-type-error", "Did you expect another type?", "Step through your program to see why this type appears here.", 3, ), Suggestion( "look-documentation-type-error", "Maybe you forgot some details about this operation?", "Look up the documentation or perform a web search with the error message.", 2, ), ] # overwrite / add for special cases # something + str or str + something for r, string_first in [ (r"unsupported operand type\(s\) for \+: '(.+?)' and 'str'", False), (r"^Can't convert '(.+?)' object to str implicitly$", True), # Python 3.5 (r"^must be str, not (.+)$", True), # Python 3.6 (r'^can only concatenate str (not "(.+?)") to str$', True), # Python 3.7 ]: m = re.match(r, error_info["message"], re.I) # @UndefinedVariable if m is not None: self._bad_string_concatenation(m.group(1), string_first) return # TODO: other operations, when one side is string def _bad_string_concatenation(self, other_type_name, string_first): self.intro_text = "Your program is trying to put together " + ( "a string and %s." if string_first else "%s and a string." ) % _get_phrase_for_object(other_type_name) self.suggestions.append( Suggestion( "convert-other-operand-to-string", "Did you mean to treat both sides as text and produce a string?", "In this case you should apply function `str` to the %s " % _get_phrase_for_object(other_type_name, False) + "in order to convert it to string first, eg:\n\n" + ("`'abc' + str(%s)`" if string_first else "`str(%s) + 'abc'`") % _get_sample_for_type(other_type_name), 8, ) ) if other_type_name in ("float", "int"): self.suggestions.append( Suggestion( "convert-other-operand-to-number", "Did you mean to treat both sides as numbers and produce a sum?", "In this case you should first convert the string to a number " + "using either function `float` or `int`, eg:\n\n" + ("`float('3.14') + 22`" if string_first else "`22 + float('3.14')`"), 7, ) ) def _get_phrase_for_object(type_name, with_article=True): friendly_names = { "str": "a string", "int": "an integer", "float": "a float", "list": "a list", "tuple": "a tuple", "dict": "a dictionary", "set": "a set", "bool": "a boolean", } result = friendly_names.get(type_name, "an object of type '%s'" % type_name) if with_article: return result else: _, rest = result.split(" ", maxsplit=1) return rest def _get_sample_for_type(type_name): if type_name == "int": return "42" elif type_name == "float": return "3.14" elif type_name == "str": return "'abc'" elif type_name == "bytes": return "b'abc'" elif type_name == "list": return "[1, 2, 3]" elif type_name == "tuple": return "(1, 2, 3)" elif type_name == "set": return "{1, 2, 3}" elif type_name == "dict": return "{1 : 'one', 2 : 'two'}" else: return "..." def load_plugin(): for name in globals(): if name.endswith("ErrorHelper") and not name.startswith("_"): type_name = name[: -len("Helper")] add_error_helper(type_name, globals()[name]) thonny-3.2.7/thonny/plugins/backend_config_page.py0000644000175000017500000001035013611773167023351 0ustar annamaaannamaa00000000000000import tkinter as tk from tkinter import ttk from thonny import get_runner, get_workbench from thonny.config_ui import ConfigurationPage from thonny.ui_utils import create_string_var class BackendDetailsConfigPage(ConfigurationPage): def should_restart(self): raise NotImplementedError() class OnlyTextConfigurationPage(BackendDetailsConfigPage): def __init__(self, master, text): super().__init__(master) label = ttk.Label(self, text=text) label.grid() def should_restart(self): return False class BackendConfigurationPage(ConfigurationPage): def __init__(self, master): ConfigurationPage.__init__(self, master) self._backend_specs_by_desc = { spec.description: spec for spec in get_workbench().get_backends().values() } self._conf_pages = {} self._current_page = None current_backend_name = get_workbench().get_option("run.backend_name") try: current_backend_desc = get_workbench().get_backends()[current_backend_name].description except KeyError: current_backend_desc = "" self._combo_variable = create_string_var(current_backend_desc) label = ttk.Label( self, text=_("Which interpreter or device should Thonny use for running your code?") ) label.grid(row=0, column=0, columnspan=2, sticky=tk.W) sorted_backend_specs = sorted( self._backend_specs_by_desc.values(), key=lambda x: x.sort_key ) self._combo = ttk.Combobox( self, exportselection=False, textvariable=self._combo_variable, values=[spec.description for spec in sorted_backend_specs], ) self._combo.grid(row=1, column=0, columnspan=2, sticky=tk.NSEW, pady=(0, 10)) self._combo.state(["!disabled", "readonly"]) self.labelframe = ttk.LabelFrame(self, text=" " + _("Details") + " ") self.labelframe.grid(row=2, column=0, sticky="nsew") self.labelframe.columnconfigure(0, weight=1) self.labelframe.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.rowconfigure(2, weight=1) self._combo_variable.trace("w", self._backend_changed) self._backend_changed() def _backend_changed(self, *args): backend_desc = self._combo_variable.get() if backend_desc == "": if self._current_page is not None: self._current_page.grid_forget() return page = self._get_conf_page(backend_desc) if page != self._current_page: if self._current_page is not None: self._current_page.grid_forget() page.grid(sticky="nsew", padx=10, pady=5) self._current_page = page def _get_conf_page(self, backend_desc): if backend_desc not in self._conf_pages: cp_constructor = self._backend_specs_by_desc[backend_desc].config_page_constructor if isinstance(cp_constructor, str): self._conf_pages[backend_desc] = OnlyTextConfigurationPage( self.labelframe, cp_constructor ) else: assert issubclass(cp_constructor, ConfigurationPage) self._conf_pages[backend_desc] = cp_constructor(self.labelframe) return self._conf_pages[backend_desc] def apply(self): if self._current_page is None: return None result = self._current_page.apply() if result is False: return False backend_desc = self._combo_variable.get() backend_name = self._backend_specs_by_desc[backend_desc].name get_workbench().set_option("run.backend_name", backend_name) if getattr(self._combo_variable, "modified") or self._current_page.should_restart(): get_runner().restart_backend(False) return None def load_plugin() -> None: def select_device(): get_workbench().show_options("interpreter") get_workbench().add_configuration_page( "interpreter", _("Interpreter"), BackendConfigurationPage, 20 ) get_workbench().add_command( "select_interpreter", "run", _("Select interpreter") + "...", select_device, group=1 ) thonny-3.2.7/thonny/plugins/dock_user_windows_frontend.py0000644000175000017500000000141313611773167025070 0ustar annamaaannamaa00000000000000import os from thonny import get_workbench _OPTION_NAME = "run.dock_user_windows" def toggle_variable(): var = get_workbench().get_variable(_OPTION_NAME) var.set(not var.get()) update_environment() def update_environment(): os.environ["DOCK_USER_WINDOWS"] = str(get_workbench().get_option(_OPTION_NAME)) def on_window_appear(event): get_workbench().become_active_window(force=False) def load_plugin(): get_workbench().set_default(_OPTION_NAME, False) get_workbench().add_command( "toggle_dock_user_windows", "run", _("Dock user windows"), toggle_variable, flag_name=_OPTION_NAME, group=40, ) update_environment() get_workbench().bind("UserWindowAppeared", on_window_appear, True) thonny-3.2.7/thonny/plugins/base_syntax_themes.py0000644000175000017500000004532513611773167023340 0ustar annamaaannamaa00000000000000from thonny import get_workbench from thonny.workbench import SyntaxThemeSettings def default_light() -> SyntaxThemeSettings: default_fg = "black" default_bg = "#fdfdfd" light_fg = "DarkGray" string_fg = "DarkGreen" open_string_bg = "#c3f9d3" gutter_foreground = "#999999" gutter_background = "#e0e0e0" return { "TEXT": { "foreground": default_fg, "insertbackground": default_fg, "background": default_bg, }, "GUTTER": {"foreground": gutter_foreground, "background": gutter_background}, "breakpoint": {"foreground": "crimson"}, "current_line": {"background": "#f5f5f5"}, "definition": {"foreground": "DarkBlue", "font": "BoldEditorFont"}, "string": {"foreground": string_fg}, "string3": {"foreground": string_fg, "background": None, "font": "EditorFont"}, "open_string": {"foreground": string_fg, "background": open_string_bg}, "open_string3": { "foreground": string_fg, "background": open_string_bg, "font": "EditorFont", }, "keyword": {"foreground": "#7f0055", "font": "BoldEditorFont"}, "builtin": {"foreground": "#7f0055"}, "number": {"foreground": "#B04600"}, "comment": {"foreground": light_fg}, "welcome": {"foreground": light_fg}, "magic": {"foreground": light_fg}, "prompt": {"foreground": "purple", "font": "BoldEditorFont"}, "stdin": {"foreground": "Blue"}, "stdout": {"foreground": "Black"}, "stderr": {"foreground": "#CC0000"}, # same as ANSI red "value": {"foreground": "DarkBlue"}, "hyperlink": {"foreground": "#3A66DD", "underline": True}, # paren matcher "surrounding_parens": {"foreground": "Blue", "font": "BoldEditorFont"}, "unclosed_expression": {"background": "LightGray"}, # find/replace "found": {"foreground": "blue", "underline": True}, "current_found": {"foreground": "white", "background": "red"}, "matched_name": {"background": "#e6ecfe"}, "local_name": {"font": "ItalicEditorFont"}, # debugger "active_focus": {"background": "#F8FC9A", "borderwidth": 1, "relief": "solid"}, "suspended_focus": {"background": "", "borderwidth": 1, "relief": "solid"}, "completed_focus": {"background": "#BBEDB2", "borderwidth": 1, "relief": "flat"}, "exception_focus": {"background": "#FFBFD6", "borderwidth": 1, "relief": "solid"}, "expression_box": {"background": "#DCEDF2", "foreground": default_fg}, "black_fg": {"foreground": "#2E3436"}, "black_bg": {"background": "#2E3436"}, "bright_black_fg": {"foreground": "#555753"}, "bright_black_bg": {"background": "#555753"}, "dim_black_fg": {"foreground": "#1E2224"}, "dim_black_bg": {"background": "#1E2224"}, "red_fg": {"foreground": "#CC0000"}, "red_bg": {"background": "#CC0000"}, "bright_red_fg": {"foreground": "#EF2929"}, "bright_red_bg": {"background": "#EF2929"}, "dim_red_fg": {"foreground": "#880000"}, "dim_red_bg": {"background": "#880000"}, "green_fg": {"foreground": "#4E9A06"}, "green_bg": {"background": "#4E9A06"}, "bright_green_fg": {"foreground": "#8AE234"}, "bright_green_bg": {"background": "#8AE234"}, "dim_green_fg": {"foreground": "#346704"}, "dim_green_bg": {"background": "#346704"}, "yellow_fg": {"foreground": "#C4A000"}, "yellow_bg": {"background": "#C4A000"}, "bright_yellow_fg": {"foreground": "#FCE94F"}, "bright_yellow_bg": {"background": "#FCE94F"}, "dim_yellow_fg": {"foreground": "#836B00"}, "dim_yellow_bg": {"background": "#836B00"}, "blue_fg": {"foreground": "#3465A4"}, "blue_bg": {"background": "#3465A4"}, "bright_blue_fg": {"foreground": "#729FCF"}, "bright_blue_bg": {"background": "#729FCF"}, "dim_blue_fg": {"foreground": "#22436D"}, "dim_blue_bg": {"background": "#22436D"}, "magenta_fg": {"foreground": "#75507B"}, "magenta_bg": {"background": "#75507B"}, "bright_magenta_fg": {"foreground": "#AD7FA8"}, "bright_magenta_bg": {"background": "#AD7FA8"}, "dim_magenta_fg": {"foreground": "#4E3552"}, "dim_magenta_bg": {"background": "#4E3552"}, "cyan_fg": {"foreground": "#06989A"}, "cyan_bg": {"background": "#06989A"}, "bright_cyan_fg": {"foreground": "#34E2E2"}, "bright_cyan_bg": {"background": "#34E2E2"}, "dim_cyan_fg": {"foreground": "#046567"}, "dim_cyan_bg": {"background": "#046567"}, "white_fg": {"foreground": "#D3D7CF"}, "white_bg": {"background": "#D3D7CF"}, "bright_white_fg": {"foreground": "#EEEEEC"}, "bright_white_bg": {"background": "#EEEEEC"}, "dim_white_fg": {"foreground": "#8D8F8A"}, "dim_white_bg": {"background": "#8D8F8A"}, "fore_fg": {"foreground": default_fg}, "fore_bg": {"background": default_fg}, "bright_fore_fg": {"foreground": "#000000"}, "bright_fore_bg": {"background": "#000000"}, "dim_fore_fg": {"foreground": "#222222"}, "dim_fore_bg": {"background": "#222222"}, "back_fg": {"foreground": default_bg}, "back_bg": {"background": default_bg}, "bright_back_fg": {"foreground": "#ffffff"}, "bright_back_bg": {"background": "#ffffff"}, "dim_back_fg": {"foreground": "#e0e0e0"}, "dim_back_bg": {"background": "#e0e0e0"}, "intense_io": {"font": "BoldIOFont"}, "italic_io": {"font": "ItalicIOFont"}, "intense_italic_io": {"font": "BoldItalicIOFont"}, "underline": {"underline": True}, "strikethrough": {"overstrike": True}, } def default_dark() -> SyntaxThemeSettings: default_fg = "#B3B3B3" default_bg = "#2d2d2d" string_fg = "#8DC76F" open_string_bg = "#224533" gutter_foreground = "#606060" gutter_background = "#323232" # s.configure("Local.Code", foreground="#BCCAE8") # s.configure("MatchedName.Code", background="#193022") return { "TEXT": { "foreground": default_fg, "insertbackground": default_fg, "background": default_bg, }, "GUTTER": {"foreground": gutter_foreground, "background": gutter_background}, "breakpoint": {"foreground": "pink"}, "current_line": {"background": "#363636"}, "sel": {"foreground": "#eeeeee", "background": "#6E6E6E"}, "definition": {"foreground": default_fg}, "string": {"foreground": string_fg}, "string3": {"foreground": string_fg, "background": None, "font": "EditorFont"}, "open_string": {"foreground": string_fg, "background": open_string_bg}, "open_string3": { "foreground": string_fg, "background": open_string_bg, "font": "EditorFont", }, "builtin": {"foreground": "#A9B1C9"}, "keyword": {"foreground": "#A9B1C9", "font": "BoldEditorFont"}, "number": {"foreground": "#FFCABF"}, "comment": {"foreground": "#D4D44E"}, "welcome": {"foreground": "pink"}, "magic": {"foreground": "pink"}, # shell "prompt": {"foreground": "#5BEBBB", "font": "BoldEditorFont"}, "stdin": {"foreground": "LightBlue"}, "stdout": {"foreground": "LightGray"}, "stderr": {"foreground": "#EB5B83"}, "value": {"foreground": "#EBEB5B"}, "hyperlink": {"foreground": "#619DC7", "underline": True}, # paren matcher "surrounding_parens": {"foreground": "#F0995B", "font": "BoldEditorFont"}, "unclosed_expression": {"background": "#000000"}, # find/replace "found": {"underline": True}, "current_found": {"foreground": "white", "background": "red"}, "matched_name": {"background": "#474747"}, "local_name": {"font": "ItalicEditorFont"}, # debugger "active_focus": {"background": "#807238", "borderwidth": 1, "relief": "solid"}, "suspended_focus": {"background": "", "borderwidth": 1, "relief": "solid"}, "completed_focus": {"background": "#807238", "borderwidth": 1, "relief": "flat"}, "exception_focus": {"background": "#FFBFD6", "borderwidth": 1, "relief": "solid"}, "expression_box": {"background": "#506E67", "foreground": default_fg}, "black_fg": {"foreground": "#2E3436"}, "black_bg": {"background": "#2E3436"}, "bright_black_fg": {"foreground": "#555753"}, "bright_black_bg": {"background": "#555753"}, "dim_black_fg": {"foreground": "#1E2224"}, "dim_black_bg": {"background": "#1E2224"}, "red_fg": {"foreground": "#CC0000"}, "red_bg": {"background": "#CC0000"}, "bright_red_fg": {"foreground": "#EF2929"}, "bright_red_bg": {"background": "#EF2929"}, "dim_red_fg": {"foreground": "#880000"}, "dim_red_bg": {"background": "#880000"}, "green_fg": {"foreground": "#4E9A06"}, "green_bg": {"background": "#4E9A06"}, "bright_green_fg": {"foreground": "#8AE234"}, "bright_green_bg": {"background": "#8AE234"}, "dim_green_fg": {"foreground": "#346704"}, "dim_green_bg": {"background": "#346704"}, "yellow_fg": {"foreground": "#C4A000"}, "yellow_bg": {"background": "#C4A000"}, "bright_yellow_fg": {"foreground": "#FCE94F"}, "bright_yellow_bg": {"background": "#FCE94F"}, "dim_yellow_fg": {"foreground": "#836B00"}, "dim_yellow_bg": {"background": "#836B00"}, "blue_fg": {"foreground": "#3465A4"}, "blue_bg": {"background": "#3465A4"}, "bright_blue_fg": {"foreground": "#729FCF"}, "bright_blue_bg": {"background": "#729FCF"}, "dim_blue_fg": {"foreground": "#22436D"}, "dim_blue_bg": {"background": "#22436D"}, "magenta_fg": {"foreground": "#75507B"}, "magenta_bg": {"background": "#75507B"}, "bright_magenta_fg": {"foreground": "#AD7FA8"}, "bright_magenta_bg": {"background": "#AD7FA8"}, "dim_magenta_fg": {"foreground": "#4E3552"}, "dim_magenta_bg": {"background": "#4E3552"}, "cyan_fg": {"foreground": "#06989A"}, "cyan_bg": {"background": "#06989A"}, "bright_cyan_fg": {"foreground": "#34E2E2"}, "bright_cyan_bg": {"background": "#34E2E2"}, "dim_cyan_fg": {"foreground": "#046567"}, "dim_cyan_bg": {"background": "#046567"}, "white_fg": {"foreground": "#D3D7CF"}, "white_bg": {"background": "#D3D7CF"}, "bright_white_fg": {"foreground": "#EEEEEC"}, "bright_white_bg": {"background": "#EEEEEC"}, "dim_white_fg": {"foreground": "#8D8F8A"}, "dim_white_bg": {"background": "#8D8F8A"}, "fore_fg": {"foreground": default_fg}, "fore_bg": {"background": default_fg}, "bright_fore_fg": {"foreground": "#ffffff"}, "bright_fore_bg": {"background": "#ffffff"}, "dim_fore_fg": {"foreground": "#e0e0e0"}, "dim_fore_bg": {"background": "#e0e0e0"}, "back_fg": {"foreground": default_bg}, "back_bg": {"background": default_bg}, "bright_back_fg": {"foreground": "#000000"}, "bright_back_bg": {"background": "#000000"}, "dim_back_fg": {"foreground": "#222222"}, "dim_back_bg": {"background": "#222222"}, "intense_io": {"font": "BoldIOFont"}, "italic_io": {"font": "ItalicIOFont"}, "intense_italic_io": {"font": "BoldItalicIOFont"}, "underline": {"underline": True}, "strikethrough": {"overstrike": True}, } def default_dark_green() -> SyntaxThemeSettings: open_string_bg = "#453B22" gutter_background = "#33402F" return { "TEXT": {"background": "#273627"}, "GUTTER": {"background": gutter_background}, "current_line": {"background": "#2E402E"}, "sel": {"background": "#6E6E6E"}, "unclosed_expression": {"background": "#0F1F15"}, "open_string": {"background": open_string_bg}, "open_string3": {"background": open_string_bg}, "keyword": {"foreground": "#88CFB6", "font": "BoldEditorFont"}, "builtin": {"foreground": "#88CFB6"}, # debugger "active_focus": {"background": "#807238"}, "completed_focus": {"background": "#807238"}, "exception_focus": {"background": "#FFBFD6"}, "expression_box": {"background": "#506E67"}, } def default_dark_blue() -> SyntaxThemeSettings: open_string_bg = "#224533" gutter_background = "#2F3640" return { "TEXT": {"background": "#272936"}, "GUTTER": {"background": gutter_background}, "current_line": {"background": "#2D3040"}, "sel": {"background": "#6E6E6E"}, "unclosed_expression": {"background": "#100B21"}, "open_string": {"background": open_string_bg}, "open_string3": {"background": open_string_bg}, "keyword": {"foreground": "#8899CF", "font": "BoldEditorFont"}, "builtin": {"foreground": "#8899CF"}, # debugger "active_focus": {"background": "#807238"}, "completed_focus": {"background": "#807238"}, "exception_focus": {"background": "#FFBFD6"}, "expression_box": {"background": "#506E67"}, } def idle_classic() -> SyntaxThemeSettings: string_fg = "#00aa00" return { "TEXT": {"foreground": "black", "insertbackground": "black", "background": "white"}, "GUTTER": {"foreground": "gray", "background": "#efefef"}, "sel": {"foreground": "black", "background": "gray"}, "number": {"foreground": "black"}, "definition": {"foreground": "#0000ff", "font": "EditorFont"}, "string": {"foreground": string_fg}, "string3": {"foreground": string_fg}, "open_string": {"foreground": string_fg}, "open_string3": {"foreground": string_fg}, "keyword": {"foreground": "#ff7700", "font": "EditorFont"}, "builtin": {"foreground": "#900090"}, "comment": {"foreground": "#dd0000"}, "prompt": {"foreground": "#770000"}, "stdin": {"foreground": "black"}, "stdout": {"foreground": "Blue"}, "value": {"foreground": "Blue"}, "stderr": {"foreground": "Red"}, "found": {"foreground": "", "underline": True}, "current_found": {"foreground": "white", "background": "black"}, } def idle_dark() -> SyntaxThemeSettings: normal_fg = "white" string_fg = "#02ff02" return { "TEXT": {"foreground": normal_fg, "insertbackground": normal_fg, "background": "#002240"}, "sel": {"foreground": "#FFFFFF", "background": "#7e7e7e"}, "number": {"foreground": normal_fg}, "definition": {"foreground": "#5e5eff", "font": "EditorFont"}, "string": {"foreground": string_fg}, "string3": {"foreground": string_fg}, "open_string": {"foreground": string_fg}, "open_string3": {"foreground": string_fg}, "keyword": {"foreground": "#ff8000", "font": "EditorFont"}, "builtin": {"foreground": "#ff00ff"}, "comment": {"foreground": "#dd0000"}, "welcome": {"foreground": "#dd0000"}, "prompt": {"foreground": "#ff4d4d"}, "stdin": {"foreground": normal_fg}, "stdout": {"foreground": "#c2d1fa"}, "value": {"foreground": "#c2d1fa"}, "stderr": {"foreground": "#ffb3b3"}, "found": {"foreground": "", "underline": True}, "current_found": {"foreground": "#002240", "background": "#fbfbfb"}, } def desert_sunset() -> SyntaxThemeSettings: normal_fg = "#f0e68c" string_fg = "#ffa0a0" return { "TEXT": {"foreground": normal_fg, "insertbackground": normal_fg, "background": "#333333"}, "GUTTER": {"foreground": "gray", "background": "#404040"}, "sel": {"foreground": "#000000", "background": "gray"}, "number": {"foreground": normal_fg}, "definition": {"foreground": "#98fb98"}, "string": {"foreground": string_fg}, "string3": {"foreground": string_fg}, "open_string": {"foreground": string_fg}, "open_string3": {"foreground": string_fg}, "keyword": {"foreground": "#cc6600"}, "builtin": {"foreground": "#519e51"}, "comment": {"foreground": "#87ceeb"}, "welcome": {"foreground": "#87ceeb"}, "prompt": {"foreground": "#87ceeb"}, "stdin": {"foreground": normal_fg}, "stdout": {"foreground": "#eeeeee"}, "value": {"foreground": "#eeeeee"}, "stderr": {"foreground": "#ff595b"}, "found": {"foreground": "", "underline": True}, "current_found": {"foreground": "#ffffff", "background": "#333333"}, } def zenburn() -> SyntaxThemeSettings: # https://github.com/mig/gedit-themes/blob/master/zenburn.xml # https://github.com/trusktr/gedit-color-schemes/blob/master/gtksourceview-3.0/styles/zenburn.xml normal_fg = "#dcdccc" string_fg = "#cc9393" return { "TEXT": {"foreground": normal_fg, "insertbackground": normal_fg, "background": "#3f3f3f"}, "GUTTER": {"foreground": "#7f8f8f", "background": "#464646"}, "current_line": {"background": "#4A4A4A"}, "sel": {"foreground": "white", "background": "#506070"}, "number": {"foreground": "#8cd0d3"}, "definition": {"foreground": "#f4a020", "font": "BoldEditorFont"}, "string": {"foreground": string_fg}, "string3": {"foreground": string_fg}, "open_string": {"foreground": string_fg}, "open_string3": {"foreground": string_fg}, "keyword": {"foreground": "#f0dfaf", "font": "BoldEditorFont"}, "builtin": {"foreground": "#efef8f"}, "comment": {"foreground": "#7f9f7f"}, "welcome": {"foreground": "#7f9f7f"}, "prompt": {"foreground": "#87ceeb"}, "stdin": {"foreground": normal_fg}, "stdout": {"foreground": "#eeeeee"}, "value": {"foreground": "#eeeeee"}, "stderr": {"foreground": "#ff3e40"}, # paren matcher "surrounding_parens": {"foreground": "white", "font": "BoldEditorFont"}, } def load_plugin() -> None: get_workbench().add_syntax_theme("Default Light", None, default_light) get_workbench().add_syntax_theme("Default Dark", None, default_dark) get_workbench().add_syntax_theme("Default Dark Green", "Default Dark", default_dark_green) get_workbench().add_syntax_theme("Default Dark Blue", "Default Dark", default_dark_blue) get_workbench().add_syntax_theme("Desert Sunset", "Default Dark", desert_sunset) get_workbench().add_syntax_theme("Zenburn", "Default Dark", zenburn) get_workbench().add_syntax_theme("IDLE Classic", "Default Light", idle_classic) # Comments in IDLE Dark really hurt the eyes # get_workbench().add_syntax_theme("IDLE Dark", "Default Dark", idle_dark) get_workbench().set_default("view.syntax_theme", "Default Light") thonny-3.2.7/thonny/plugins/remove_old_data_dir.py0000644000175000017500000000253613611773167023432 0ustar annamaaannamaa00000000000000import os.path from tkinter.messagebox import askyesno, showinfo from thonny import get_workbench, THONNY_USER_DIR import shutil def load_plugin(): old_data_dir = os.path.join(os.path.expanduser("~"), ".thonny") if os.path.exists(old_data_dir): def doit(): if not os.path.exists(old_data_dir): showinfo("Already deleted", "Looks like it's already deleted") return answer = askyesno( "Delete old data directory?", "Thonny versions before 3.0 (and first 3.0 betas) used to keep " + "configuration, logs and such in '%s'" % old_data_dir + ". " + "Since 3.0 this data is kept in a new location: '%s'.\n\n" % THONNY_USER_DIR + "If you don't intend to use older Thonny versions anymore, " + "you probably want to delete the old directory and reclaim disk space.\n\n" + "Do you want me to delete this directory now?", ) if answer: shutil.rmtree(old_data_dir, True) shutil.rmtree(old_data_dir, True) # first one may keep empty directory showinfo("Done!", "Done!") get_workbench().add_command( "delolddatadir", "tools", "Clean up Thonny 2.1 data folder ...", doit, group=110 ) thonny-3.2.7/thonny/plugins/files.py0000644000175000017500000002342513611773167020552 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import os import tkinter as tk from thonny import get_workbench, get_runner, get_shell from thonny.base_file_browser import BaseLocalFileBrowser, BaseRemoteFileBrowser from thonny.ui_utils import lookup_style_option from thonny.common import normpath_with_actual_case, InlineCommand from thonny.running import construct_cd_command from thonny.misc_utils import running_on_windows from tkinter import messagebox minsize = 80 class FilesView(tk.PanedWindow): def __init__(self, master=None): tk.PanedWindow.__init__(self, master, orient="vertical", borderwidth=0) self.remote_added = False self.configure(sashwidth=lookup_style_option("Sash", "sashthickness", 4)) self.configure(background=lookup_style_option("TPanedWindow", "background")) get_workbench().bind("BackendTerminated", self.on_backend_terminate, True) get_workbench().bind("BackendRestart", self.on_backend_restart, True) get_workbench().bind("WorkbenchClose", self.on_workbench_close, True) self.local_files = ActiveLocalFileBrowser(self) self.local_files.check_update_focus() self.add(self.local_files, minsize=minsize) self.remote_files = ActiveRemoteFileBrowser(self) self.reset_remote() def on_show(self): self.reset_remote() self.local_files.refresh_tree() def reset_remote(self, msg=None): runner = get_runner() if not runner: return proxy = runner.get_backend_proxy() if not proxy: self.hide_remote() return if proxy.supports_remote_files(): # remote pane is needed if not self.remote_added: self.add(self.remote_files, before=self.local_files, minsize=minsize) self.remote_added = True self.restore_split() self.remote_files.clear() self.remote_files.check_update_focus() else: # remote pane not needed self.hide_remote() def hide_remote(self): if self.remote_added: self.save_split() self.remove(self.remote_files) self.remote_added = False def save_split(self): _, y = self.sash_coord(0) get_workbench().set_option("view.files_split", y) def restore_split(self): split = get_workbench().get_option("view.files_split", None) if split is None: if self.winfo_height() > 5: split = int(self.winfo_height() * 0.66) else: split = 600 self.sash_place(0, 0, split) def on_backend_restart(self, event): if event.get("full"): self.reset_remote(event) def on_backend_terminate(self, event): self.reset_remote(event) def on_workbench_close(self, event=None): if self.remote_added: self.save_split() def get_active_local_dir(self): return self.local_files.get_active_directory() def get_active_remote_dir(self): if self.remote_added: return self.remote_files.get_active_directory() else: return None def destroy(self): get_workbench().unbind("BackendTerminated", self.on_backend_terminate) get_workbench().unbind("BackendRestart", self.on_backend_restart) get_workbench().unbind("WorkbenchClose", self.on_workbench_close) super().destroy() class ActiveLocalFileBrowser(BaseLocalFileBrowser): def __init__(self, master, show_hidden_files=False): super().__init__(master, show_hidden_files) get_workbench().bind("ToplevelResponse", self.on_toplevel_response, True) def create_new_file(self): path = super().create_new_file() if path and path.endswith(".py"): get_workbench().get_editor_notebook().show_file(path) def get_proposed_new_file_name(self, folder, extension): base = "new_file" if os.path.exists(os.path.join(folder, base + extension)): i = 2 while True: name = base + "_" + str(i) + extension path = os.path.join(folder, name) if os.path.exists(path): i += 1 else: return name else: return base + extension def request_focus_into(self, path): if path == "": if running_on_windows(): # list of drives, can't cd return self.focus_into(path) else: path = "/" if not os.path.isdir(path): return proxy = get_runner().get_backend_proxy() if ( proxy and proxy.uses_local_filesystem() and proxy.get_cwd() != path and get_runner().is_waiting_toplevel_command() ): get_shell().submit_magic_command(construct_cd_command(path)) else: # it's OK, if it's already focused into this directory # focus again to refresh self.focus_into(path) get_workbench().set_local_cwd(path) def on_toplevel_response(self, event): self.check_update_focus() def check_update_focus(self): cwd = get_workbench().get_local_cwd() if cwd != self.current_focus and os.path.isdir(cwd): self.focus_into(cwd) def check_add_upload_command(self): target_dir = self.master.get_active_remote_dir() if target_dir is None: return proxy = get_runner().get_backend_proxy() if not proxy.supports_remote_directories(): target_dir_desc = proxy.get_node_label() else: target_dir_desc = target_dir def upload(): selection = self.get_selection_info(True) if not selection: return if "dir" in selection["kinds"] and not proxy.supports_remote_directories(): messagebox.showerror( "Can't upload directory", "%s does not support directories.\n" % proxy.get_node_label() + "You can only upload files.", ) else: response = get_runner().send_command( InlineCommand( "upload", allow_overwrite=False, source_paths=selection["paths"], target_dir=target_dir, blocking=True, description=_("Uploading %s to %s") % (selection["description"], target_dir), ) ) check_upload_download_response("upload", response) self.master.remote_files.refresh_tree() self.menu.add_command(label=_("Upload to %s") % target_dir_desc, command=upload) def add_middle_menu_items(self): self.check_add_upload_command() super().add_middle_menu_items() class ActiveRemoteFileBrowser(BaseRemoteFileBrowser): def __init__(self, master, show_hidden_files=False): super().__init__(master, show_hidden_files) get_workbench().bind("ToplevelResponse", self.on_toplevel_response, True) def on_toplevel_response(self, event): if get_runner().get_backend_proxy().supports_remote_files(): self.check_update_focus() def check_update_focus(self): proxy = get_runner().get_backend_proxy() if self.current_focus != proxy.get_cwd(): self.focus_into(proxy.get_cwd()) def request_new_focus(self, path): get_shell().submit_magic_command(["%cd", path if path != "" else "/"]) def add_download_command(self): target_dir = self.master.get_active_local_dir() def download(): selection = self.get_selection_info(True) if not selection: return response = get_runner().send_command( InlineCommand( "download", allow_overwrite=False, source_paths=selection["paths"], target_dir=target_dir, blocking=True, description=_("Downloading %s to %s") % (selection["description"], target_dir), ) ) check_upload_download_response("download", response) self.master.local_files.refresh_tree() self.menu.add_command(label=_("Download to %s") % target_dir, command=download) def add_middle_menu_items(self): self.add_download_command() super().add_middle_menu_items() def check_upload_download_response(command_name, command_response): if command_response and command_response.get("existing_files"): # command was not performed because overwriting existing files need confirmation existing = sorted(command_response["existing_files"][:25]) if len(command_response["existing_files"]) > 25: existing.append("...") user_response = messagebox.askokcancel( "Overwriting", "Some file(s) will be overwritten:\n\n" + " " + "\n ".join(existing), icon="info", ) if not user_response: return else: get_runner().send_command( InlineCommand( command_name, allow_overwrite=True, source_paths=command_response["source_paths"], target_dir=command_response["target_dir"], blocking=True, description=command_response["description"], ) ) def load_plugin() -> None: get_workbench().set_default( "file.last_browser_folder", normpath_with_actual_case(os.path.expanduser("~")) ) get_workbench().add_view(FilesView, _("Files"), "nw") thonny-3.2.7/thonny/plugins/misc_analyzers.py0000644000175000017500000001411013611773167022462 0ustar annamaaannamaa00000000000000from thonny.assistance import ProgramAnalyzer, add_program_analyzer from thonny import get_runner, rst_utils from thonny.running import CPythonProxy import logging import os from thonny.common import is_same_path known_stdlib_modules = { # Compiled from https://docs.python.org/3.7/py-modindex.html "__future__", "__main__", "_dummy_thread", "_thread", "abc", "aifc", "argparse", "array", "ast", "asynchat", "asyncio", "asyncore", "atexit", "audioop", "base64", "bdb", "binascii", "binhex", "bisect", "builtins", "bz2", "calendar", "cgi", "cgitb", "chunk", "cmath", "cmd", "code", "codecs", "codeop", "collections", "colorsys", "compileall", "concurrent", "configparser", "contextlib", "contextvars", "copy", "copyreg", "cProfile", "crypt", "csv", "ctypes", "curses", "dataclasses", "datetime", "dbm", "decimal", "difflib", "dis", "distutils", "doctest", "dummy_threading", "email", "encodings", "ensurepip", "enum", "errno", "faulthandler", "fcntl", "filecmp", "fileinput", "fnmatch", "formatter", "fractions", "ftplib", "functools", "gc", "getopt", "getpass", "gettext", "glob", "grp", "gzip", "hashlib", "heapq", "hmac", "html", "http", "imaplib", "imghdr", "imp", "importlib", "inspect", "io", "ipaddress", "itertools", "json", "keyword", "lib2to3", "linecache", "locale", "logging", "lzma", "macpath", "mailbox", "mailcap", "marshal", "math", "mimetypes", "mmap", "modulefinder", "msilib", "msvcrt", "multiprocessing", "netrc", "nis", "nntplib", "numbers", "operator", "optparse", "os", "ossaudiodev", "parser", "pathlib", "pdb", "pickle", "pickletools", "pipes", "pkgutil", "platform", "plistlib", "poplib", "posix", "pprint", "profile", "pstats", "pty", "pwd", "py_compile", "pyclbr", "pydoc", "queue", "quopri", "random", "re", "readline", "reprlib", "resource", "rlcompleter", "runpy", "sched", "secrets", "select", "selectors", "shelve", "shlex", "shutil", "signal", "site", "smtpd", "smtplib", "sndhdr", "socket", "socketserver", "spwd", "sqlite3", "ssl", "stat", "statistics", "string", "stringprep", "struct", "subprocess", "sunau", "symbol", "symtable", "sys", "sysconfig", "syslog", "tabnanny", "tarfile", "telnetlib", "tempfile", "termios", "test", "textwrap", "threading", "time", "timeit", "tkinter", "token", "tokenize", "trace", "traceback", "tracemalloc", "tty", "turtle", "turtledemo", "types", "typing", "unicodedata", "unittest", "urllib", "uu", "uuid", "venv", "warnings", "wave", "weakref", "webbrowser", "winreg", "winsound", "wsgiref", "xdrlib", "xml", "xmlrpc", "zipapp", "zipfile", "zipimport", "zlib", } class ProgramNamingAnalyzer(ProgramAnalyzer): def start_analysis(self, main_file_path, imported_file_paths): self.completion_handler(self, list(self._get_warnings(main_file_path))) def _get_warnings(self, main_file_path): # TODO: current dir may be different main_file_dir = os.path.dirname(main_file_path) if not os.path.isdir(main_file_dir): return [] library_modules = known_stdlib_modules | self._get_3rd_party_modules() for item in os.listdir(main_file_dir): full_path = os.path.join(main_file_dir, item) if item.endswith(".py") and item[:-3] in library_modules: if is_same_path(full_path, main_file_path): prelude = "Your program file is named '%s'." % item rename_hint = " (*File → Rename…* )" else: prelude = ( "Your working directory `%s <%s>`__ contains a file named '%s'.\n\n" % (rst_utils.escape(main_file_dir), rst_utils.escape(main_file_dir), item) ) rename_hint = "" yield { "filename": full_path, "lineno": 0, "symbol": "file-shadows-library-module", "msg": "Possibly bad file name", "explanation_rst": prelude + "\n\n" + "When you try to import library module ``%s``, your file will be imported instead.\n\n" % item[:-3] + "Rename your '%s'%s to make the library module visible again." % (item, rename_hint), "group": "warnings", "relevance": 5, } def _get_3rd_party_modules(self): proxy = get_runner().get_backend_proxy() if not isinstance(proxy, CPythonProxy): return [] try: sys_path = proxy.get_sys_path() except Exception: logging.exception("Can't get sys path from proxy") return [] module_names = set() for item in sys_path: if os.path.isdir(item) and ("site-packages" in item or "dist-packages" in item): module_names.update(self._get_module_names(item)) for name in os.listdir(item): if "-" not in name: module_names.add(name.replace(".py", "")) return module_names def _get_module_names(self, dir_path): result = set() for name in os.listdir(dir_path): if "-" not in name: result.add(name.replace(".py", "")) return result def load_plugin(): add_program_analyzer(ProgramNamingAnalyzer) thonny-3.2.7/thonny/plugins/commenting_indenting.py0000644000175000017500000001110413611773167023636 0ustar annamaaannamaa00000000000000import tkinter as tk from thonny import get_workbench from thonny.common import TextRange from thonny.ui_utils import select_sequence BLOCK_COMMENT_PREFIX = "# " def _get_focused_writable_text(): widget = get_workbench().focus_get() # In Ubuntu when moving from one menu to another, this may give None when text is actually focused if isinstance(widget, tk.Text) and ( not hasattr(widget, "is_read_only") or not widget.is_read_only() ): return widget else: return None def _writable_text_is_focused(): return _get_focused_writable_text() is not None def _selection_is_line_commented(text): sel_range = _get_focused_code_range(text) for lineno in range(sel_range.lineno, sel_range.end_lineno + 1): line = text.get(str(lineno) + ".0", str(lineno) + ".end") if not line.startswith(BLOCK_COMMENT_PREFIX): return False return True def _select_lines(text, first_line, last_line): text.tag_remove("sel", "1.0", tk.END) text.tag_add("sel", str(first_line) + ".0", str(last_line) + ".end") def _toggle_selection_comment(text): if _selection_is_line_commented(text): _uncomment_selection(text) else: _comment_selection(text) def _comment_selection(text): """Adds ## in front of all selected lines if any lines are selected, or just the current line otherwise""" sel_range = _get_focused_code_range(text) for lineno in range(sel_range.lineno, sel_range.end_lineno + 1): text.insert(str(lineno) + ".0", BLOCK_COMMENT_PREFIX) if sel_range.end_lineno > sel_range.lineno: _select_lines(text, sel_range.lineno, sel_range.end_lineno) text.edit_separator() def _uncomment_selection(text): sel_range = _get_focused_code_range(text) for lineno in range(sel_range.lineno, sel_range.end_lineno + 1): line = text.get(str(lineno) + ".0", str(lineno) + ".end") if line.startswith(BLOCK_COMMENT_PREFIX): text.delete(str(lineno) + ".0", str(lineno) + "." + str(len(BLOCK_COMMENT_PREFIX))) def _get_focused_code_range(text): if len(text.tag_ranges("sel")) > 0: lineno, col_offset = map(int, text.index(tk.SEL_FIRST).split(".")) end_lineno, end_col_offset = map(int, text.index(tk.SEL_LAST).split(".")) if end_lineno > lineno and end_col_offset == 0: # SelectAll includes nonexisting extra line end_lineno -= 1 end_col_offset = int(text.index(str(end_lineno) + ".end").split(".")[1]) else: lineno, col_offset = map(int, text.index(tk.INSERT).split(".")) end_lineno, end_col_offset = lineno, col_offset return TextRange(lineno, col_offset, end_lineno, end_col_offset) def _cmd_toggle_selection_comment(): text = _get_focused_writable_text() if text is not None: _toggle_selection_comment(text) def _cmd_comment_selection(): text = _get_focused_writable_text() if text is not None: _comment_selection(text) def _cmd_uncomment_selection(): text = _get_focused_writable_text() if text is not None: _uncomment_selection(text) def _cmd_indent_selection(): text = _get_focused_writable_text() if text is not None: text.indent_region() def _cmd_dedent_selection(): text = _get_focused_writable_text() if text is not None: text.dedent_region() def load_plugin() -> None: get_workbench().add_command( "indent", "edit", _("Indent selected lines"), _cmd_indent_selection, tester=_writable_text_is_focused, accelerator="Tab", group=49, ) get_workbench().add_command( "dedent", "edit", _("Dedent selected lines"), _cmd_dedent_selection, tester=_writable_text_is_focused, accelerator="Shift+Tab", group=49, ) get_workbench().add_command( "toggle_comment", "edit", _("Toggle comment"), _cmd_toggle_selection_comment, default_sequence=select_sequence("", ""), tester=_writable_text_is_focused, group=50, ) get_workbench().add_command( "comment_selection", "edit", _("Comment out"), _cmd_comment_selection, default_sequence="", tester=_writable_text_is_focused, group=50, ) get_workbench().add_command( "uncomment_selection", "edit", _("Uncomment"), _cmd_uncomment_selection, default_sequence="", tester=_writable_text_is_focused, group=50, ) thonny-3.2.7/thonny/plugins/find_replace.py0000644000175000017500000004074313611773167022065 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import tkinter as tk from tkinter import ttk from thonny import get_workbench from thonny.ui_utils import select_sequence, CommonDialog # TODO - consider moving the cmd_find method to main class in order to pass the editornotebook reference # TODO - logging # TODO - instead of text.see method create another one which attempts to center the line where the text was found # TODO - test on mac and linux # Handles the find dialog display and the logic of searching. # Communicates with the codeview that is passed to the constructor as a parameter. _active_find_dialog = None class FindDialog(CommonDialog): last_searched_word = None def __init__(self, master): padx = 15 pady = 15 super().__init__(master, takefocus=1, background="pink") main_frame = ttk.Frame(self) main_frame.grid(row=1, column=1, sticky="nsew") self.columnconfigure(1, weight=1) self.rowconfigure(1, weight=1) self.codeview = master # references to the current set of passive found tags e.g. all words that match the searched term but are not the active string self.passive_found_tags = set() self.active_found_tag = None # reference to the currently active (centered) found string # a tuple containing the start and indexes of the last processed string # if the last action was find, then the end index is start index + 1 # if the last action was replace, then the indexes correspond to the start # and end of the inserted word self.last_processed_indexes = None self.last_search_case = None # case sensitivity value used during the last search # set up window display self.geometry( "+%d+%d" % ( master.winfo_rootx() + master.winfo_width() // 2, master.winfo_rooty() + master.winfo_height() // 2 - 150, ) ) self.title(_("Find & Replace")) self.resizable(height=tk.FALSE, width=tk.FALSE) self.transient(master) self.protocol("WM_DELETE_WINDOW", self._ok) # Find text label self.find_label = ttk.Label(main_frame, text=_("Find:")) self.find_label.grid(column=0, row=0, sticky="w", padx=(padx, 0), pady=(pady, 0)) # Find text field self.find_entry_var = tk.StringVar() self.find_entry = ttk.Entry(main_frame, textvariable=self.find_entry_var) self.find_entry.grid(column=1, row=0, columnspan=2, padx=(0, 10), pady=(pady, 0)) if FindDialog.last_searched_word is not None: self.find_entry.insert(0, FindDialog.last_searched_word) # Replace text label self.replace_label = ttk.Label(main_frame, text=_("Replace with:")) self.replace_label.grid(column=0, row=1, sticky="w", padx=(padx, 0)) # Replace text field self.replace_entry = ttk.Entry(main_frame) self.replace_entry.grid(column=1, row=1, columnspan=2, padx=(0, 10)) # Info text label (invisible by default, used to tell user that searched string was not found etc) self.infotext_label_var = tk.StringVar() self.infotext_label_var.set("") self.infotext_label = ttk.Label( main_frame, textvariable=self.infotext_label_var, foreground="red" ) # TODO - style to conf self.infotext_label.grid(column=0, row=2, columnspan=3, pady=3, padx=(padx, 0)) # Case checkbox self.case_var = tk.IntVar() self.case_checkbutton = ttk.Checkbutton( main_frame, text=_("Case sensitive"), variable=self.case_var ) self.case_checkbutton.grid(column=0, row=3, padx=(padx, 0), pady=(0, pady)) # Direction radiobuttons self.direction_var = tk.IntVar() self.up_radiobutton = ttk.Radiobutton( main_frame, text=_("Up"), variable=self.direction_var, value=1 ) self.up_radiobutton.grid(column=1, row=3, pady=(0, pady)) self.down_radiobutton = ttk.Radiobutton( main_frame, text=_("Down"), variable=self.direction_var, value=2 ) self.down_radiobutton.grid(column=2, row=3, pady=(0, pady)) self.down_radiobutton.invoke() # Find button - goes to the next occurrence button_width = 17 self.find_button = ttk.Button( main_frame, text=_("Find"), width=button_width, command=self._perform_find, default="active", ) self.find_button.grid(column=3, row=0, sticky=tk.W + tk.E, pady=(pady, 0), padx=(0, padx)) self.find_button.config(state="disabled") # Replace button - replaces the current occurrence, if it exists self.replace_button = ttk.Button( main_frame, text=_("Replace"), width=button_width, command=self._perform_replace ) self.replace_button.grid(column=3, row=1, sticky=tk.W + tk.E, padx=(0, padx)) self.replace_button.config(state="disabled") # Replace + find button - replaces the current occurence and goes to next self.replace_and_find_button = ttk.Button( main_frame, text=_("Replace+Find"), width=button_width, command=self._perform_replace_and_find, ) # TODO - text to resources self.replace_and_find_button.grid(column=3, row=2, sticky=tk.W + tk.E, padx=(0, padx)) self.replace_and_find_button.config(state="disabled") # Replace all button - replaces all occurrences self.replace_all_button = ttk.Button( main_frame, text=_("Replace all"), width=button_width, command=self._perform_replace_all ) # TODO - text to resources self.replace_all_button.grid( column=3, row=3, sticky=tk.W + tk.E, padx=(0, padx), pady=(0, pady) ) if FindDialog.last_searched_word == None: self.replace_all_button.config(state="disabled") # create bindings self.bind("", self._ok) self.find_entry_var.trace("w", self._update_button_statuses) self.find_entry.bind("", self._perform_find, True) self.bind("", self._perform_find, True) self.find_entry.bind("", self._perform_find, True) self._update_button_statuses() global _active_find_dialog _active_find_dialog = self self.focus_set() def focus_set(self): self.find_entry.focus_set() self.find_entry.selection_range(0, tk.END) # callback for text modifications on the find entry object, used to dynamically enable and disable buttons def _update_button_statuses(self, *args): find_text = self.find_entry_var.get() if len(find_text) == 0: self.find_button.config(state="disabled") self.replace_and_find_button.config(state="disabled") self.replace_all_button.config(state="disabled") else: self.find_button.config(state="normal") self.replace_all_button.config(state="normal") if self.active_found_tag is not None: self.replace_and_find_button.config(state="normal") # returns whether the next search is case sensitive based on the current value of the case sensitivity checkbox def _is_search_case_sensitive(self): return self.case_var.get() != 0 # returns whether the current search is a repeat of the last searched based on all significant values def _repeats_last_search(self, tofind): return ( tofind == FindDialog.last_searched_word and self.last_processed_indexes is not None and self.last_search_case == self._is_search_case_sensitive() ) # performs the replace operation - replaces the currently active found word with what is entered in the replace field def _perform_replace(self): # nothing is currently in found status if self.active_found_tag == None: return # get the found word bounds del_start = self.active_found_tag[0] del_end = self.active_found_tag[1] # erase all tags - these would not be correct anyway after new word is inserted self._remove_all_tags() toreplace = self.replace_entry.get() # get the text to replace # delete the found word self.codeview.text.delete(del_start, del_end) # insert the new word self.codeview.text.insert(del_start, toreplace) # mark the inserted word boundaries self.last_processed_indexes = ( del_start, self.codeview.text.index("%s+%dc" % (del_start, len(toreplace))), ) get_workbench().event_generate( "Replace", widget=self.codeview.text, old_text=self.codeview.text.get(del_start, del_end), new_text=toreplace, ) # performs the replace operation followed by a new find def _perform_replace_and_find(self): if self.active_found_tag == None: return self._perform_replace() self._perform_find() # replaces all occurences of the search string with the replace string def _perform_replace_all(self): tofind = self.find_entry.get() if len(tofind) == 0: self.infotext_label_var.set(_("Enter string to be replaced.")) return toreplace = self.replace_entry.get() self._remove_all_tags() currentpos = 1.0 end = self.codeview.text.index("end") while True: currentpos = self.codeview.text.search( tofind, currentpos, end, nocase=not self._is_search_case_sensitive() ) if currentpos == "": break endpos = self.codeview.text.index("%s+%dc" % (currentpos, len(tofind))) self.codeview.text.delete(currentpos, endpos) if toreplace != "": self.codeview.text.insert(currentpos, toreplace) currentpos = self.codeview.text.index("%s+%dc" % (currentpos, len(toreplace))) get_workbench().event_generate( "ReplaceAll", widget=self.codeview.text, old_text=tofind, new_text=toreplace ) def _perform_find(self, event=None): self.infotext_label_var.set("") # reset the info label text tofind = self.find_entry.get() # get the text to find if len(tofind) == 0: # in the case of empty string, cancel return # TODO - set warning text to info label? search_backwards = ( self.direction_var.get() == 1 ) # True - search backwards ('up'), False - forwards ('down') if self._repeats_last_search( tofind ): # continuing previous search, find the next occurrence if search_backwards: search_start_index = self.last_processed_indexes[0] else: search_start_index = self.last_processed_indexes[1] if self.active_found_tag is not None: self.codeview.text.tag_remove( "current_found", self.active_found_tag[0], self.active_found_tag[1] ) # remove the active tag from the previously found string self.passive_found_tags.add( (self.active_found_tag[0], self.active_found_tag[1]) ) # ..and set it to passive instead self.codeview.text.tag_add( "found", self.active_found_tag[0], self.active_found_tag[1] ) else: # start a new search, start from the current insert line position if self.active_found_tag is not None: self.codeview.text.tag_remove( "current_found", self.active_found_tag[0], self.active_found_tag[1] ) # remove the previous active tag if it was present for tag in self.passive_found_tags: self.codeview.text.tag_remove( "found", tag[0], tag[1] ) # and remove all the previous passive tags that were present search_start_index = self.codeview.text.index( "insert" ) # start searching from the current insert position self._find_and_tag_all(tofind) # set the passive tag to ALL found occurences FindDialog.last_searched_word = tofind # set the data about last search self.last_search_case = self._is_search_case_sensitive() wordstart = self.codeview.text.search( tofind, search_start_index, backwards=search_backwards, forwards=not search_backwards, nocase=not self._is_search_case_sensitive(), ) # performs the search and sets the start index of the found string if len(wordstart) == 0: self.infotext_label_var.set( _("The specified text was not found!") ) # TODO - better text, also move it to the texts resources list self.replace_and_find_button.config(state="disabled") self.replace_button.config(state="disabled") return self.last_processed_indexes = ( wordstart, self.codeview.text.index("%s+1c" % wordstart), ) # sets the data about last search self.codeview.text.see(wordstart) # moves the view to the found index wordend = self.codeview.text.index( "%s+%dc" % (wordstart, len(tofind)) ) # calculates the end index of the found string self.codeview.text.tag_add( "current_found", wordstart, wordend ) # tags the found word as active self.active_found_tag = (wordstart, wordend) self.replace_and_find_button.config(state="normal") self.replace_button.config(state="normal") get_workbench().event_generate( "Find", widget=self.codeview.text, text=tofind, backwards=search_backwards, case_sensitive=self._is_search_case_sensitive(), ) def _ok(self, event=None): """Called when the window is closed. responsible for handling all cleanup.""" self._remove_all_tags() self.destroy() global _active_find_dialog _active_find_dialog = None # removes the active tag and all passive tags def _remove_all_tags(self): for tag in self.passive_found_tags: self.codeview.text.tag_remove("found", tag[0], tag[1]) # removes the passive tags if self.active_found_tag is not None: self.codeview.text.tag_remove( "current_found", self.active_found_tag[0], self.active_found_tag[1] ) # removes the currently active tag self.active_found_tag = None self.replace_and_find_button.config(state="disabled") self.replace_button.config(state="disabled") # finds and tags all occurences of the searched term def _find_and_tag_all(self, tofind, force=False): # TODO - to be improved so only whole words are matched - surrounded by whitespace, parentheses, brackets, colons, semicolons, points, plus, minus if ( self._repeats_last_search(tofind) and not force ): # nothing to do, all passive tags already set return currentpos = 1.0 end = self.codeview.text.index("end") # searches and tags until the end of codeview while True: currentpos = self.codeview.text.search( tofind, currentpos, end, nocase=not self._is_search_case_sensitive() ) if currentpos == "": break endpos = self.codeview.text.index("%s+%dc" % (currentpos, len(tofind))) self.passive_found_tags.add((currentpos, endpos)) self.codeview.text.tag_add("found", currentpos, endpos) currentpos = self.codeview.text.index("%s+1c" % currentpos) def load_plugin() -> None: def cmd_open_find_dialog(): if _active_find_dialog is not None: _active_find_dialog.focus_set() else: editor = get_workbench().get_editor_notebook().get_current_editor() if editor: FindDialog(editor._code_view) def find_f3(event): if _active_find_dialog is None: cmd_open_find_dialog() else: _active_find_dialog._perform_find(event) get_workbench().add_command( "OpenFindDialog", "edit", _("Find & Replace"), cmd_open_find_dialog, default_sequence=select_sequence("", ""), extra_sequences=[""], ) get_workbench().bind("", find_f3, True) thonny-3.2.7/thonny/plugins/event_view.py0000644000175000017500000000273613611773167021625 0ustar annamaaannamaa00000000000000""" Helper view for Thonny developers """ from thonny import get_workbench from thonny.tktextext import TextFrame from thonny.common import DebuggerResponse class EventsView(TextFrame): def __init__(self, master): TextFrame.__init__(self, master) # self.text.config(wrap=tk.WORD) get_workbench().bind("ShowView", self._log_event, True) get_workbench().bind("HideView", self._log_event, True) get_workbench().bind("ToplevelReponse", self._log_event, True) get_workbench().bind("DebuggerResponse", self._log_event, True) get_workbench().bind("ProgramOutput", self._log_event, True) get_workbench().bind("InputRequest", self._log_event, True) def _log_event(self, event): self.text.insert("end", event.sequence + "\n") for name in dir(event): if name not in ["sequence", "setdefault", "update"] and not name.startswith("_"): self.text.insert( "end", " " + name + ": " + repr(getattr(event, name))[:100] + "\n" ) if isinstance(event, DebuggerResponse): frame = event.stack[-1] self.text.insert("end", " " + "event" + ": " + frame.event + "\n") self.text.insert("end", " " + "focus" + ": " + str(frame.focus) + "\n") self.text.see("end") def load_plugin() -> None: if get_workbench().get_option("general.debug_mode"): get_workbench().add_view(EventsView, _("Events"), "se") thonny-3.2.7/thonny/plugins/replayer.py0000644000175000017500000003154713611773167021277 0ustar annamaaannamaa00000000000000import ast import json import os.path import tkinter as tk from datetime import datetime from tkinter import ttk from thonny import codeview, get_workbench, ui_utils, THONNY_USER_DIR from thonny.base_file_browser import BaseLocalFileBrowser from thonny.plugins.coloring import SyntaxColorer from thonny.ui_utils import lookup_style_option, CommonDialog class ReplayWindow(CommonDialog): def __init__(self): super().__init__(get_workbench(), background=lookup_style_option("TFrame", "background")) ui_utils.set_zoomed(self, True) self.main_pw = ReplayerPanedWindow(self, orient=tk.HORIZONTAL, sashwidth=10) self.center_pw = ReplayerPanedWindow(self.main_pw, orient=tk.VERTICAL, sashwidth=10) self.right_frame = ttk.Frame(self.main_pw) self.right_pw = ReplayerPanedWindow(self.right_frame, orient=tk.VERTICAL, sashwidth=10) self.editor_notebook = ReplayerEditorNotebook(self.center_pw) shell_book = ttk.Notebook(self.main_pw) self.shell = ShellFrame(shell_book) self.details_frame = EventDetailsFrame(self.right_pw) self.log_frame = LogFrame( self.right_pw, self.editor_notebook, self.shell, self.details_frame ) self.browser = ReplayerFileBrowser(self.main_pw, self.log_frame) self.control_frame = ControlFrame(self.right_frame) self.main_pw.grid(padx=10, pady=10, sticky=tk.NSEW) self.main_pw.add(self.browser, width=200) self.main_pw.add(self.center_pw, width=1000) self.main_pw.add(self.right_frame, width=200) self.center_pw.add(self.editor_notebook, height=700) self.center_pw.add(shell_book, height=300) shell_book.add(self.shell, text="Shell") self.right_pw.grid(sticky=tk.NSEW) self.control_frame.grid(sticky=tk.NSEW) self.right_pw.add(self.log_frame, height=600) self.right_pw.add(self.details_frame, height=200) self.right_frame.columnconfigure(0, weight=1) self.right_frame.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) class ReplayerFileBrowser(BaseLocalFileBrowser): def __init__(self, master, log_frame): super().__init__(master, True) self.log_frame = log_frame self.configure(border=1, relief=tk.GROOVE) user_logs_path = os.path.join(THONNY_USER_DIR, "user_logs") if os.path.exists(user_logs_path): self.focus_into(user_logs_path) else: self.focus_into(os.path.expanduser("~")) def on_double_click(self, event): # self.save_current_folder() path = self.get_selected_path() if path: self.log_frame.load_log(path) return "break" # avoid default action of opening the node class ControlFrame(ttk.Frame): def __init__(self, master, **kw): ttk.Frame.__init__(self, master=master, **kw) self.toggle_button = ttk.Button(self, text="Play") self.speed_scale = ttk.Scale(self, from_=1, to=100, orient=tk.HORIZONTAL) self.toggle_button.grid(row=0, column=0, sticky=tk.NSEW, pady=(10, 0), padx=(0, 5)) self.speed_scale.grid(row=0, column=1, sticky=tk.NSEW, pady=(10, 0), padx=(5, 0)) self.columnconfigure(1, weight=1) class LogFrame(ui_utils.TreeFrame): def __init__(self, master, editor_book, shell, details_frame): ui_utils.TreeFrame.__init__(self, master, ("desc", "pause")) self.tree.heading("desc", text="Event", anchor=tk.W) self.tree.heading("pause", text="Pause (sec)", anchor=tk.W) self.configure(border=1, relief=tk.GROOVE) self.editor_notebook = editor_book self.shell = shell self.details_frame = details_frame self.all_events = [] self.last_event_index = -1 self.loading = False def load_log(self, filename): self._clear_tree() self.details_frame._clear_tree() self.all_events = [] self.last_event_index = -1 self.loading = True self.editor_notebook.reset() self.shell.reset() with open(filename, encoding="UTF-8") as f: events = json.load(f) last_event_time = None for event in events: node_id = self.tree.insert("", "end") self.tree.set(node_id, "desc", event["sequence"]) event_time = datetime.strptime(event["time"], "%Y-%m-%dT%H:%M:%S.%f") if last_event_time: delta = event_time - last_event_time pause = delta.seconds else: pause = 0 self.tree.set(node_id, "pause", str(pause if pause else "")) self.all_events.append(event) last_event_time = event_time self.loading = False def replay_event(self, event): "this should be called with events in correct order" # print("log replay", event) if "text_widget_id" in event: if ( event.get("text_widget_context", None) == "shell" or event.get("text_widget_class") == "ShellText" ): self.shell.replay_event(event) else: self.editor_notebook.replay_event(event) def reset(self): self.shell.reset() self.editor_notebook.reset() self.last_event_index = -1 def on_select(self, event): # parameter "event" is here tkinter event if self.loading: return iid = self.tree.focus() if iid != "": self.select_event(self.tree.index(iid)) def select_event(self, event_index): event = self.all_events[event_index] self.details_frame.load_event(event) # here event means logged event if event_index > self.last_event_index: # replay all events between last replayed event up to and including this event while self.last_event_index < event_index: self.replay_event(self.all_events[self.last_event_index + 1]) self.last_event_index += 1 elif event_index < self.last_event_index: # Undo by reseting and replaying again self.reset() self.select_event(event_index) class EventDetailsFrame(ui_utils.TreeFrame): def __init__(self, master): ui_utils.TreeFrame.__init__(self, master, columns=("attribute", "value")) self.tree.heading("attribute", text="Attribute", anchor=tk.W) self.tree.heading("value", text="Value", anchor=tk.W) self.configure(border=1, relief=tk.GROOVE) def load_event(self, event): self._clear_tree() for name in self.order_keys(event): node_id = self.tree.insert("", "end") self.tree.set(node_id, "attribute", name) self.tree.set(node_id, "value", event[name]) def order_keys(self, event): return event.keys() class ReplayerCodeView(ttk.Frame): def __init__(self, master): ttk.Frame.__init__(self, master) self.vbar = ttk.Scrollbar(self, orient=tk.VERTICAL) self.vbar.grid(row=0, column=2, sticky=tk.NSEW) self.hbar = ttk.Scrollbar(self, orient=tk.HORIZONTAL) self.hbar.grid(row=1, column=0, sticky=tk.NSEW, columnspan=2) self.text = codeview.SyntaxText( self, yscrollcommand=self.vbar.set, xscrollcommand=self.hbar.set, borderwidth=0, font="EditorFont", wrap=tk.NONE, insertwidth=2, # selectborderwidth=2, inactiveselectbackground="gray", # highlightthickness=0, # TODO: try different in Mac and Linux # highlightcolor="gray", padx=5, pady=5, undo=True, autoseparators=False, ) self.text.grid(row=0, column=1, sticky=tk.NSEW) self.hbar["command"] = self.text.xview self.vbar["command"] = self.text.yview self.columnconfigure(1, weight=1) self.rowconfigure(0, weight=1) class ReplayerEditor(ttk.Frame): def __init__(self, master): ttk.Frame.__init__(self, master) self.code_view = ReplayerCodeView(self) self.code_view.grid(sticky=tk.NSEW) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) def replay_event(self, event): if event["sequence"] in ["TextInsert", "TextDelete"]: if event["sequence"] == "TextInsert": self.code_view.text.insert( event["index"], event["text"], ast.literal_eval(event["tags"]) ) elif event["sequence"] == "TextDelete": if event["index2"] and event["index2"] != "None": self.code_view.text.delete(event["index1"], event["index2"]) else: self.code_view.text.delete(event["index1"]) self.see_event(event) def see_event(self, event): for key in ["index", "index1", "index2"]: if key in event and event[key] and event[key] != "None": self.code_view.text.see(event[key]) def reset(self): self.code_view.text.delete("1.0", "end") class ReplayerEditorProper(ReplayerEditor): def __init__(self, master): ReplayerEditor.__init__(self, master) self.set_colorer() def set_colorer(self): self.colorer = SyntaxColorer(self.code_view.text) def replay_event(self, event): ReplayerEditor.replay_event(self, event) # TODO: some problem when doing fast rewind # self.colorer.notify_range("1.0", "end") def reset(self): ReplayerEditor.reset(self) self.set_colorer() class ReplayerEditorNotebook(ttk.Notebook): def __init__(self, master): ttk.Notebook.__init__(self, master, padding=0) self._editors_by_text_widget_id = {} def clear(self): for child in self.winfo_children(): child.destroy() self._editors_by_text_widget_id = {} def get_editor_by_text_widget_id(self, text_widget_id): if text_widget_id not in self._editors_by_text_widget_id: editor = ReplayerEditorProper(self) self.add(editor, text="") self._editors_by_text_widget_id[text_widget_id] = editor return self._editors_by_text_widget_id[text_widget_id] def replay_event(self, event): if "text_widget_id" in event: editor = self.get_editor_by_text_widget_id(event["text_widget_id"]) # print(event.editor_id, id(editor), event) self.select(editor) editor.replay_event(event) if "filename" in event: self.tab(editor, text=os.path.basename(event["filename"])) def reset(self): for editor in self.winfo_children(): self.forget(editor) editor.destroy() self._editors_by_text_widget_id = {} class ShellFrame(ReplayerEditor): def __init__(self, master): ReplayerEditor.__init__(self, master) # TODO: use same source as shell vert_spacing = 10 io_indent = 16 self.code_view.text.tag_configure("toplevel", font="EditorFont") self.code_view.text.tag_configure("prompt", foreground="purple", font="BoldEditorFont") self.code_view.text.tag_configure("command", foreground="black") self.code_view.text.tag_configure("version", foreground="DarkGray") self.code_view.text.tag_configure("automagic", foreground="DarkGray") self.code_view.text.tag_configure( "value", foreground="DarkBlue" ) # TODO: see also _text_key_press and _text_key_release self.code_view.text.tag_configure("error", foreground="Red") self.code_view.text.tag_configure( "io", lmargin1=io_indent, lmargin2=io_indent, rmargin=io_indent, font="IOFont" ) self.code_view.text.tag_configure("stdin", foreground="Blue") self.code_view.text.tag_configure("stdout", foreground="Black") self.code_view.text.tag_configure("stderr", foreground="Red") self.code_view.text.tag_configure("hyperlink", foreground="#3A66DD", underline=True) self.code_view.text.tag_configure("vertically_spaced", spacing1=vert_spacing) self.code_view.text.tag_configure("inactive", foreground="#aaaaaa") class ReplayerPanedWindow(tk.PanedWindow): def __init__(self, master=None, cnf={}, **kw): cnf = cnf.copy() cnf.update(kw) cnf["background"] = lookup_style_option("TFrame", "background") super().__init__(master=master, cnf=cnf) def load_plugin() -> None: def open_replayer(): win = ReplayWindow() ui_utils.show_dialog(win) get_workbench().set_default("tools.replayer_last_browser_folder", None) if get_workbench().get_ui_mode() == "expert": get_workbench().add_command( "open_replayer", "tools", _("Open replayer..."), open_replayer, group=110 ) thonny-3.2.7/thonny/plugins/mypy/0000755000175000017500000000000013611777205020063 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/mypy/__init__.py0000644000175000017500000000755413611773167022212 0ustar annamaaannamaa00000000000000import re import os.path import subprocess import sys from typing import Iterable from thonny import get_runner, ui_utils, get_workbench from thonny.assistance import SubprocessProgramAnalyzer, add_program_analyzer from thonny.running import get_interpreter_for_subprocess import logging class MyPyAnalyzer(SubprocessProgramAnalyzer): def is_enabled(self): return get_workbench().get_option("assistance.use_mypy") def start_analysis(self, main_file_path, imported_file_paths: Iterable[str]) -> None: self.interesting_files = [main_file_path] + list(imported_file_paths) args = [ get_interpreter_for_subprocess(), "-m", "mypy", "--ignore-missing-imports", "--check-untyped-defs", "--warn-redundant-casts", "--warn-unused-ignores", "--show-column-numbers", main_file_path, ] + list(imported_file_paths) # TODO: ignore "... need type annotation" messages from mypy.version import __version__ try: ver = tuple(map(int, __version__.split("."))) except Exception: ver = (0, 470) # minimum required version if ver >= (0, 520): args.insert(3, "--no-implicit-optional") if ver >= (0, 590): args.insert(3, "--python-executable") args.insert(4, get_runner().get_local_executable()) if ver >= (0, 730): args.insert(3, "--warn-unreachable") args.insert(3, "--allow-redefinition") args.insert(3, "--strict-equality") args.insert(3, "--no-color-output") args.insert(3, "--no-error-summary") env = os.environ.copy() env["MYPYPATH"] = os.path.join(os.path.dirname(__file__), "typeshed_extras") self._proc = ui_utils.popen_with_ui_thread_callback( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=env, on_completion=self._parse_and_output_warnings, # Specify a cwd which is not ancestor of user files. # This gives absolute filenames in the output. # Note that mypy doesn't accept when cwd is sys.prefix # or dirname(sys.executable) cwd=os.path.dirname(__file__), ) def _parse_and_output_warnings(self, pylint_proc, out_lines, err_lines): if err_lines: logging.getLogger("thonny").warning("MyPy: " + "".join(err_lines)) warnings = [] for line in out_lines: m = re.match(r"(.*?):(\d+)(:(\d+))?:(.*?):(.*)", line.strip()) if m is not None: message = m.group(6).strip() if message == "invalid syntax": continue # user will see this as Python error filename = m.group(1) if filename not in self.interesting_files: logging.getLogger("thonny").warning("MyPy: " + line) continue atts = { "filename": filename, "lineno": int(m.group(2)), "kind": m.group(5).strip(), # always "error" ? "msg": message, "group": "warnings", } if m.group(3): # https://github.com/thonny/thonny/issues/598 atts["col_offset"] = max(int(m.group(4)) - 1, 0) # TODO: add better categorization and explanation atts["symbol"] = "mypy-" + atts["kind"] warnings.append(atts) else: logging.error("Can't parse MyPy line: " + line.strip()) self.completion_handler(self, warnings) def load_plugin(): add_program_analyzer(MyPyAnalyzer) get_workbench().set_default("assistance.use_mypy", True) thonny-3.2.7/thonny/plugins/mypy/typeshed_extras/0000755000175000017500000000000013611777205023276 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/mypy/typeshed_extras/turtle.pyi0000644000175000017500000003116013611773167025344 0ustar annamaaannamaa00000000000000# Stubs for turtle (generated from Python 3.7) import tkinter as TK from typing import Any, Optional, Union, overload, Tuple, Dict, List class Vec2D(tuple): def __new__(cls, x: float, y: float): ... def __add__(self, other: Any) -> Any: ... def __mul__(self, other: Any) -> Any: ... def __rmul__(self, other: Any) -> Any: ... def __sub__(self, other: Any) -> Any: ... def __neg__(self) -> "Vec2D": ... def __abs__(self) -> "Vec2D": ... def rotate(self, angle: Any) -> "Vec2D": ... def __getnewargs__(self) -> Tuple[float, float]: ... Point2D = Union[Vec2D, Tuple[float, float]] class ScrolledCanvas(TK.Frame): bg = "" hscroll = TK.Scrollbar() vscroll = TK.Scrollbar() def __init__( self, master: TK.Widget, width: int = ..., height: int = ..., canvwidth: int = ..., canvheight: int = ..., ) -> None: ... canvwidth = 0 canvheight = 0 def reset( self, canvwidth: Optional[int] = ..., canvheight: Optional[int] = ..., bg: Optional[str] = ..., ) -> None: ... def adjustScrolls(self) -> None: ... def onResize(self, event: TK.Event) -> None: ... def bbox(self, *args: Any) -> Tuple[int, int, int, int]: ... def cget(self, *args: Any, **kwargs: Any): ... def config(self, *args: Any, **kwargs: Any) -> None: ... def bind(self, *args: Any, **kwargs: Any) -> None: ... def unbind(self, *args: Any, **kwargs: Any) -> None: ... def focus_force(self) -> None: ... class _Root(TK.Tk): def __init__(self) -> None: ... def setupcanvas(self, width: Any, height: Any, cwidth: Any, cheight: Any) -> None: ... def set_geometry(self, width: Any, height: Any, startx: Any, starty: Any) -> None: ... def ondestroy(self, destroy: Any) -> None: ... def win_width(self): ... def win_height(self): ... class TurtleScreenBase: cv = TK.Canvas() canvwidth = 0 canvheight = 0 xscale = 0.0 def __init__(self, cv: TK.Canvas) -> None: ... def mainloop(self) -> None: ... def textinput(self, title: str, prompt: str) -> Optional[str]: ... def numinput( self, title: str, prompt: str, default: Optional[float] = ..., minval: Optional[float] = ..., maxval: Optional[float] = ..., ) -> Optional[float]: ... class Terminator(Exception): ... class TurtleGraphicsError(Exception): ... class Shape: def __init__(self, type_: str, data: Optional[Any] = None) -> None: ... def addcomponent(self, poly: Any, fill: Any, outline: Optional[Any] = None) -> None: ... class Tbuffer: bufsize = 0 buffer = ... # type: Any ptr = 0 cumulate = True def __init__(self, bufsize: int = ...) -> None: ... def reset(self, bufsize: Optional[Any] = None) -> None: ... def push(self, item: Any) -> None: ... def pop(self): ... def nr_of_items(self): ... class TurtleScreen(TurtleScreenBase): def __init__(self, cv: TK.Canvas, mode: Any, colormode: Any, delay: Any) -> None: ... def clear(self) -> None: ... xscale = 0.0 def mode(self, mode: Optional[str] = ...) -> Optional[str]: ... yscale = ... # type: Any def setworldcoordinates(self, llx: Any, lly: Any, urx: Any, ury: Any) -> None: ... def register_shape(self, name: Any, shape: Optional[Any] = None) -> None: ... def colormode(self, cmode: Optional[float] = ...) -> Optional[float]: ... def reset(self) -> None: ... def turtles(self) -> List["Turtle"]: ... def bgcolor( self, *args: Union[Tuple[str], Tuple[float, float, float]] ) -> Union[Tuple[str], Tuple[float, float, float]]: ... def tracer(self, n: Optional[Any] = None, delay: Optional[Any] = None): ... def delay(self, delay: Optional[Any] = None): ... def update(self) -> None: ... def window_width(self): ... def window_height(self): ... def getcanvas(self): ... def getshapes(self): ... def onclick(self, fun: Any, btn: int = ..., add: Optional[Any] = None) -> None: ... def onkey(self, fun: Any, key: Any) -> None: ... def onkeypress(self, fun: Any, key: Optional[Any] = None) -> None: ... def listen(self, xdummy: Optional[Any] = None, ydummy: Optional[Any] = None) -> None: ... def ontimer(self, fun: Any, t: int = ...) -> None: ... def bgpic(self, picname: Optional[Any] = None): ... def screensize( self, canvwidth: Optional[Any] = None, canvheight: Optional[Any] = None, bg: Optional[Any] = None, ): ... onscreenclick = onclick resetscreen = reset clearscreen = clear addshape = register_shape onkeyrelease = onkey class TNavigator: START_ORIENTATION = {} # type: Dict[str, Vec2D] DEFAULT_MODE = "" DEFAULT_ANGLEOFFSET = 0 DEFAULT_ANGLEORIENT = 0 undobuffer = ... # type: Any def __init__(self, mode: str = ...) -> None: ... def reset(self) -> None: ... def degrees(self, fullcircle: float = ...) -> None: ... def radians(self) -> None: ... def forward(self, distance: float) -> None: ... def back(self, distance: float) -> None: ... def right(self, angle: float) -> None: ... def left(self, angle: float) -> None: ... def pos(self) -> Vec2D: ... def xcor(self) -> float: ... def ycor(self) -> float: ... @overload def goto(self, x: float, y: float) -> None: ... @overload def goto(self, x: Point2D) -> None: ... def home(self) -> None: ... def setx(self, x: float) -> None: ... def sety(self, y: float) -> None: ... @overload def distance(self, x: float, y: float) -> float: ... @overload def distance(self, x: Union[Turtle, Point2D]) -> float: ... @overload def towards(self, x: float, y: float) -> float: ... @overload def towards(self, x: Union[Turtle, Point2D]) -> float: ... def heading(self) -> float: ... def setheading(self, to_angle: float) -> None: ... def circle( self, radius: float, extent: Optional[float] = None, steps: Optional[float] = None ) -> None: ... def speed(self, s: int = ...) -> None: ... fd = forward bk = back backward = back rt = right lt = left position = pos setpos = goto setposition = goto seth = setheading class TPen: undobuffer = ... # type: Any def __init__(self, resizemode: Any) -> None: ... def resizemode(self, rmode: Optional[Any] = None): ... def pensize(self, width: Optional[Any] = None): ... def penup(self): ... def pendown(self): ... def isdown(self): ... def speed(self, speed: Optional[Any] = None): ... def color(self, *args: Any): ... def pencolor(self, *args: Any): ... def fillcolor(self, *args: Any): ... def showturtle(self) -> None: ... def hideturtle(self) -> None: ... def isvisible(self): ... def pen(self, pen: Optional[Any] = None, **pendict: Any): ... width = pensize up = penup pu = penup pd = pendown down = pendown st = showturtle ht = hideturtle class _TurtleImage: screen = ... # type: Any def __init__(self, screen: Any, shapeIndex: Any) -> None: ... class RawTurtle(TPen, TNavigator): screens = ... # type: Any screen = ... # type: Any drawingLineItem = ... # type: Any turtle = ... # type: Any currentLineItem = ... # type: Any currentLine = ... # type: Any items = ... # type: Any stampItems = ... # type: Any undobuffer = ... # type: Any def __init__( self, canvas: Optional[Any] = None, shape: Any = None, undobuffersize: Any = None, visible: Any = None, ) -> None: ... def reset(self) -> None: ... def setundobuffer(self, size: Any) -> None: ... def undobufferentries(self): ... def clear(self) -> None: ... def clone(self): ... def shape(self, name: Optional[Any] = None): ... def shapesize( self, stretch_wid: Optional[Any] = None, stretch_len: Optional[Any] = None, outline: Optional[Any] = None, ): ... def shearfactor(self, shear: Optional[Any] = None): ... def settiltangle(self, angle: Any) -> None: ... def tiltangle(self, angle: Optional[Any] = None): ... def tilt(self, angle: Any) -> None: ... def shapetransform( self, t11: Optional[Any] = None, t12: Optional[Any] = None, t21: Optional[Any] = None, t22: Optional[Any] = None, ): ... def get_shapepoly(self): ... def stamp(self): ... def clearstamp(self, stampid: Any) -> None: ... def clearstamps(self, n: Optional[Any] = None) -> None: ... def filling(self): ... def begin_fill(self) -> None: ... def end_fill(self) -> None: ... def dot(self, size: Optional[Any] = None, *color: Any) -> None: ... def write(self, arg: Any, move: bool = ..., align: str = ..., font: Any = None) -> None: ... def begin_poly(self) -> None: ... def end_poly(self) -> None: ... def get_poly(self): ... def getscreen(self): ... def getturtle(self): ... getpen = ... # type: Any def onclick(self, fun: Any, btn: int = ..., add: Optional[Any] = None) -> None: ... def onrelease(self, fun: Any, btn: int = ..., add: Optional[Any] = None) -> None: ... def ondrag(self, fun: Any, btn: int = ..., add: Optional[Any] = None) -> None: ... def undo(self): ... turtlesize = shapesize RawPen = RawTurtle class _Screen(TurtleScreen): def __init__(self) -> None: ... def setup(self, width: Any, height: Any, startx: Any, starty: Any): ... def title(self, titlestring: Any) -> None: ... def bye(self) -> None: ... def exitonclick(self): ... def Screen() -> _Screen: ... class Turtle(RawTurtle): def __init__(self, shape: Any, undobuffersize: Any, visible: Any) -> None: ... Pen = Turtle def write_docstringdict(filename: str = ...) -> None: ... _screen = Screen() _turtle = Turtle() addshape = _screen.addshape bgcolor = _screen.bgcolor bgpic = _screen.bgpic bye = _screen.bye clearscreen = _screen.clearscreen colormode = _screen.colormode delay = _screen.delay exitonclick = _screen.exitonclick getcanvas = _screen.getcanvas getshapes = _screen.getshapes listen = _screen.listen mainloop = _screen.mainloop mode = _screen.mode numinput = _screen.numinput onkey = _screen.onkey onkeypress = _screen.onkeypress onkeyrelease = _screen.onkeyrelease onscreenclick = _screen.onscreenclick ontimer = _screen.ontimer register_shape = _screen.register_shape resetscreen = _screen.resetscreen screensize = _screen.screensize setup = _screen.setup setworldcoordinates = _screen.setworldcoordinates textinput = _screen.textinput title = _screen.title tracer = _screen.tracer turtles = _screen.turtles update = _screen.update window_height = _screen.window_height window_width = _screen.window_width done = mainloop back = _turtle.back backward = _turtle.backward begin_fill = _turtle.begin_fill begin_poly = _turtle.begin_poly bk = _turtle.bk circle = _turtle.circle clear = _turtle.clear clearstamp = _turtle.clearstamp clearstamps = _turtle.clearstamps clone = _turtle.clone color = _turtle.color degrees = _turtle.degrees distance = _turtle.distance dot = _turtle.dot down = _turtle.down end_fill = _turtle.end_fill end_poly = _turtle.end_poly fd = _turtle.fd fillcolor = _turtle.fillcolor filling = _turtle.filling forward = _turtle.forward get_poly = _turtle.get_poly get_shapepoly = _turtle.get_shapepoly getpen = _turtle.getpen getscreen = _turtle.getscreen getturtle = _turtle.getturtle goto = _turtle.goto heading = _turtle.heading hideturtle = _turtle.hideturtle home = _turtle.home ht = _turtle.ht isdown = _turtle.isdown isvisible = _turtle.isvisible left = _turtle.left lt = _turtle.lt onclick = _turtle.onclick ondrag = _turtle.ondrag onrelease = _turtle.onrelease pd = _turtle.pd pen = _turtle.pen pencolor = _turtle.pencolor pendown = _turtle.pendown pensize = _turtle.pensize penup = _turtle.penup pos = _turtle.pos position = _turtle.position pu = _turtle.pu radians = _turtle.radians reset = _turtle.reset resizemode = _turtle.resizemode right = _turtle.right rt = _turtle.rt seth = _turtle.seth setheading = _turtle.setheading setpos = _turtle.setpos setposition = _turtle.setposition settiltangle = _turtle.settiltangle setundobuffer = _turtle.setundobuffer setx = _turtle.setx sety = _turtle.sety shape = _turtle.shape shapesize = _turtle.shapesize shapetransform = _turtle.shapetransform shearfactor = _turtle.shearfactor showturtle = _turtle.showturtle speed = _turtle.speed st = _turtle.st stamp = _turtle.stamp tilt = _turtle.tilt tiltangle = _turtle.tiltangle towards = _turtle.towards turtlesize = _turtle.turtlesize undo = _turtle.undo undobufferentries = _turtle.undobufferentries up = _turtle.up width = _turtle.width write = _turtle.write xcor = _turtle.xcor ycor = _turtle.ycor thonny-3.2.7/thonny/plugins/variables.py0000644000175000017500000001206413611773167021415 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- from tkinter import ttk, messagebox from thonny import get_runner, get_workbench from thonny.common import InlineCommand from thonny.memory import VariablesFrame class VariablesView(VariablesFrame): # TODO: Indicate invalid state when program or debug command is running more than a second def __init__(self, master): super().__init__(master) ttk.Style().configure("Centered.TButton", justify="center") self.back_button = ttk.Button( self.tree, style="Centered.TButton", text=_("Back to\ncurrent frame"), command=self._handle_back_button, width=15, ) get_workbench().bind("BackendRestart", self._handle_backend_restart, True) get_workbench().bind("ToplevelResponse", self._handle_toplevel_response, True) # get_workbench().bind("DebuggerResponse", self._debugger_response, True) get_workbench().bind("get_frame_info_response", self._handle_frame_info_event, True) get_workbench().bind("get_globals_response", self._handle_get_globals_response, True) # records last info from progress messages self._last_active_info = None def _update_back_button(self, visible): if visible: assert self._last_active_info is not None self.back_button.configure(text="Back to\n" + self._last_active_info[-1]) self.back_button.place(relx=1, x=-5, y=5, anchor="ne") else: self.back_button.place_forget() def _handle_back_button(self): assert self._last_active_info is not None if len(self._last_active_info) == 2: self.show_globals(*self._last_active_info) else: assert len(self._last_active_info) == 4 self.show_frame_variables(*self._last_active_info) def _handle_backend_restart(self, event): self._clear_tree() def _handle_get_globals_response(self, event): if "error" in event: self._clear_tree() messagebox.showerror("Error querying global variables", event["error"]) elif "globals" not in event: self._clear_tree() messagebox.showerror("Error querying global variables", str(event)) else: self.show_globals(event["globals"], event["module_name"]) def _handle_toplevel_response(self, event): if "globals" in event: self.show_globals(event["globals"], "__main__") else: # MicroPython get_runner().send_command(InlineCommand("get_globals", module_name="__main__")) def show_globals(self, globals_, module_name, is_active=True): # TODO: update only if something has changed self.update_variables(globals_) if module_name == "__main__": self._set_tab_caption("Variables") else: self._set_tab_caption("Variables (%s)" % module_name) if is_active: self._last_active_info = (globals_, module_name) self._update_back_button(not is_active) def show_frame_variables(self, locals_, globals_, freevars, frame_name, is_active=True): # TODO: update only if something has changed actual_locals = {} nonlocals = {} for name in locals_: if name in freevars: nonlocals[name] = locals_[name] else: actual_locals[name] = locals_[name] groups = [("LOCALS", actual_locals), ("GLOBALS", globals_)] if nonlocals: groups.insert(1, ("NONLOCALS", nonlocals)) self.update_variables(groups) self._set_tab_caption("Variables (%s)" % frame_name) if is_active: self._last_active_info = (locals_, globals_, freevars, frame_name) self._update_back_button(not is_active) def _handle_frame_info_event(self, frame_info): if frame_info.get("error"): "probably non-existent frame" return else: is_active = frame_info[ "location" ] == "stack" or ( # same __main__ globals can be in different frames frame_info["code_name"] == "" and frame_info["module_name"] == "__main__" and self._last_active_info[-1] == "__main__" and self._last_active_info[0] == frame_info["globals"] ) if frame_info["code_name"] == "": self.show_globals(frame_info["globals"], frame_info["module_name"], is_active) else: self.show_frame_variables( frame_info["locals"], frame_info["globals"], frame_info["freevars"], frame_info["code_name"], is_active, ) def _set_tab_caption(self, text): # pylint: disable=no-member if self.hidden: return self.home_widget.master.tab(self.home_widget, text=text) def load_plugin() -> None: get_workbench().add_view(VariablesView, _("Variables"), "ne", default_position_key="AAA") thonny-3.2.7/thonny/plugins/statement_boxes.py0000644000175000017500000002030113611773167022642 0ustar annamaaannamaa00000000000000""" NB! Stippling doesn't work on mac: http://wiki.tcl.tk/44444 http://rkeene.org/projects/tcl/tk.fossil/tkthistory/2954673 """ import logging import os.path from tkinter import font import thonny from thonny import get_workbench, jedi_utils from thonny.codeview import get_syntax_options_for_tag python_tree = jedi_utils.import_python_tree() def create_bitmap_file(width, height, predicate, name): cache_dir = os.path.join(thonny.THONNY_USER_DIR, "image_cache") name = "%s_%d_%d.xbm" % (name, width, height) filename = os.path.join(cache_dir, name) # if os.path.exists(filename): # return filename hex_lines = [] if width % 8 == 0: row_size = width else: # need to pad row size so that it is multiple of 8 row_size = width + 8 - (width % 8) for y in range(height): byte_hexes = [] for byte_index in range(row_size // 8): byte = 0 for bit_index in range(7, -1, -1): x = byte_index * 8 + bit_index byte <<= 1 if predicate(x, y): byte |= 1 byte_hexes.append(format(byte, "#04x")) hex_lines.append(",".join(byte_hexes)) data = ( "#define im_width %d\n" % width + "#define im_height %d\n" % height + "static char im_bits[] = {\n" + "%s\n" % ",\n".join(hex_lines) + "};" ) os.makedirs(cache_dir, exist_ok=True) with open(filename, "w") as fp: fp.write(data) return filename def configure_text(text): spacing1 = 2 spacing3 = 3 text_font = text["font"] text.configure(spacing1=spacing1, spacing3=spacing3) text.master._gutter.configure(spacing1=spacing1, spacing3=spacing3) if isinstance(text_font, str): text_font = font.nametofont(text_font) indent_width = text_font.measure(" ") bbox = text.bbox("1.0") if bbox is None or bbox[3] < 5: # text not ready yet # TODO: Text in Tk 8.6 has sync method return False line_height = bbox[3] + spacing1 + spacing3 print(indent_width, line_height) def ver(x: int, y: int, top: bool, bottom: bool) -> bool: # tells where to show pixels in vertical border of the statement # It would be convenient if tiling started from the start of # 1st char, but it is offset a bit # In order to make computation easier, I'm offsetting x as well x = (x - 5) % indent_width stripe_width = 8 gap = 3 left = indent_width - stripe_width - gap return ( left <= x < left + stripe_width or top and y == 0 and x >= left or bottom and y == line_height - 1 and x >= left ) def hor(x: int, y: int, top: bool, bottom: bool) -> bool: # tells where to show pixels in statement line return top and y == 0 or bottom and y == line_height - 1 color = get_syntax_options_for_tag("GUTTER").get("background", "gray") for orient, base_predicate in [("hor", hor), ("ver", ver)]: for top in [False, True]: for bottom in [False, True]: def predicate( x, y, # need to make base_predicate, top and bottom local base_predicate=base_predicate, top=top, bottom=bottom, ): return base_predicate(x, y, top, bottom) tag_name = "%s_%s_%s" % (orient, top, bottom) bitmap_path = create_bitmap_file(indent_width, line_height, predicate, tag_name) text.tag_configure(tag_name, background=color, bgstipple="@" + bitmap_path) return True def print_tree(node, level=0): indent = " " * level # if (isinstance(node, python_tree.PythonNode) and node.type == "sim" if node.type in ("simple_stmt",) or isinstance(node, python_tree.Flow): print(indent, node.type, node.start_pos, node.end_pos) if hasattr(node, "children"): for child in node.children: print_tree(child, level + 1) def clear_tags(text): for pos in ["ver", "hor"]: for top in [True, False]: for bottom in [True, False]: text.tag_remove("%s_%s_%s" % (pos, top, bottom), "1.0", "end") def add_tags(text): source = text.get("1.0", "end") clear_tags(text) tree = jedi_utils.parse_source(source) print_tree(tree) last_line = 0 last_col = 0 def tag_tree(node): nonlocal last_line, last_col if node.type == "simple_stmt" or isinstance(node, (python_tree.Flow, python_tree.Scope)): start_line, start_col = node.start_pos end_line, end_col = node.end_pos # Before dealing with this node, # handle the case, where last vertical tag was meant for # same column, but there were empty or comment lines between if start_col == last_col: for i in range(last_line + 1, start_line): # NB! tag not visible when logically empty line # doesn't have indent prefix text.tag_add( "ver_False_False", "%d.%d" % (i, last_col - 1), "%d.%d" % (i, last_col) ) print("ver_False_False", "%d.%d" % (i, last_col - 1), "%d.%d" % (i, last_col)) print(node) # usually end_col is 0 # exceptions: several statements on the same line (semicoloned statements) # also unclosed parens in if-header for lineno in range(start_line, end_line if end_col == 0 else end_line + 1): top = lineno == start_line and lineno > 1 bottom = False # start_line == end_line-1 # horizontal line (only for first or last line) if top or bottom: text.tag_add( "hor_%s_%s" % (top, bottom), "%d.%d" % (lineno, start_col), "%d.%d" % (lineno + 1 if end_col == 0 else lineno, 0), ) print( "hor_%s_%s" % (top, bottom), "%d.%d" % (lineno, start_col), "%d.%d" % (lineno + 1, 0), ) # vertical line (only for indented statements) # Note that I'm using start col for all lines # (statement's indent shouldn't decrease in continuation lines) if start_col > 0: text.tag_add( "ver_%s_%s" % (top, bottom), "%d.%d" % (lineno, start_col - 1), "%d.%d" % (lineno, start_col), ) print( "ver_%s_%s" % (top, bottom), "%d.%d" % (lineno, start_col - 1), "%d.%d" % (lineno, start_col), ) last_line = lineno last_col = start_col # Recurse if node.type != "simple_stmt" and hasattr(node, "children"): for child in node.children: tag_tree(child) tag_tree(tree) def handle_editor_event(event): configure_and_add_tags(event.editor.get_text_widget()) def handle_events(event): if hasattr(event, "text_widget"): text = event.text_widget else: text = event.widget configure_and_add_tags(text) def configure_and_add_tags(text): if not getattr(text, "structure_tags_configured", False): try: if configure_text(text): text.structure_tags_configured = True else: text.after(500, lambda: configure_and_add_tags(text)) return except Exception: logging.exception("Problem with defining structure tags") return add_tags(text) def _load_plugin() -> None: wb = get_workbench() wb.set_default("view.program_structure", False) wb.bind("Save", handle_editor_event, True) wb.bind("Open", handle_editor_event, True) wb.bind_class("CodeViewText", "<>", handle_events, True) thonny-3.2.7/thonny/plugins/notes.py0000644000175000017500000000402313611773167020571 0ustar annamaaannamaa00000000000000import os.path from thonny.tktextext import TextFrame, EnhancedText from thonny import get_workbench, ui_utils, THONNY_USER_DIR from thonny.ui_utils import TextMenu class NotesText(EnhancedText): def __init__(self, master, **kw): EnhancedText.__init__(self, master=master, wrap="word", undo=True, **kw) self.context_menu = TextMenu(self) def on_secondary_click(self, event=None): super().on_secondary_click(event=event) self.context_menu.tk_popup(event.x_root, event.y_root) class NotesView(TextFrame): def __init__(self, master): self.filename = os.path.join(THONNY_USER_DIR, "user_notes.txt") super().__init__( master, text_class=NotesText, horizontal_scrollbar_class=ui_utils.AutoScrollbar ) self.load_content() self.text.edit_reset() get_workbench().bind("ToplevelResponse", self.save_content, True) def load_content(self): if not os.path.isfile(self.filename): self.text.insert( "1.0", _( "This box is meant for your working notes -- assignment instructions, " + "code snippets, whatever.\n\n" + "Everything will be saved automatically " + "and loaded when you open Thonny next time.\n\n" + "Feel free to delete this text to make room for your own notes." ), ) return with open(self.filename, encoding="utf-8") as fp: content = fp.read() self.text.delete("1.0", "end") self.text.insert("1.0", content) self.text.mark_set("insert", "1.0") self.text.see("1.0") def save_content(self, event=None): with open(self.filename, "w", encoding="utf-8") as fp: fp.write(self.text.get("1.0", "end-1c")) def destroy(self): self.save_content() super().destroy() def load_plugin(): get_workbench().add_view(NotesView, _("Notes"), "ne", default_position_key="zz") thonny-3.2.7/thonny/plugins/micropython/0000755000175000017500000000000013611777205021440 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/micropython/__init__.py0000644000175000017500000004036313611774245023560 0ustar annamaaannamaa00000000000000import ast import logging import io import os import platform import queue import re import subprocess import sys import textwrap import threading import time import tokenize import traceback import webbrowser from queue import Queue from textwrap import dedent from time import sleep from tkinter import ttk, messagebox from thonny.ui_utils import askopenfilename, create_url_label from typing import Optional import jedi import serial.tools.list_ports from serial import SerialException from thonny import common, get_runner, get_shell, get_workbench, running from thonny.common import ( BackendEvent, InlineResponse, MessageFromBackend, ToplevelCommand, ToplevelResponse, InterruptCommand, EOFCommand, CommandToBackend, ) from thonny.config_ui import ConfigurationPage from thonny.misc_utils import find_volumes_by_name, TimeHelper from thonny.plugins.backend_config_page import BackendDetailsConfigPage from thonny.running import BackendProxy, SubprocessProxy from thonny.ui_utils import SubprocessDialog, create_string_var, show_dialog DEFAULT_WEBREPL_URL = "ws://192.168.4.1:8266/" class MicroPythonProxy(SubprocessProxy): def __init__(self, clean): self._port = get_workbench().get_option(self.backend_name + ".port") self._clean_start = clean if self._port == "auto": potential = self._detect_potential_ports() if len(potential) == 1: self._port = potential[0][0] else: self._port = None message = dedent( """\ Couldn't find the device automatically. Check the connection (making sure the device is not in bootloader mode) or choose "Tools → Options → Interpreter" to select the port manually.""" ) if len(potential) > 1: _, descriptions = zip(*potential) message += "\n\nLikely candidates are:\n * " + "\n * ".join(descriptions) self._show_error(message) super().__init__(clean, running.get_interpreter_for_subprocess()) # Following is required for compatibility with older MP plugins (ESP) # TODO: remove it later self.micropython_upload_enabled = False def _get_launcher_with_args(self): import thonny.plugins.micropython.backend cmd = [ thonny.plugins.micropython.backend.__file__, "--clean", str(self._clean_start), "--port", str(self._port), "--api_stubs_path", self._get_api_stubs_path(), ] if self._port == "webrepl": cmd.extend( [ "--url", get_workbench().get_option(self.backend_name + ".webrepl_url"), "--password", get_workbench().get_option(self.backend_name + ".webrepl_password"), ] ) return cmd def interrupt(self): self._send_msg(InterruptCommand()) """ # For some reason following kills the backend and KeyboardInterrupt can't be caught if self._proc is not None and self._proc.poll() is None: if running_on_windows(): try: os.kill(self._proc.pid, signal.CTRL_BREAK_EVENT) # @UndefinedVariable except Exception: logging.exception("Could not interrupt backend process") else: self._proc.send_signal(signal.SIGINT) """ def send_command(self, cmd: CommandToBackend) -> Optional[str]: if isinstance(cmd, EOFCommand): get_shell().restart() # Runner doesn't notice restart return super().send_command(cmd) def _clear_environment(self): "TODO:" def _detect_potential_ports(self): all_ports = list_serial_ports() """ for p in all_ports: print(p.description, p.device, None if p.vid is None else hex(p.vid), None if p.pid is None else hex(p.pid), ) """ return [ (p.device, p.description) for p in all_ports if (p.vid, p.pid) in self.known_usb_vids_pids or p.description in self.known_port_descriptions or self.consider_unknown_devices and ( ("USB" in p.description and "serial" in p.description.lower()) or "UART" in p.description or "DAPLink" in p.description or "STLink" in p.description ) ] @property def known_usb_vids_pids(self): """Return set of pairs of USB device VID, PID""" return set() @property def consider_unknown_devices(self): return True @property def known_port_descriptions(self): return set() def _get_api_stubs_path(self): import inspect return os.path.join(os.path.dirname(inspect.getfile(self.__class__)), "api_stubs") def supports_remote_files(self): return self._proc is not None def uses_local_filesystem(self): return False def ready_for_remote_file_operations(self): return self._proc is not None and get_runner().is_waiting_toplevel_command() def supports_remote_directories(self): return self._cwd is not None and self._cwd != "" def supports_trash(self): return False def is_connected(self): return self._proc is not None def _show_error(self, text): get_shell().print_error("\n" + text + "\n") def disconnect(self): self.destroy() def get_node_label(self): if "CircuitPython" in self._welcome_text: return _("CircuitPython device") elif "micro:bit" in self._welcome_text.lower(): return "micro:bit" else: return _("MicroPython device") def get_exe_dirs(self): return [] class MicroPythonConfigPage(BackendDetailsConfigPage): backend_name = None # Will be overwritten on Workbench.add_backend def __init__(self, master): super().__init__(master) intro_text = ( _("Connect your device to the computer and select corresponding port below") + "\n" + "(" + _('look for your device name, "USB Serial" or "UART"') + ").\n" + _("If you can't find it, you may need to install proper USB driver first.") ) if self.allow_webrepl: intro_text = ( ("Connecting via USB cable:") + "\n" + intro_text + "\n\n" + ("Connecting via WebREPL protocol:") + "\n" + ( "If your device supports WebREPL, first connect via serial, make sure WebREPL is enabled\n" + "(import webrepl_setup), connect your computer and device to same network and select < WebREPL > below" ) ) intro_label = ttk.Label(self, text=intro_text) intro_label.grid(row=0, column=0, sticky="nw") driver_url = self._get_usb_driver_url() if driver_url: driver_url_label = create_url_label(self, driver_url) driver_url_label.grid(row=1, column=0, sticky="nw") port_label = ttk.Label(self, text="Port or WebREPL" if self.allow_webrepl else _("Port")) port_label.grid(row=3, column=0, sticky="nw", pady=(10, 0)) self._ports_by_desc = { p.description if p.device in p.description else p.description + " (" + p.device + ")": p.device for p in list_serial_ports() } self._ports_by_desc["< " + _("Try to detect port automatically") + " >"] = "auto" self._WEBREPL_OPTION_DESC = "< WebREPL >" if self.allow_webrepl: self._ports_by_desc[self._WEBREPL_OPTION_DESC] = "webrepl" def port_order(p): _, name = p if name is None: return "" elif name.startswith("COM") and len(name) == 4: # Make one-digit COM ports go before COM10 return name.replace("COM", "COM0") else: return name # order by port, auto first port_descriptions = [key for key, _ in sorted(self._ports_by_desc.items(), key=port_order)] self._port_desc_variable = create_string_var( self.get_stored_port_desc(), self._on_change_port ) self._port_combo = ttk.Combobox( self, exportselection=False, textvariable=self._port_desc_variable, values=port_descriptions, ) self._port_combo.state(["!disabled", "readonly"]) self._port_combo.grid(row=4, column=0, sticky="new") self.columnconfigure(0, weight=1) self._webrepl_frame = None self._flashing_frame = None self._on_change_port() def _get_webrepl_frame(self): if self._webrepl_frame is not None: return self._webrepl_frame self._webrepl_frame = ttk.Frame(self) self._webrepl_url_var = create_string_var( get_workbench().get_option(self.backend_name + ".webrepl_url") ) url_label = ttk.Label(self._webrepl_frame, text="URL (eg. %s)" % DEFAULT_WEBREPL_URL) url_label.grid(row=0, column=0, sticky="nw", pady=(10, 0)) url_entry = ttk.Entry(self._webrepl_frame, textvariable=self._webrepl_url_var, width=24) url_entry.grid(row=1, column=0, sticky="nw") self._webrepl_password_var = create_string_var( get_workbench().get_option(self.backend_name + ".webrepl_password") ) pw_label = ttk.Label( self._webrepl_frame, text="Password (the one specified with `import webrepl_setup`)" ) pw_label.grid(row=2, column=0, sticky="nw", pady=(10, 0)) pw_entry = ttk.Entry(self._webrepl_frame, textvariable=self._webrepl_password_var, width=9) pw_entry.grid(row=3, column=0, sticky="nw") return self._webrepl_frame def _get_flashing_frame(self): if self._flashing_frame is not None: return self._flashing_frame self._flashing_frame = ttk.Frame(self) self._flashing_label = ttk.Label(self._flashing_frame, text=_("Firmware")) self._flashing_label.grid(row=1, column=0, sticky="w", pady=(10, 0)) button_caption = _("Open the dialog for installing or upgrading MicroPython on your device") self._flashing_button = ttk.Button( self._flashing_frame, text=button_caption, width=len(button_caption), command=self._open_flashing_dialog, ) self._flashing_button.grid(row=2, column=0, sticky="we") self._flashing_frame.columnconfigure(0, weight=1) return self._flashing_frame def get_stored_port_desc(self): name = get_workbench().get_option(self.backend_name + ".port") for desc in self._ports_by_desc: if self._ports_by_desc[desc] == name: return desc return "" def get_selected_port_name(self): port_desc = self._port_desc_variable.get() return self._ports_by_desc[port_desc] def is_modified(self): return ( self._port_desc_variable.modified # pylint: disable=no-member or self.webrepl_selected() and self._webrepl_password_var.modified # pylint: disable=no-member or self.webrepl_selected() and self._webrepl_url_var.modified ) # pylint: disable=no-member def webrepl_selected(self): return self.get_selected_port_name() == "webrepl" def should_restart(self): return self.is_modified() def apply(self): if not self.is_modified(): return else: port_name = self.get_selected_port_name() get_workbench().set_option(self.backend_name + ".port", port_name) if self.webrepl_selected(): get_workbench().set_option( self.backend_name + ".webrepl_url", self._webrepl_url_var.get() ) get_workbench().set_option( self.backend_name + ".webrepl_password", self._webrepl_password_var.get() ) def _on_change_port(self, *args): if self._port_desc_variable.get() == self._WEBREPL_OPTION_DESC: self._get_webrepl_frame().grid(row=6, column=0, sticky="nwe") if self._flashing_frame and self._flashing_frame.winfo_ismapped(): self._flashing_frame.grid_forget() else: if self._has_flashing_dialog(): self._get_flashing_frame().grid(row=6, column=0, sticky="nwe") if self._webrepl_frame and self._webrepl_frame.winfo_ismapped(): self._webrepl_frame.grid_forget() def _get_usb_driver_url(self): return None def _has_flashing_dialog(self): return False def _open_flashing_dialog(self): raise NotImplementedError() @property def allow_webrepl(self): return False class GenericMicroPythonProxy(MicroPythonProxy): @property def known_usb_vids_pids(self): """Return set of pairs of USB device (VID, PID)""" return { # Generic MicroPython Board, see http://pid.codes/org/MicroPython/ (0x1209, 0xADDA) } class GenericMicroPythonConfigPage(MicroPythonConfigPage): @property def allow_webrepl(self): return False def list_serial_ports(): # serial.tools.list_ports.comports() can be too slow # because os.path.islink can be too slow (https://github.com/pyserial/pyserial/pull/303) # Workarond: temporally patch os.path.islink try: old_islink = os.path.islink if platform.system() == "Windows": os.path.islink = lambda _: False return list(serial.tools.list_ports.comports()) finally: os.path.islink = old_islink def list_serial_ports_with_descriptions(): def port_order(p): name = p.device if name is None: return "" elif name.startswith("COM") and len(name) == 4: # Make one-digit COM ports go before COM10 return name.replace("COM", "COM0") else: return name sorted_ports = sorted(list_serial_ports(), key=port_order) return [ ( p.description if p.device in p.description else p.description + " (" + p.device + ")", p.device, ) for p in sorted_ports ] def add_micropython_backend(name, proxy_class, description, config_page): get_workbench().set_default(name + ".port", "auto") get_workbench().set_default(name + ".webrepl_url", DEFAULT_WEBREPL_URL) get_workbench().set_default(name + ".webrepl_password", "") get_workbench().add_backend(name, proxy_class, description, config_page) def load_plugin(): add_micropython_backend( "GenericMicroPython", GenericMicroPythonProxy, _("MicroPython (generic)"), GenericMicroPythonConfigPage, ) def explain_deprecation(): messagebox.showinfo( "Moved commands", dedent( """ MicroPython commands have been moved or replaced: * "Select device" * Moved into "Run" menu as "Select interpreter" * "Upload current script as main script" * "Upload current script as boot script" * "Upload current script with current name" * use "File => Save copy..." * "Show device's main script" * "Show device's boot script" * Double-click in Files view (Show => Files) * "Upload ____ firmware" * Moved into interpreter config page or "Tools" menu * "Soft reboot" * Moved into "Run" menu as "Send EOF / Soft reboot" " "Close serial connection" * Moved into "Run" menu as "Disconnect" """ ), ) get_workbench().add_command( "devicedeprecation", "tempdevice", "Where are all the commands?", explain_deprecation, group=1, ) thonny-3.2.7/thonny/plugins/micropython/api_stubs/0000755000175000017500000000000013611777205023431 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/micropython/api_stubs/os.py0000644000175000017500000000150613611773167024431 0ustar annamaaannamaa00000000000000class VfsFat: "" def chdir(): pass def getcwd(): pass def ilistdir(): pass def mkdir(): pass def mkfs(): pass def mount(): pass def open(): pass def remove(): pass def rename(): pass def rmdir(): pass def stat(): pass def statvfs(): pass def umount(): pass def chdir(): pass def dupterm(): pass def getcwd(): pass def ilistdir(): pass def listdir(): pass def mkdir(): pass def mount(): pass def remove(): pass def rename(): pass def rmdir(): pass sep = "/" def stat(): pass def statvfs(): pass def sync(): pass def umount(): pass def uname(): pass def unlink(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/ubinascii.py0000644000175000017500000000015613611773167025756 0ustar annamaaannamaa00000000000000def a2b_base64(): pass def b2a_base64(): pass def hexlify(): pass def unhexlify(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/stm.py0000644000175000017500000000663113611773167024617 0ustar annamaaannamaa00000000000000ADC1 = 1073815552 ADC1_COMMON = 1073816320 ADC_CR1 = 4 ADC_CR2 = 8 ADC_DR = 76 ADC_HTR = 36 ADC_JDR1 = 60 ADC_JDR2 = 64 ADC_JDR3 = 68 ADC_JDR4 = 72 ADC_JOFR1 = 20 ADC_JOFR2 = 24 ADC_JOFR3 = 28 ADC_JOFR4 = 32 ADC_JSQR = 56 ADC_LTR = 40 ADC_SMPR1 = 12 ADC_SMPR2 = 16 ADC_SQR1 = 44 ADC_SQR2 = 48 ADC_SQR3 = 52 ADC_SR = 0 CRC = 1073885184 CRC_CR = 8 CRC_DR = 0 CRC_IDR = 4 DBGMCU = 3758366720 DBGMCU_APB1FZ = 8 DBGMCU_APB2FZ = 12 DBGMCU_CR = 4 DBGMCU_IDCODE = 0 DMA1 = 1073897472 DMA2 = 1073898496 DMA_HIFCR = 12 DMA_HISR = 4 DMA_LIFCR = 8 DMA_LISR = 0 EXTI = 1073822720 EXTI_EMR = 4 EXTI_FTSR = 12 EXTI_IMR = 0 EXTI_PR = 20 EXTI_RTSR = 8 EXTI_SWIER = 16 FLASH = 1073888256 FLASH_ACR = 0 FLASH_CR = 16 FLASH_KEYR = 4 FLASH_OPTCR = 20 FLASH_OPTCR1 = 24 FLASH_OPTKEYR = 8 FLASH_SR = 12 GPIOA = 1073872896 GPIOB = 1073873920 GPIOC = 1073874944 GPIOD = 1073875968 GPIOE = 1073876992 GPIOH = 1073880064 GPIO_AFR0 = 32 GPIO_AFR1 = 36 GPIO_BSRR = 24 GPIO_BSRRH = 26 GPIO_BSRRL = 24 GPIO_IDR = 16 GPIO_LCKR = 28 GPIO_MODER = 0 GPIO_ODR = 20 GPIO_OSPEEDR = 8 GPIO_OTYPER = 4 GPIO_PUPDR = 12 I2C1 = 1073763328 I2C2 = 1073764352 I2C3 = 1073765376 I2C_CCR = 28 I2C_CR1 = 0 I2C_CR2 = 4 I2C_DR = 16 I2C_FLTR = 36 I2C_OAR1 = 8 I2C_OAR2 = 12 I2C_SR1 = 20 I2C_SR2 = 24 I2C_TRISE = 32 I2S2EXT = 1073755136 I2S3EXT = 1073758208 IWDG = 1073754112 IWDG_KR = 0 IWDG_PR = 4 IWDG_RLR = 8 IWDG_SR = 12 PWR = 1073770496 PWR_CR = 0 PWR_CSR = 4 RCC = 1073887232 RCC_AHB1ENR = 48 RCC_AHB1LPENR = 80 RCC_AHB1RSTR = 16 RCC_AHB2ENR = 52 RCC_AHB2LPENR = 84 RCC_AHB2RSTR = 20 RCC_AHB3ENR = 56 RCC_AHB3LPENR = 88 RCC_AHB3RSTR = 24 RCC_APB1ENR = 64 RCC_APB1LPENR = 96 RCC_APB1RSTR = 32 RCC_APB2ENR = 68 RCC_APB2LPENR = 100 RCC_APB2RSTR = 36 RCC_BDCR = 112 RCC_CFGR = 8 RCC_CIR = 12 RCC_CR = 0 RCC_CSR = 116 RCC_DCKCFGR = 140 RCC_PLLCFGR = 4 RCC_PLLI2SCFGR = 132 RCC_SSCGR = 128 RTC = 1073752064 RTC_ALRMAR = 28 RTC_ALRMBR = 32 RTC_BKP0R = 80 RTC_BKP10R = 120 RTC_BKP11R = 124 RTC_BKP12R = 128 RTC_BKP13R = 132 RTC_BKP14R = 136 RTC_BKP15R = 140 RTC_BKP16R = 144 RTC_BKP17R = 148 RTC_BKP18R = 152 RTC_BKP19R = 156 RTC_BKP1R = 84 RTC_BKP2R = 88 RTC_BKP3R = 92 RTC_BKP4R = 96 RTC_BKP5R = 100 RTC_BKP6R = 104 RTC_BKP7R = 108 RTC_BKP8R = 112 RTC_BKP9R = 116 RTC_CALIBR = 24 RTC_CALR = 60 RTC_CR = 8 RTC_DR = 4 RTC_ISR = 12 RTC_PRER = 16 RTC_SHIFTR = 44 RTC_SSR = 40 RTC_TAFCR = 64 RTC_TR = 0 RTC_TSDR = 52 RTC_TSSSR = 56 RTC_TSTR = 48 RTC_WPR = 36 RTC_WUTR = 20 SDIO = 1073818624 SPI1 = 1073819648 SPI2 = 1073756160 SPI3 = 1073757184 SPI4 = 1073820672 SPI5 = 1073827840 SPI_CR1 = 0 SPI_CR2 = 4 SPI_CRCPR = 16 SPI_DR = 12 SPI_I2SCFGR = 28 SPI_I2SPR = 32 SPI_RXCRCR = 20 SPI_SR = 8 SPI_TXCRCR = 24 SYSCFG = 1073821696 SYSCFG_CMPCR = 32 SYSCFG_EXTICR0 = 8 SYSCFG_EXTICR1 = 12 SYSCFG_EXTICR2 = 16 SYSCFG_EXTICR3 = 20 SYSCFG_MEMRMP = 0 SYSCFG_PMC = 4 TIM1 = 1073807360 TIM10 = 1073824768 TIM11 = 1073825792 TIM2 = 1073741824 TIM3 = 1073742848 TIM4 = 1073743872 TIM5 = 1073744896 TIM9 = 1073823744 TIM_ARR = 44 TIM_BDTR = 68 TIM_CCER = 32 TIM_CCMR1 = 24 TIM_CCMR2 = 28 TIM_CCR1 = 52 TIM_CCR2 = 56 TIM_CCR3 = 60 TIM_CCR4 = 64 TIM_CNT = 36 TIM_CR1 = 0 TIM_CR2 = 4 TIM_DCR = 72 TIM_DIER = 12 TIM_DMAR = 76 TIM_EGR = 20 TIM_OR = 80 TIM_PSC = 40 TIM_RCR = 48 TIM_SMCR = 8 TIM_SR = 16 USART1 = 1073811456 USART2 = 1073759232 USART6 = 1073812480 USART_BRR = 8 USART_CR1 = 12 USART_CR2 = 16 USART_CR3 = 20 USART_DR = 4 USART_GTPR = 24 USART_SR = 0 WWDG = 1073753088 WWDG_CFR = 4 WWDG_CR = 0 WWDG_SR = 8 mem16 = None mem32 = None mem8 = None thonny-3.2.7/thonny/plugins/micropython/api_stubs/uselect.py0000644000175000017500000000014013611773167025445 0ustar annamaaannamaa00000000000000POLLERR = 8 POLLHUP = 16 POLLIN = 1 POLLOUT = 4 def poll(): pass def select(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/_onewire.py0000644000175000017500000000023113611773167025611 0ustar annamaaannamaa00000000000000def crc8(): pass def readbit(): pass def readbyte(): pass def reset(): pass def writebit(): pass def writebyte(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/uctypes.py0000644000175000017500000000105313611773167025501 0ustar annamaaannamaa00000000000000ARRAY = -1073741824 BFINT16 = -671088640 BFINT32 = -402653184 BFINT8 = -939524096 BFUINT16 = -805306368 BFUINT32 = -536870912 BFUINT8 = -1073741824 BF_LEN = 22 BF_POS = 17 BIG_ENDIAN = 1 FLOAT32 = -268435456 FLOAT64 = -134217728 INT16 = 402653184 INT32 = 671088640 INT64 = 939524096 INT8 = 134217728 LITTLE_ENDIAN = 0 NATIVE = 2 PTR = 536870912 UINT16 = 268435456 UINT32 = 536870912 UINT64 = 805306368 UINT8 = 0 VOID = 0 def addressof(): pass def bytearray_at(): pass def bytes_at(): pass def sizeof(): pass class struct: "" thonny-3.2.7/thonny/plugins/micropython/api_stubs/random.py0000644000175000017500000000026513611773167025271 0ustar annamaaannamaa00000000000000def choice(): pass def getrandbits(): pass def randint(): pass def random(): pass def randrange(): pass def seed(): pass def uniform(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/errno.py0000644000175000017500000000050413611773167025132 0ustar annamaaannamaa00000000000000EACCES = 13 EADDRINUSE = 98 EAGAIN = 11 EALREADY = 114 EBADF = 9 ECONNABORTED = 103 ECONNREFUSED = 111 ECONNRESET = 104 EEXIST = 17 EHOSTUNREACH = 113 EINPROGRESS = 115 EINVAL = 22 EIO = 5 EISDIR = 21 ENOBUFS = 105 ENODEV = 19 ENOENT = 2 ENOMEM = 12 ENOTCONN = 107 EOPNOTSUPP = 95 EPERM = 1 ETIMEDOUT = 110 errorcode = None thonny-3.2.7/thonny/plugins/micropython/api_stubs/uzlib.py0000644000175000017500000000022613611773167025133 0ustar annamaaannamaa00000000000000class DecompIO: "" def read(): pass def readinto(): pass def readline(): pass def decompress(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/ustruct.py0000644000175000017500000000020313611773167025512 0ustar annamaaannamaa00000000000000def calcsize(): pass def pack(): pass def pack_into(): pass def unpack(): pass def unpack_from(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/time.py0000644000175000017500000000044313611773167024745 0ustar annamaaannamaa00000000000000def localtime(): pass def mktime(): pass def sleep(): pass def sleep_ms(): pass def sleep_us(): pass def ticks_add(): pass def ticks_cpu(): pass def ticks_diff(): pass def ticks_ms(): pass def ticks_us(): pass def time(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/uerrno.py0000644000175000017500000000050413611773167025317 0ustar annamaaannamaa00000000000000EACCES = 13 EADDRINUSE = 98 EAGAIN = 11 EALREADY = 114 EBADF = 9 ECONNABORTED = 103 ECONNREFUSED = 111 ECONNRESET = 104 EEXIST = 17 EHOSTUNREACH = 113 EINPROGRESS = 115 EINVAL = 22 EIO = 5 EISDIR = 21 ENOBUFS = 105 ENODEV = 19 ENOENT = 2 ENOMEM = 12 ENOTCONN = 107 EOPNOTSUPP = 95 EPERM = 1 ETIMEDOUT = 110 errorcode = None thonny-3.2.7/thonny/plugins/micropython/api_stubs/re.py0000644000175000017500000000013013611773167024406 0ustar annamaaannamaa00000000000000DEBUG = 4096 def compile(): pass def match(): pass def search(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/zlib.py0000644000175000017500000000022613611773167024746 0ustar annamaaannamaa00000000000000class DecompIO: "" def read(): pass def readinto(): pass def readline(): pass def decompress(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/hashlib.py0000644000175000017500000000012513611773167025416 0ustar annamaaannamaa00000000000000class sha256: "" def digest(): pass def update(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/pyb.py0000644000175000017500000001426113611773167024604 0ustar annamaaannamaa00000000000000class ADC: "" def read(): pass def read_timed(): pass def read_timed_multi(): pass class ADCAll: "" def read_channel(): pass def read_core_temp(): pass def read_core_vbat(): pass def read_core_vref(): pass def read_vref(): pass class Accel: "" def filtered_xyz(): pass def read(): pass def tilt(): pass def write(): pass def x(): pass def y(): pass def z(): pass class ExtInt: "" EVT_FALLING = 270663680 EVT_RISING = 269615104 EVT_RISING_FALLING = 271712256 IRQ_FALLING = 270598144 IRQ_RISING = 269549568 IRQ_RISING_FALLING = 271646720 def disable(): pass def enable(): pass def line(): pass def regs(): pass def swint(): pass class Flash: "" def ioctl(): pass def readblocks(): pass def writeblocks(): pass class I2C: "" MASTER = 0 SLAVE = 1 def deinit(): pass def init(): pass def is_ready(): pass def mem_read(): pass def mem_write(): pass def recv(): pass def scan(): pass def send(): pass class LCD: "" def command(): pass def contrast(): pass def fill(): pass def get(): pass def light(): pass def pixel(): pass def show(): pass def text(): pass def write(): pass class LED: "" def intensity(): pass def off(): pass def on(): pass def toggle(): pass class Pin: "" AF1_TIM1 = 1 AF1_TIM2 = 1 AF2_TIM3 = 2 AF2_TIM4 = 2 AF2_TIM5 = 2 AF3_TIM10 = 3 AF3_TIM11 = 3 AF3_TIM9 = 3 AF4_I2C1 = 4 AF4_I2C3 = 4 AF5_SPI1 = 5 AF5_SPI2 = 5 AF7_USART1 = 7 AF7_USART2 = 7 AF8_USART6 = 8 AF9_I2C3 = 9 AF_OD = 18 AF_PP = 2 ALT = 2 ALT_OPEN_DRAIN = 18 ANALOG = 3 IN = 0 IRQ_FALLING = 270598144 IRQ_RISING = 269549568 OPEN_DRAIN = 17 OUT = 1 OUT_OD = 17 OUT_PP = 1 PULL_DOWN = 2 PULL_NONE = 0 PULL_UP = 1 def af(): pass def af_list(): pass board = None cpu = None def debug(): pass def dict(): pass def gpio(): pass def high(): pass def init(): pass def irq(): pass def low(): pass def mapper(): pass def mode(): pass def name(): pass def names(): pass def off(): pass def on(): pass def pin(): pass def port(): pass def pull(): pass def value(): pass class RTC: "" def calibration(): pass def datetime(): pass def info(): pass def init(): pass def wakeup(): pass SD = None class SDCard: "" def info(): pass def ioctl(): pass def power(): pass def present(): pass def read(): pass def readblocks(): pass def write(): pass def writeblocks(): pass class SPI: "" LSB = 128 MASTER = 260 MSB = 0 SLAVE = 0 def deinit(): pass def init(): pass def read(): pass def readinto(): pass def recv(): pass def send(): pass def send_recv(): pass def write(): pass def write_readinto(): pass class Servo: "" def angle(): pass def calibration(): pass def pulse_width(): pass def speed(): pass class Switch: "" def callback(): pass def value(): pass class Timer: "" BOTH = 10 CENTER = 32 DOWN = 16 ENC_A = 9 ENC_AB = 11 ENC_B = 10 FALLING = 2 HIGH = 0 IC = 8 LOW = 2 OC_ACTIVE = 3 OC_FORCED_ACTIVE = 6 OC_FORCED_INACTIVE = 7 OC_INACTIVE = 4 OC_TIMING = 2 OC_TOGGLE = 5 PWM = 0 PWM_INVERTED = 1 RISING = 0 UP = 0 def callback(): pass def channel(): pass def counter(): pass def deinit(): pass def freq(): pass def init(): pass def period(): pass def prescaler(): pass def source_freq(): pass class UART: "" CTS = 512 RTS = 256 def any(): pass def deinit(): pass def init(): pass def read(): pass def readchar(): pass def readinto(): pass def readline(): pass def sendbreak(): pass def write(): pass def writechar(): pass class USB_HID: "" def recv(): pass def send(): pass class USB_VCP: "" def any(): pass def close(): pass def isconnected(): pass def read(): pass def readinto(): pass def readline(): pass def readlines(): pass def recv(): pass def send(): pass def setinterrupt(): pass def write(): pass def bootloader(): pass def delay(): pass def dht_readinto(): pass def disable_irq(): pass def elapsed_micros(): pass def elapsed_millis(): pass def enable_irq(): pass def fault_debug(): pass def freq(): pass def hard_reset(): pass def have_cdc(): pass def hid(): pass hid_keyboard = None hid_mouse = None def info(): pass def main(): pass def micros(): pass def millis(): pass def mount(): pass def pwm(): pass def repl_info(): pass def repl_uart(): pass def servo(): pass def standby(): pass def stop(): pass def sync(): pass def udelay(): pass def unique_id(): pass def usb_mode(): pass def wfi(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/urandom.py0000644000175000017500000000026513611773167025456 0ustar annamaaannamaa00000000000000def choice(): pass def getrandbits(): pass def randint(): pass def random(): pass def randrange(): pass def seed(): pass def uniform(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/utime.py0000644000175000017500000000044313611773167025132 0ustar annamaaannamaa00000000000000def localtime(): pass def mktime(): pass def sleep(): pass def sleep_ms(): pass def sleep_us(): pass def ticks_add(): pass def ticks_cpu(): pass def ticks_diff(): pass def ticks_ms(): pass def ticks_us(): pass def time(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/gc.py0000644000175000017500000000027213611773167024400 0ustar annamaaannamaa00000000000000def collect(): pass def disable(): pass def enable(): pass def isenabled(): pass def mem_alloc(): pass def mem_free(): pass def threshold(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/ujson.py0000644000175000017500000000013413611773167025142 0ustar annamaaannamaa00000000000000def dump(): pass def dumps(): pass def load(): pass def loads(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/builtins.py0000644000175000017500000001355613611773167025651 0ustar annamaaannamaa00000000000000class ArithmeticError: "" class AssertionError: "" class AttributeError: "" class BaseException: "" class EOFError: "" Ellipsis = None class Exception: "" class GeneratorExit: "" class ImportError: "" class IndentationError: "" class IndexError: "" class KeyError: "" class KeyboardInterrupt: "" class LookupError: "" class MemoryError: "" class NameError: "" class NotImplementedError: "" class OSError: "" class OverflowError: "" class RuntimeError: "" class StopAsyncIteration: "" class StopIteration: "" class SyntaxError: "" class SystemExit: "" class TypeError: "" class UnicodeError: "" class ValueError: "" class ViperTypeError: "" class ZeroDivisionError: "" def abs(): pass def all(): pass def any(): pass def bin(): pass class bool: "" class bytearray: "" def append(): pass def extend(): pass class bytes: "" def center(): pass def count(): pass def decode(): pass def endswith(): pass def find(): pass def format(): pass def index(): pass def isalpha(): pass def isdigit(): pass def islower(): pass def isspace(): pass def isupper(): pass def join(): pass def lower(): pass def lstrip(): pass def partition(): pass def replace(): pass def rfind(): pass def rindex(): pass def rpartition(): pass def rsplit(): pass def rstrip(): pass def split(): pass def splitlines(): pass def startswith(): pass def strip(): pass def upper(): pass def callable(): pass def chr(): pass class classmethod: "" def compile(): pass class complex: "" def delattr(): pass class dict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass def dir(): pass def divmod(): pass class enumerate: "" def eval(): pass def exec(): pass def execfile(): pass class filter: "" class float: "" class frozenset: "" def copy(): pass def difference(): pass def intersection(): pass def isdisjoint(): pass def issubset(): pass def issuperset(): pass def symmetric_difference(): pass def union(): pass def getattr(): pass def globals(): pass def hasattr(): pass def hash(): pass def help(): pass def hex(): pass def id(): pass def input(): pass class int: "" def from_bytes(): pass def to_bytes(): pass def isinstance(): pass def issubclass(): pass def iter(): pass def len(): pass class list: "" def append(): pass def clear(): pass def copy(): pass def count(): pass def extend(): pass def index(): pass def insert(): pass def pop(): pass def remove(): pass def reverse(): pass def sort(): pass def locals(): pass class map: "" def max(): pass class memoryview: "" def min(): pass def next(): pass class object: "" def oct(): pass def open(): pass def ord(): pass def pow(): pass def print(): pass class property: "" def deleter(): pass def getter(): pass def setter(): pass class range: "" def repr(): pass class reversed: "" def round(): pass class set: "" def add(): pass def clear(): pass def copy(): pass def difference(): pass def difference_update(): pass def discard(): pass def intersection(): pass def intersection_update(): pass def isdisjoint(): pass def issubset(): pass def issuperset(): pass def pop(): pass def remove(): pass def symmetric_difference(): pass def symmetric_difference_update(): pass def union(): pass def update(): pass def setattr(): pass class slice: "" def sorted(): pass class staticmethod: "" class str: "" def center(): pass def count(): pass def encode(): pass def endswith(): pass def find(): pass def format(): pass def index(): pass def isalpha(): pass def isdigit(): pass def islower(): pass def isspace(): pass def isupper(): pass def join(): pass def lower(): pass def lstrip(): pass def partition(): pass def replace(): pass def rfind(): pass def rindex(): pass def rpartition(): pass def rsplit(): pass def rstrip(): pass def split(): pass def splitlines(): pass def startswith(): pass def strip(): pass def upper(): pass def sum(): pass class super: "" class tuple: "" def count(): pass def index(): pass class type: "" class zip: "" thonny-3.2.7/thonny/plugins/micropython/api_stubs/select.py0000644000175000017500000000014013611773167025260 0ustar annamaaannamaa00000000000000POLLERR = 8 POLLHUP = 16 POLLIN = 1 POLLOUT = 4 def poll(): pass def select(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/json.py0000644000175000017500000000013413611773167024755 0ustar annamaaannamaa00000000000000def dump(): pass def dumps(): pass def load(): pass def loads(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/dht.py0000644000175000017500000000052213611773167024564 0ustar annamaaannamaa00000000000000class DHT11: "" def humidity(): pass def measure(): pass def temperature(): pass class DHT22: "" def humidity(): pass def measure(): pass def temperature(): pass class DHTBase: "" def measure(): pass def dht_readinto(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/onewire.py0000644000175000017500000000100013611773167025445 0ustar annamaaannamaa00000000000000class OneWire: "" MATCH_ROM = 85 SEARCH_ROM = 240 SKIP_ROM = 204 def _search_rom(): pass def crc8(): pass def readbit(): pass def readbyte(): pass def readinto(): pass def reset(): pass def scan(): pass def select_rom(): pass def write(): pass def writebit(): pass def writebyte(): pass class OneWireError: "" _ow = None def const(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/uos.py0000644000175000017500000000150613611773167024616 0ustar annamaaannamaa00000000000000class VfsFat: "" def chdir(): pass def getcwd(): pass def ilistdir(): pass def mkdir(): pass def mkfs(): pass def mount(): pass def open(): pass def remove(): pass def rename(): pass def rmdir(): pass def stat(): pass def statvfs(): pass def umount(): pass def chdir(): pass def dupterm(): pass def getcwd(): pass def ilistdir(): pass def listdir(): pass def mkdir(): pass def mount(): pass def remove(): pass def rename(): pass def rmdir(): pass sep = "/" def stat(): pass def statvfs(): pass def sync(): pass def umount(): pass def uname(): pass def unlink(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/heapq.py0000644000175000017500000000011513611773167025101 0ustar annamaaannamaa00000000000000def heapify(): pass def heappop(): pass def heappush(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/cmath.py0000644000175000017500000000035313611773167025103 0ustar annamaaannamaa00000000000000def cos(): pass e = 2.718282 def exp(): pass def log(): pass def log10(): pass def phase(): pass pi = 3.141593 def polar(): pass def rect(): pass def sin(): pass def sqrt(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/uhashlib.py0000644000175000017500000000012513611773167025603 0ustar annamaaannamaa00000000000000class sha256: "" def digest(): pass def update(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/machine.py0000644000175000017500000000544113611773167025416 0ustar annamaaannamaa00000000000000DEEPSLEEP_RESET = 4 HARD_RESET = 2 class I2C: "" def init(): pass def readfrom(): pass def readfrom_into(): pass def readfrom_mem(): pass def readfrom_mem_into(): pass def readinto(): pass def scan(): pass def start(): pass def stop(): pass def write(): pass def writeto(): pass def writeto_mem(): pass PWRON_RESET = 1 class Pin: "" AF1_TIM1 = 1 AF1_TIM2 = 1 AF2_TIM3 = 2 AF2_TIM4 = 2 AF2_TIM5 = 2 AF3_TIM10 = 3 AF3_TIM11 = 3 AF3_TIM9 = 3 AF4_I2C1 = 4 AF4_I2C3 = 4 AF5_SPI1 = 5 AF5_SPI2 = 5 AF7_USART1 = 7 AF7_USART2 = 7 AF8_USART6 = 8 AF9_I2C3 = 9 AF_OD = 18 AF_PP = 2 ALT = 2 ALT_OPEN_DRAIN = 18 ANALOG = 3 IN = 0 IRQ_FALLING = 270598144 IRQ_RISING = 269549568 OPEN_DRAIN = 17 OUT = 1 OUT_OD = 17 OUT_PP = 1 PULL_DOWN = 2 PULL_NONE = 0 PULL_UP = 1 def af(): pass def af_list(): pass board = None cpu = None def debug(): pass def dict(): pass def gpio(): pass def high(): pass def init(): pass def irq(): pass def low(): pass def mapper(): pass def mode(): pass def name(): pass def names(): pass def off(): pass def on(): pass def pin(): pass def port(): pass def pull(): pass def value(): pass SOFT_RESET = 0 class SPI: "" LSB = 128 MSB = 0 def deinit(): pass def init(): pass def read(): pass def readinto(): pass def write(): pass def write_readinto(): pass class Signal: "" def off(): pass def on(): pass def value(): pass class UART: "" CTS = 512 RTS = 256 def any(): pass def deinit(): pass def init(): pass def read(): pass def readchar(): pass def readinto(): pass def readline(): pass def sendbreak(): pass def write(): pass def writechar(): pass class WDT: "" def feed(): pass WDT_RESET = 3 def bootloader(): pass def deepsleep(): pass def disable_irq(): pass def enable_irq(): pass def freq(): pass def idle(): pass def info(): pass mem16 = None mem32 = None mem8 = None def reset(): pass def reset_cause(): pass def sleep(): pass def soft_reset(): pass def time_pulse_us(): pass def unique_id(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/framebuf.py0000644000175000017500000000072213611773167025576 0ustar annamaaannamaa00000000000000class FrameBuffer: "" def blit(): pass def fill(): pass def fill_rect(): pass def hline(): pass def line(): pass def pixel(): pass def rect(): pass def scroll(): pass def text(): pass def vline(): pass def FrameBuffer1(): pass GS2_HMSB = 5 GS4_HMSB = 2 GS8 = 6 MONO_HLSB = 3 MONO_HMSB = 4 MONO_VLSB = 0 MVLSB = 0 RGB565 = 1 thonny-3.2.7/thonny/plugins/micropython/api_stubs/collections.py0000644000175000017500000000075113611773167026327 0ustar annamaaannamaa00000000000000class OrderedDict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass class deque: "" def append(): pass def popleft(): pass def namedtuple(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/binascii.py0000644000175000017500000000015613611773167025571 0ustar annamaaannamaa00000000000000def a2b_base64(): pass def b2a_base64(): pass def hexlify(): pass def unhexlify(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/array.py0000644000175000017500000000012413611773167025121 0ustar annamaaannamaa00000000000000class array: "" def append(): pass def extend(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/io.py0000644000175000017500000000226513611773167024422 0ustar annamaaannamaa00000000000000class BytesIO: "" def close(): pass def flush(): pass def getvalue(): pass def read(): pass def readinto(): pass def readline(): pass def seek(): pass def write(): pass class FileIO: "" def close(): pass def flush(): pass def read(): pass def readinto(): pass def readline(): pass def readlines(): pass def seek(): pass def tell(): pass def write(): pass class StringIO: "" def close(): pass def flush(): pass def getvalue(): pass def read(): pass def readinto(): pass def readline(): pass def seek(): pass def write(): pass class TextIOWrapper: "" def close(): pass def flush(): pass def read(): pass def readinto(): pass def readline(): pass def readlines(): pass def seek(): pass def tell(): pass def write(): pass def open(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/utimeq.py0000644000175000017500000000016213611773167025311 0ustar annamaaannamaa00000000000000class utimeq: "" def peektime(): pass def pop(): pass def push(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/ucollections.py0000644000175000017500000000075113611773167026514 0ustar annamaaannamaa00000000000000class OrderedDict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass class deque: "" def append(): pass def popleft(): pass def namedtuple(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/lcd160cr.py0000644000175000017500000000427013611773167025327 0ustar annamaaannamaa00000000000000LANDSCAPE = 1 LANDSCAPE_UPSIDEDOWN = 3 class LCD160CR: "" def _fcmd2(): pass def _fcmd2b(): pass def _send(): pass def _waitfor(): pass def clip_line(): pass def dot(): pass def dot_no_clip(): pass def erase(): pass def fast_spi(): pass def feed_wdt(): pass def get_line(): pass def get_pixel(): pass def get_touch(): pass def iflush(): pass def is_touched(): pass def jpeg(): pass def jpeg_data(): pass def jpeg_start(): pass def line(): pass def line_no_clip(): pass def oflush(): pass def poly_dot(): pass def poly_line(): pass def rect(): pass def rect_interior(): pass def rect_interior_no_clip(): pass def rect_no_clip(): pass def rect_outline(): pass def rect_outline_no_clip(): pass def reset(): pass def rgb(): pass def save_to_flash(): pass def screen_dump(): pass def screen_load(): pass def set_brightness(): pass def set_font(): pass def set_i2c_addr(): pass def set_orient(): pass def set_pen(): pass def set_pixel(): pass def set_pos(): pass def set_power(): pass def set_scroll(): pass def set_scroll_buf(): pass def set_scroll_win(): pass def set_scroll_win_param(): pass def set_spi_win(): pass def set_startup_deco(): pass def set_text_color(): pass def set_uart_baudrate(): pass def show_framebuf(): pass def touch_config(): pass def write(): pass PORTRAIT = 0 PORTRAIT_UPSIDEDOWN = 2 STARTUP_DECO_INFO = 2 STARTUP_DECO_MLOGO = 1 STARTUP_DECO_NONE = 0 _uart_baud_table = None def calcsize(): pass def const(): pass machine = None def pack_into(): pass def sleep_ms(): pass uerrno = None thonny-3.2.7/thonny/plugins/micropython/api_stubs/umachine.py0000644000175000017500000000544113611773167025603 0ustar annamaaannamaa00000000000000DEEPSLEEP_RESET = 4 HARD_RESET = 2 class I2C: "" def init(): pass def readfrom(): pass def readfrom_into(): pass def readfrom_mem(): pass def readfrom_mem_into(): pass def readinto(): pass def scan(): pass def start(): pass def stop(): pass def write(): pass def writeto(): pass def writeto_mem(): pass PWRON_RESET = 1 class Pin: "" AF1_TIM1 = 1 AF1_TIM2 = 1 AF2_TIM3 = 2 AF2_TIM4 = 2 AF2_TIM5 = 2 AF3_TIM10 = 3 AF3_TIM11 = 3 AF3_TIM9 = 3 AF4_I2C1 = 4 AF4_I2C3 = 4 AF5_SPI1 = 5 AF5_SPI2 = 5 AF7_USART1 = 7 AF7_USART2 = 7 AF8_USART6 = 8 AF9_I2C3 = 9 AF_OD = 18 AF_PP = 2 ALT = 2 ALT_OPEN_DRAIN = 18 ANALOG = 3 IN = 0 IRQ_FALLING = 270598144 IRQ_RISING = 269549568 OPEN_DRAIN = 17 OUT = 1 OUT_OD = 17 OUT_PP = 1 PULL_DOWN = 2 PULL_NONE = 0 PULL_UP = 1 def af(): pass def af_list(): pass board = None cpu = None def debug(): pass def dict(): pass def gpio(): pass def high(): pass def init(): pass def irq(): pass def low(): pass def mapper(): pass def mode(): pass def name(): pass def names(): pass def off(): pass def on(): pass def pin(): pass def port(): pass def pull(): pass def value(): pass SOFT_RESET = 0 class SPI: "" LSB = 128 MSB = 0 def deinit(): pass def init(): pass def read(): pass def readinto(): pass def write(): pass def write_readinto(): pass class Signal: "" def off(): pass def on(): pass def value(): pass class UART: "" CTS = 512 RTS = 256 def any(): pass def deinit(): pass def init(): pass def read(): pass def readchar(): pass def readinto(): pass def readline(): pass def sendbreak(): pass def write(): pass def writechar(): pass class WDT: "" def feed(): pass WDT_RESET = 3 def bootloader(): pass def deepsleep(): pass def disable_irq(): pass def enable_irq(): pass def freq(): pass def idle(): pass def info(): pass mem16 = None mem32 = None mem8 = None def reset(): pass def reset_cause(): pass def sleep(): pass def soft_reset(): pass def time_pulse_us(): pass def unique_id(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/struct.py0000644000175000017500000000020313611773167025325 0ustar annamaaannamaa00000000000000def calcsize(): pass def pack(): pass def pack_into(): pass def unpack(): pass def unpack_from(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/usocket.py0000644000175000017500000000100413611773167025456 0ustar annamaaannamaa00000000000000AF_INET = 2 AF_INET6 = 10 SOCK_DGRAM = 2 SOCK_RAW = 3 SOCK_STREAM = 1 def getaddrinfo(): pass class socket: "" def accept(): pass def bind(): pass def close(): pass def connect(): pass def listen(): pass def recv(): pass def recvfrom(): pass def send(): pass def sendto(): pass def setblocking(): pass def setsockopt(): pass def settimeout(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/micropython.py0000644000175000017500000000044513611773167026364 0ustar annamaaannamaa00000000000000def alloc_emergency_exception_buf(): pass def const(): pass def heap_lock(): pass def heap_unlock(): pass def kbd_intr(): pass def mem_info(): pass def opt_level(): pass def qstr_info(): pass def schedule(): pass def stack_use(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/uheapq.py0000644000175000017500000000011513611773167025266 0ustar annamaaannamaa00000000000000def heapify(): pass def heappop(): pass def heappush(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/uio.py0000644000175000017500000000226513611773167024607 0ustar annamaaannamaa00000000000000class BytesIO: "" def close(): pass def flush(): pass def getvalue(): pass def read(): pass def readinto(): pass def readline(): pass def seek(): pass def write(): pass class FileIO: "" def close(): pass def flush(): pass def read(): pass def readinto(): pass def readline(): pass def readlines(): pass def seek(): pass def tell(): pass def write(): pass class StringIO: "" def close(): pass def flush(): pass def getvalue(): pass def read(): pass def readinto(): pass def readline(): pass def seek(): pass def write(): pass class TextIOWrapper: "" def close(): pass def flush(): pass def read(): pass def readinto(): pass def readline(): pass def readlines(): pass def seek(): pass def tell(): pass def write(): pass def open(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/ure.py0000644000175000017500000000013013611773167024573 0ustar annamaaannamaa00000000000000DEBUG = 4096 def compile(): pass def match(): pass def search(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/socket.py0000644000175000017500000000100413611773167025271 0ustar annamaaannamaa00000000000000AF_INET = 2 AF_INET6 = 10 SOCK_DGRAM = 2 SOCK_RAW = 3 SOCK_STREAM = 1 def getaddrinfo(): pass class socket: "" def accept(): pass def bind(): pass def close(): pass def connect(): pass def listen(): pass def recv(): pass def recvfrom(): pass def send(): pass def sendto(): pass def setblocking(): pass def setsockopt(): pass def settimeout(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/sys.py0000644000175000017500000000041013611773167024617 0ustar annamaaannamaa00000000000000argv = None byteorder = "little" def exit(): pass implementation = None maxsize = 2147483647 modules = None path = None platform = "pyboard" def print_exception(): pass stderr = None stdin = None stdout = None version = "3.4.0" version_info = None thonny-3.2.7/thonny/plugins/micropython/api_stubs/math.py0000644000175000017500000000163513611773167024744 0ustar annamaaannamaa00000000000000def acos(): pass def acosh(): pass def asin(): pass def asinh(): pass def atan(): pass def atan2(): pass def atanh(): pass def ceil(): pass def copysign(): pass def cos(): pass def cosh(): pass def degrees(): pass e = 2.718282 def erf(): pass def erfc(): pass def exp(): pass def expm1(): pass def fabs(): pass def floor(): pass def fmod(): pass def frexp(): pass def gamma(): pass def isfinite(): pass def isinf(): pass def isnan(): pass def ldexp(): pass def lgamma(): pass def log(): pass def log10(): pass def log2(): pass def modf(): pass pi = 3.141593 def pow(): pass def radians(): pass def sin(): pass def sinh(): pass def sqrt(): pass def tan(): pass def tanh(): pass def trunc(): pass thonny-3.2.7/thonny/plugins/micropython/api_stubs/network.py0000644000175000017500000000002613611773167025475 0ustar annamaaannamaa00000000000000def route(): pass thonny-3.2.7/thonny/plugins/micropython/serial_connection.py0000644000175000017500000001042613611774245025514 0ustar annamaaannamaa00000000000000import serial from thonny.plugins.micropython.connection import MicroPythonConnection, ConnectionFailedException import threading import time from serial.serialutil import SerialException import logging import platform import sys from textwrap import dedent class SerialConnection(MicroPythonConnection): def __init__(self, port, baudrate, skip_reader=False): super().__init__() try: self._serial = serial.Serial(port, baudrate=baudrate, timeout=None) except SerialException as error: err_str = str(error) if "FileNotFoundError" in err_str: err_str = "port not found" message = "Unable to connect to " + port + ": " + err_str # TODO: check if these error codes also apply to Linux and Mac if error.errno == 13 and platform.system() == "Linux": # TODO: check if user already has this group message += "\n\n" + dedent( """\ Try adding yourself to the 'dialout' group: > sudo usermod -a -G dialout (NB! This needs to be followed by reboot or logging out and logging in again!)""" ) elif "PermissionError" in message: message += "\n\n" + dedent( """\ If you have serial connection to the device from another program, then disconnect it there.""" ) elif error.errno == 16: message += "\n\n" + "Try restarting the device." raise ConnectionFailedException(message) if skip_reader: self._reading_thread = None else: self._reading_thread = threading.Thread(target=self._listen_serial, daemon=True) self._reading_thread.start() def write(self, data, block_size=256, delay=0.01): # delay and block size taken from rshell # https://github.com/dhylands/rshell/blob/master/rshell/pyboard.py#L242 for i in range(0, len(data), block_size): block = data[i : i + block_size] # self._log_data(b"[" + block + b"]") size = self._serial.write(block) assert size == len(block) time.sleep(delay) return len(data) def _listen_serial(self): "NB! works in background thread" try: data = b"" while True: data += self._serial.read(1) # To avoid busy loop if len(data) == 0: self._error = "EOF" # print("LISTEN EOFFFFFFFFFF") break data += self._serial.read_all() self.num_bytes_received += len(data) # don't publish incomplete utf-8 data try: data.decode("utf-8") # testing if data decodes to_be_published = data data = b"" except UnicodeDecodeError as e: if e.start == 0: # Invalid start byte, ie. we have missed first byte(s) of the codepoint. # No use of waiting, output everything to_be_published = data data = b"" else: to_be_published = data[: e.start] data = data[e.start :] if to_be_published: self._read_queue.put(to_be_published) except Exception as e: self._error = str(e) def incoming_is_empty(self): return self._serial.in_waiting == 0 and super().incoming_is_empty() def outgoing_is_empty(self): return self._serial.out_waiting == 0 def reset_output_buffer(self): self._serial.reset_output_buffer() def close(self): if self._serial is not None: try: self._serial.cancel_read() if self._reading_thread: self._reading_thread.join() finally: try: self._serial.close() self._serial = None except Exception: logging.exception("Couldn't close serial") def debug(*args, file=sys.stderr): print(*args, file=file) thonny-3.2.7/thonny/plugins/micropython/backend.py0000644000175000017500000017373513611774245023422 0ustar annamaaannamaa00000000000000from thonny.common import ( InputSubmission, InterruptCommand, EOFCommand, parse_message, ToplevelCommand, ToplevelResponse, InlineCommand, InlineResponse, UserError, serialize_message, BackendEvent, ValueInfo, execute_system_command, ) import sys import logging import traceback import queue from thonny.plugins.micropython.connection import ( ConnectionClosedException, ConnectionFailedException, ) from textwrap import dedent import ast import re from queue import Queue, Empty import threading import os import time from thonny.misc_utils import find_volumes_by_name, sizeof_fmt import jedi import io import tokenize from thonny.running import EXPECTED_TERMINATION_CODE import binascii import shutil # See https://github.com/dhylands/rshell/blob/master/rshell/main.py # for UART_BUFFER_SIZE vs USB_BUFFER_SIZE # ampy uses 32 bytes: https://github.com/pycampers/ampy/blob/master/ampy/files.py # I'm not worrying so much, because reader thread reads continuously # and writer (SerialConnection) has it's own blocks and delays BUFFER_SIZE = 512 BAUDRATE = 115200 ENCODING = "utf-8" # Commands RAW_MODE_CMD = b"\x01" NORMAL_MODE_CMD = b"\x02" INTERRUPT_CMD = b"\x03" SOFT_REBOOT_CMD = b"\x04" # Output tokens THONNY_MSG_START = b"\x02" THONNY_MSG_END = b"\x04" EOT = b"\x04" NORMAL_PROMPT = b">>> " LF = b"\n" OK = b"OK" # first prompt when switching to raw mode (or after soft reboot in raw mode) # Looks like it's not translatable in CP # https://github.com/adafruit/circuitpython/blob/master/locale/circuitpython.pot FIRST_RAW_PROMPT = b"raw REPL; CTRL-B to exit\r\n>" FIRST_RAW_PROMPT_SUFFIX = b"\r\n>" RAW_PROMPT = b">" BLOCK_CLOSERS = re.compile( b"|".join(map(re.escape, [LF, EOT, THONNY_MSG_START, NORMAL_PROMPT, FIRST_RAW_PROMPT])) ) logger = logging.getLogger("thonny.micropython.backend") def debug(msg): return print(msg, file=sys.stderr) class MicroPythonBackend: def __init__(self, connection, clean, api_stubs_path): self._connection = connection self._local_cwd = None self._cwd = None self._interrupt_requested = False self._cancel_requested = False self._command_queue = Queue() # populated by reader thread self._progress_times = {} self._api_stubs_path = api_stubs_path self._command_reading_thread = threading.Thread(target=self._read_commands, daemon=True) self._command_reading_thread.start() self._startup_time = time.time() self._ctrl_suggestion_given = False try: self._prepare(clean) self._mainloop() except ConnectionClosedException as e: self._on_connection_closed(e) except Exception: logger.exception("Crash in backend") traceback.print_exc() def _prepare(self, clean): if clean: self._interrupt_to_raw_prompt() self._clear_environment() else: self._process_until_initial_raw_prompt() self._cwd = self._fetch_cwd() self._welcome_text = self._fetch_welcome_text() self._builtin_modules = self._fetch_builtin_modules() self._builtins_info = self._fetch_builtins_info() self._send_ready_message() def _mainloop(self): while True: try: self._cancel_requested = False self._interrupt_requested = False self._check_for_connection_errors() try: cmd = self._command_queue.get(timeout=0.1) except Empty: # No command in queue, but maybe a thread produced output meanwhile # or the user resetted the device self._forward_unexpected_output() continue if isinstance(cmd, InputSubmission): self._submit_input(cmd.data) elif isinstance(cmd, EOFCommand): self._soft_reboot(False) elif isinstance(cmd, InterruptCommand): self._interrupt() else: self.handle_command(cmd) except KeyboardInterrupt: self._interrupt() def _fetch_welcome_text(self): self._connection.write(NORMAL_MODE_CMD) welcome_text = self._connection.read_until(NORMAL_PROMPT).strip(b"\r\n >") if os.name != "nt": welcome_text = welcome_text.replace(b"\r\n", b"\n") # Go back to raw prompt self._connection.write(RAW_MODE_CMD) self._connection.read_until(FIRST_RAW_PROMPT) return welcome_text.decode(ENCODING, errors="replace") def _fetch_uname(self): res = self._evaluate("__thonny_os.uname()", prelude="import os as __thonny_os") return { "sysname": res[0], "nodename": res[1], "release": res[2], "version": res[3], "machine": res[4], } def _fetch_builtin_modules(self): out, err, _ = self._execute("help('modules')", capture_output=True) assert not err, "Error was: %r" % err modules_str_lines = out.strip().splitlines() last_line = modules_str_lines[-1].strip() if last_line.count(" ") > 0 and " " not in last_line and "\t" not in last_line: # probably something like "plus any modules on the filesystem" # (can be in different languages) modules_str_lines = modules_str_lines[:-1] modules_str = ( " ".join(modules_str_lines) .replace("/__init__", "") .replace("__main__", "") .replace("/", ".") ) return modules_str.split() def _fetch_builtins_info(self): """ for p in self._get_api_stubs_path(): builtins_file = os.path.join(p, "__builtins__.py") if os.path.exists(builtins_file): return parse_api_information(builtins_file) """ path = os.path.join(self._api_stubs_path, "builtins.py") if os.path.exists(path): return parse_api_information(path) else: return {} def _fetch_cwd(self): return self._evaluate( "__thonny_os.getcwd() if hasattr(__thonny_os, 'getcwd') else ''", prelude="import os as __thonny_os", ) def _send_ready_message(self): self.send_message(ToplevelResponse(welcome_text=self._welcome_text, cwd=self._cwd)) def _check_send_inline_progress(self, cmd, value, maximum, description=None): assert "id" in cmd prev_time = self._progress_times.get(cmd["id"], 0) if value != maximum and time.time() - prev_time < 0.2: # Don't notify too often return else: self._progress_times[cmd["id"]] = time.time() if description is None: description = cmd.get("description", "Working...") self.send_message( BackendEvent( event_type="InlineProgress", command_id=cmd["id"], value=value, maximum=maximum, description=description, ) ) def _interrupt(self): self._connection.write(INTERRUPT_CMD) def _check_for_interrupt(self, action_scope): if action_scope == "device" and self._interrupt_requested: self._interrupt() self._interrupt_requested = False if action_scope == "local" and self._cancel_requested: self._cancel_requested = False raise KeyboardInterrupt() def _interrupt_to_raw_prompt(self): # NB! Sometimes disconnecting and reconnecting (on macOS?) # too quickly causes anomalies. See CalliopeMiniProxy for more details discarded_bytes = b"" for delay in [0.05, 0.5, 0.1, 1.0, 3.0, 5.0]: # Interrupt several times, because with some drivers first interrupts seem to vanish if delay >= 1: self._show_error( "Could not enter REPL. Trying again with %d second waiting time..." % delay ) self._connection.reset_output_buffer() self._connection.write(INTERRUPT_CMD) self._connection.write(RAW_MODE_CMD) time.sleep(delay) discarded_bytes += self._connection.read_all() if discarded_bytes.endswith(FIRST_RAW_PROMPT) or discarded_bytes.endswith(b"\r\n>"): break else: max_tail_length = 500 if len(discarded_bytes) > max_tail_length: discarded_bytes_str = ( "[skipping %d bytes] ..." % (len(discarded_bytes) - max_tail_length) ) + repr(discarded_bytes[:-max_tail_length]) else: discarded_bytes_str = repr(discarded_bytes) self._show_error( "Could not enter REPL. Giving up. Read bytes:\n" + discarded_bytes_str + "\n\nYour options:\n\n" + " - check connection properties;\n" + " - make sure the device has suitable firmware;\n" + " - make sure the device is not in bootloader mode;\n" + " - reset the device and try again;\n" + " - try other serial clients (Putty, TeraTerm, screen, ...);\n" + " - ask for help in Thonny's forum or issue tracker." ) sys.exit() def _soft_reboot(self, side_command): if side_command: self._interrupt_to_raw_prompt() # Need to go to normal mode. MP doesn't run user code in raw mode # (CP does, but it doesn't hurt to do it there as well) self._connection.write(NORMAL_MODE_CMD) self._connection.read_until(NORMAL_PROMPT) self._connection.write(SOFT_REBOOT_CMD) if not side_command: self._process_until_raw_prompt() self.send_message(ToplevelResponse(cwd=self._cwd)) def _read_commands(self): "works in separate thread" while True: line = sys.stdin.readline() if line == "": logger.info("Read stdin EOF") sys.exit() cmd = parse_message(line) if isinstance(cmd, InterruptCommand): self._interrupt_requested = True self._cancel_requested = True else: self._command_queue.put(cmd) def handle_command(self, cmd): assert isinstance(cmd, (ToplevelCommand, InlineCommand)) if "local_cwd" in cmd: self._local_cwd = cmd["local_cwd"] def create_error_response(**kw): if not "error" in kw: kw["error"] = traceback.format_exc() if isinstance(cmd, ToplevelCommand): return ToplevelResponse(command_name=cmd.name, **kw) else: return InlineResponse(command_name=cmd.name, **kw) handler = getattr(self, "_cmd_" + cmd.name, None) if handler is None: response = create_error_response(error="Unknown command: " + cmd.name) else: try: response = handler(cmd) except SystemExit: # Must be caused by Thonny or plugins code if isinstance(cmd, ToplevelCommand): traceback.print_exc() response = create_error_response(SystemExit=True) except UserError as e: sys.stderr.write(str(e) + "\n") response = create_error_response() except KeyboardInterrupt: response = create_error_response(error="Interrupted", interrupted=True) except Exception: _report_internal_error() response = create_error_response(context_info="other unhandled exception") if response is None: response = {} if response is False: # Command doesn't want to send any response return elif isinstance(response, dict): if isinstance(cmd, ToplevelCommand): response = ToplevelResponse(command_name=cmd.name, **response) elif isinstance(cmd, InlineCommand): response = InlineResponse(cmd.name, **response) if "id" in cmd and "command_id" not in response: response["command_id"] = cmd["id"] debug("cmd: " + str(cmd) + ", respin: " + str(response)) self.send_message(response) def _submit_input(self, cdata: str) -> None: # TODO: what if there is a previous unused data waiting assert self._connection.outgoing_is_empty() assert cdata.endswith("\n") if not cdata.endswith("\r\n"): # submission is done with CRLF cdata = cdata[:-1] + "\r\n" bdata = cdata.encode(ENCODING) self._connection.write(bdata) # Try to consume the echo try: echo = self._connection.read(len(bdata)) except queue.Empty: # leave it. logging.warning("Timeout when reading echo") return if echo != bdata: # because of autoreload? timing problems? interruption? # Leave it. logging.warning("Unexpected echo. Expected %s, got %s" % (bdata, echo)) self._connection.unread(echo) def send_message(self, msg): if "cwd" not in msg: msg["cwd"] = self._cwd sys.stdout.write(serialize_message(msg) + "\n") sys.stdout.flush() def _send_output(self, data, stream_name): if not data: return data = self._transform_output(data) msg = BackendEvent(event_type="ProgramOutput", stream_name=stream_name, data=data) self.send_message(msg) def _transform_output(self, data): # Any keypress wouldn't work return data.replace( "Press any key to enter the REPL. Use CTRL-D to reload.", "Press Ctrl-C to enter the REPL. Use CTRL-D to reload.", ) def _ensure_raw_propmt(self): # similar to _interrupt_to_raw_prompt, but assumes we are already in a prompt self._forward_unexpected_output() self._connection.write(RAW_MODE_CMD) prompt = self._connection.read_until(FIRST_RAW_PROMPT_SUFFIX, 1, True) if not prompt.endswith(FIRST_RAW_PROMPT_SUFFIX): raise TimeoutError("Could not ensure raw prompt") def _execute(self, script, capture_output=False): self._ensure_raw_propmt() # send command self._connection.write(script.encode(ENCODING) + EOT) debug("Wrote " + script + "\n--------\n") # fetch command confirmation ok = self._connection.read(2) debug("GOTOK") assert ok == OK, "Expected OK, got %r, followed by %r" % (ok, self._connection.read_all()) return self._process_until_raw_prompt(capture_output) def _execute_without_output(self, script): out, err, value = self._execute(script, capture_output=True) if err or out: raise RuntimeError("Failed MP script: " + str(out) + "\n" + str(err)) return value def _execute_print_expr(self, expr, prelude="", cleanup="", capture_output=False): # assuming expr really contains an expression # separator is for separating side-effect output and printed value script = "" if prelude: script += prelude + "\n" script += "print(%r, repr(%s), sep='', end=%r)" % ( THONNY_MSG_START.decode(), expr, THONNY_MSG_END.decode(), ) # assuming cleanup doesn't cause output if cleanup: script += "\n" + cleanup return self._execute(script, capture_output) def _evaluate(self, expr, prelude="", cleanup=""): _, _, value_repr = self._execute_print_expr(expr, prelude, cleanup) if value_repr is None: return None else: return ast.literal_eval(value_repr) def _process_until_initial_raw_prompt(self): self._connection.write(RAW_MODE_CMD) try: self._process_until_raw_prompt() except KeyboardInterrupt: self._interrupt() def _process_until_raw_prompt(self, capture_output=False): """ Forwards output, extracts Thonny message, replaces normal prompts with raw prompts. This is executed when some code is running or just after requesting raw prompt. After submitting commands to the raw REPL, the output should be like {stdout}\x04\{stderr}\x04\n\> In the end of {stdout} there may be \x02{value-for-thonny} Interrupts will alter the execution, but from the response parsing perspective they don't matter as they look like any other exception. Things get complicated because of soft-reboots, which always end with regular prompt. Soft-reboots can occur because of Ctrl+D, machine.soft_reset() and even reset button (micro:bit). Because of soft-reboot we can't assume we'll find the terminating markers for each command. Output produced by background threads (eg. in WiPy ESP32) cause even more difficulties, because it becomes impossible to say whether we are at prompt and output is from another thread or the main thread is running. For now I'm ignoring these problems and assume all output comes from the main thread. """ # TODO: experiment with Ctrl+C, Ctrl+D, reset eot_count = 0 value = None done = False output = b"" out = b"" err = b"" while not done: if ( self._connection.num_bytes_received == 0 and not self._ctrl_suggestion_given and time.time() - self._startup_time > 1.5 ): self._show_error( "\n" + "Device is busy or does not respond. Your options:\n\n" + " - wait until it completes current work;\n" + " - use Ctrl+C to interrupt current work;\n" + " - use Stop/Restart to interrupt more and enter REPL.\n" ) self._ctrl_suggestion_given = True # There may be an input submission waiting # and we can't progress without resolving it first self._check_for_side_commands() self._check_for_interrupt("device") # Process input in chunks (max 1 parsing marker per chunk). # Prefer whole lines (to reduce the number of events), # but don't wait too long for eol. ddd = self._connection.soft_read_until(BLOCK_CLOSERS, timeout=0.05) output += ddd stream_name = "stderr" if eot_count == 1 else "stdout" if output.endswith(THONNY_MSG_START): debug("MSGSTA: " + str(output)) output = output[: -len(THONNY_MSG_START)] # Low chance of failure (eg. because of precisely timed reboot), # therefore it's safe to use big timeout temp = self._connection.soft_read_until(THONNY_MSG_END, timeout=3) if temp.endswith(THONNY_MSG_END): value = temp[: -len(THONNY_MSG_END)] debug("GOTVALUE: " + str(value)) else: # failure, restore everything to help diagnosis output = output + THONNY_MSG_START + temp elif output.endswith(EOT): debug("EOT: " + str(output)) output = output[: -len(EOT)] eot_count += 1 if eot_count == 2: # Normal completion of the command # big chance of being at the raw prompt temp = self._connection.soft_read_until(RAW_PROMPT, timeout=0.1) if temp == RAW_PROMPT and self._connection.incoming_is_empty(): done = True elif temp: # Failure, temp needs to be parsed again self._connection.unread(temp) elif output.endswith(FIRST_RAW_PROMPT) and self._connection.incoming_is_empty(): debug("FIRAPRO: " + str(output)) output = output[: -len(FIRST_RAW_PROMPT)] done = True elif ( output.endswith(NORMAL_PROMPT) and self._connection.peek_incoming() == b"\r\n" + FIRST_RAW_PROMPT ): debug("NOPRO: " + str(output)) output = output + self._connection.read_until(FIRST_RAW_PROMPT) # skip both normal and raw prompt together # (otherwise they get processed separately) output = output[: -len(NORMAL_PROMPT + b"\r\n" + FIRST_RAW_PROMPT)] done = True elif output.endswith(NORMAL_PROMPT) and self._connection.incoming_is_empty(): debug("NOPRO2: " + str(output)) output = output[: -len(NORMAL_PROMPT)] # switch to raw mode and continue self._connection.write(RAW_MODE_CMD) if output.endswith(FIRST_RAW_PROMPT[:-1]): # incomplete raw prompt, wait for more pass elif output: if capture_output: if stream_name == "stdout": out += output else: assert stream_name == "stderr" err += output else: self._send_output(output.decode(ENCODING, errors="replace"), stream_name) output = b"" debug("doneproc") return ( out.decode(ENCODING, errors="replace"), err.decode(ENCODING, errors="replace"), None if value is None else value.decode(ENCODING), ) def _clear_environment(self): # TODO: Ctrl+D in raw repl is perfect for MicroPython # but on CircuitPython it runs main.py # TODO: which is better: # self._execute_async(dedent(""" # for name in globals(): # if not name.startswith("__"): # del globals()[name] # """).strip()) # or self._execute("globals().clear(); __name__ = '__main__'") def _check_for_side_commands(self): # most likely the queue is empty if self._command_queue.empty(): return postponed = [] while not self._command_queue.empty(): cmd = self._command_queue.get() if isinstance(cmd, InputSubmission): self._submit_input(cmd.data) elif isinstance(cmd, EOFCommand): self._soft_reboot(True) else: postponed.append(cmd) # put back postponed commands while postponed: self._command_queue.put(postponed.pop(0)) def _forward_unexpected_output(self): "Invoked between commands" data = self._connection.read_all() if data.endswith(NORMAL_PROMPT): # looks like the device was resetted # hide the regular prompt from the output ... data = data[: -len(NORMAL_PROMPT)] at_prompt = True else: at_prompt = False self._send_output(data.decode(ENCODING, "replace"), "stdout") if at_prompt: # ... and recreate Thonny prompt self.send_message(ToplevelResponse()) self._check_for_connection_errors() def _supports_directories(self): # NB! make sure self._cwd is queried first return bool(self._cwd) def _connected_to_microbit(self): return "micro:bit" in self._welcome_text.lower() def _cmd_interrupt(self, cmd): self._interrupt() def _cmd_cd(self, cmd): if len(cmd.args) == 1: if not self._supports_directories(): raise UserError("This device doesn't have directories") path = cmd.args[0] self._execute("import os as __thonny_os; __thonny_os.chdir(%r)" % path) self._cwd = self._fetch_cwd() return {} else: raise UserError("%cd takes one parameter") def _cmd_Run(self, cmd): self._clear_environment() assert cmd.get("source") self._execute(cmd["source"]) return {} def _cmd_execute_source(self, cmd): try: # Try to parse as expression ast.parse(cmd.source, mode="eval") # If it didn't fail then source is an expression _, _, value_repr = self._execute_print_expr(cmd.source) if value_repr is None: value_repr = repr(None) return {"value_info": ValueInfo(0, value_repr)} except SyntaxError: # source is a statement (or invalid syntax) self._execute(cmd.source) return {} def _cmd_execute_system_command(self, cmd): # Can't use stdin, because a thread is draining it execute_system_command(cmd, cwd=self._local_cwd, disconnect_stdin=True) def _cmd_get_globals(self, cmd): if cmd.module_name == "__main__": globs = self._evaluate( "{name : repr(value) for (name, value) in globals().items() if not name.startswith('__')}" ) else: globs = self._evaluate( "{name : repr(getattr(__mod_for_globs, name)) in dir(__mod_for_globs) if not name.startswith('__')}", prelude="import %s as __mod_for_globs", ) return {"module_name": cmd.module_name, "globals": globs} def _cmd_get_dirs_child_data(self, cmd): if self._supports_directories(): data = self._get_dirs_child_data_generic(cmd["paths"]) dir_separator = "/" else: assert cmd["paths"] == {""}, "Bad command: " + repr(cmd) sizes = self._get_microbit_file_sizes() root_data = {name: {"kind": "file", "size": size} for (name, size) in sizes.items()} data = {"": root_data} dir_separator = "" return {"node_id": cmd["node_id"], "dir_separator": dir_separator, "data": data} def _cmd_get_fs_info(self, cmd): return self._get_fs_info(cmd.path) def _cmd_write_file(self, cmd): def generate_blocks(content_bytes, block_size): for i in range(0, len(content_bytes), block_size): yield content_bytes[i : i + block_size] self._write_file(generate_blocks(cmd["content_bytes"], BUFFER_SIZE), cmd["path"]) return InlineResponse( command_name="write_file", path=cmd["path"], editor_id=cmd.get("editor_id") ) def _cmd_delete(self, cmd): assert cmd.paths paths = sorted(cmd.paths, key=lambda x: len(x), reverse=True) try: self._delete_via_serial(paths) except Exception as e: if "read-only" in str(e).lower(): self._delete_via_mount(paths) self._sync_all_filesystems() def _internal_path_to_mounted_path(self, path): mount_path = self._get_fs_mount() if mount_path is None: return None flash_prefix = self._get_flash_prefix() if not path.startswith(flash_prefix): return None path_suffix = path[len(flash_prefix) :] return os.path.join(mount_path, os.path.normpath(path_suffix)) def _cmd_read_file(self, cmd): try: content_bytes = b"".join(self._read_file(cmd["path"])) error = None except Exception as e: _report_internal_error() error = str(e) content_bytes = None return {"content_bytes": content_bytes, "path": cmd["path"], "error": error} def _cmd_download(self, cmd): total_size = 0 completed_files_size = 0 remote_files = self._list_remote_files_with_info(cmd["source_paths"]) target_dir = cmd["target_dir"].rstrip("/").rstrip("\\") download_items = [] for file in remote_files: total_size += file["size"] # compute filenames (and subdirs) in target_dir # relative to the context of the user selected items assert file["path"].startswith(file["original_context"]) path_suffix = file["path"][len(file["original_context"]) :].strip("/").strip("\\") target_path = os.path.join(target_dir, os.path.normpath(path_suffix)) download_items.append(dict(source=file["path"], target=target_path, size=file["size"])) if not cmd["allow_overwrite"]: targets = [item["target"] for item in download_items] existing_files = list(filter(os.path.exists, targets)) if existing_files: return { "existing_files": existing_files, "source_paths": cmd["source_paths"], "target_dir": cmd["target_dir"], "description": cmd["description"], } def notify(current_file_progress): self._check_send_inline_progress( cmd, completed_files_size + current_file_progress, total_size ) # replace the indeterminate progressbar with determinate as soon as possible notify(0) for item in download_items: written_bytes = self._download_file(item["source"], item["target"], notify) assert written_bytes == item["size"] completed_files_size += item["size"] def _cmd_upload(self, cmd): completed_files_size = 0 local_files = self._list_local_files_with_info(cmd["source_paths"]) target_dir = cmd["target_dir"] assert target_dir.startswith("/") or not self._supports_directories() assert not target_dir.endswith("/") or target_dir == "/" upload_items = [] for file in local_files: # compute filenames (and subdirs) in target_dir # relative to the context of the user selected items assert file["path"].startswith(file["original_context"]) path_suffix = file["path"][len(file["original_context"]) :].strip("/").strip("\\") target_path = self._join_remote_path_parts(target_dir, to_remote_path(path_suffix)) upload_items.append(dict(source=file["path"], target=target_path, size=file["size"])) if not cmd["allow_overwrite"]: targets = [item["target"] for item in upload_items] existing_files = self._get_existing_remote_files(targets) if existing_files: return { "existing_files": existing_files, "source_paths": cmd["source_paths"], "target_dir": cmd["target_dir"], "description": cmd["description"], } total_size = sum([item["size"] for item in upload_items]) def notify(current_file_progress): self._check_send_inline_progress( cmd, completed_files_size + current_file_progress, total_size ) # replace the indeterminate progressbar with determinate as soon as possible notify(0) for item in upload_items: written_bytes = self._upload_file(item["source"], item["target"], notify) assert written_bytes == item["size"] completed_files_size += item["size"] def _cmd_mkdir(self, cmd): assert self._supports_directories() assert cmd.path.startswith("/") self._makedirs(cmd.path) self._sync_all_filesystems() def _cmd_editor_autocomplete(self, cmd): # template for the response result = dict(source=cmd.source, row=cmd.row, column=cmd.column) try: script = jedi.Script(cmd.source, cmd.row, cmd.column, sys_path=[self._api_stubs_path]) completions = script.completions() result["completions"] = self._filter_completions(completions) except Exception: traceback.print_exc() result["error"] = "Autocomplete error" return result def _filter_completions(self, completions): # filter out completions not applicable to MicroPython result = [] for completion in completions: if completion.name.startswith("__"): continue if completion.parent() and completion.full_name: parent_name = completion.parent().name name = completion.name root = completion.full_name.split(".")[0] # jedi proposes names from CPython builtins if root in self._builtins_info and name not in self._builtins_info[root]: continue if parent_name == "builtins" and name not in self._builtins_info: continue result.append({"name": completion.name, "complete": completion.complete}) return result def _cmd_shell_autocomplete(self, cmd): source = cmd.source # TODO: combine dynamic results and jedi results if source.strip().startswith("import ") or source.strip().startswith("from "): # this needs the power of jedi response = {"source": cmd.source} try: # at the moment I'm assuming source is the code before cursor, not whole input lines = source.split("\n") script = jedi.Script( source, len(lines), len(lines[-1]), sys_path=[self._api_stubs_path] ) completions = script.completions() response["completions"] = self._filter_completions(completions) except Exception: traceback.print_exc() response["error"] = "Autocomplete error" return response else: # use live data match = re.search( r"(\w+\.)*(\w+)?$", source ) # https://github.com/takluyver/ubit_kernel/blob/master/ubit_kernel/kernel.py if match: prefix = match.group() if "." in prefix: obj, prefix = prefix.rsplit(".", 1) names = self._evaluate( "dir({}) if '{}' in locals() or '{}' in globals() else []".format( obj, obj, obj ) ) else: names = self._evaluate("dir()") else: names = [] prefix = "" completions = [] # prevent TypeError (iterating over None) names = names if names else [] for name in names: if name.startswith(prefix) and not name.startswith("__"): completions.append({"name": name, "complete": name[len(prefix) :]}) return {"completions": completions, "source": source} def _cmd_dump_api_info(self, cmd): "For use during development of the plug-in" self._execute( dedent( """ def __get_object_atts(obj): result = [] errors = [] for name in dir(obj): try: val = getattr(obj, name) result.append((name, repr(val), repr(type(val)))) except BaseException as e: errors.append("Couldn't get attr '%s' from object '%r', Err: %r" % (name, obj, e)) return (result, errors) """ ) ) for module_name in sorted(self._fetch_builtin_modules()): if ( not module_name.startswith("_") and not module_name.startswith("adafruit") # and not module_name == "builtins" ): file_name = os.path.join( self._api_stubs_path, module_name.replace(".", "/") + ".py" ) self._dump_module_stubs(module_name, file_name) def _dump_module_stubs(self, module_name, file_name): out, err, __ = self._execute("import {0}".format(module_name), capture_output=True) if out or err: print("FAILED IMPORTING MODULE:", module_name, "\nErr: " + out + err) return os.makedirs(os.path.dirname(file_name), exist_ok=True) with io.open(file_name, "w", encoding="utf-8", newline="\n") as fp: if module_name not in [ "webrepl", "_webrepl", "gc", "http_client", "http_client_ssl", "http_server", "framebuf", "example_pub_button", "flashbdev", ]: self._dump_object_stubs(fp, module_name, "") def _dump_object_stubs(self, fp, object_expr, indent): if object_expr in [ "docs.conf", "pulseio.PWMOut", "adafruit_hid", "upysh", # "webrepl", # "gc", # "http_client", # "http_server", ]: print("SKIPPING problematic name:", object_expr) return print("DUMPING", indent, object_expr) items, errors = self._evaluate("__get_object_atts({0})".format(object_expr)) if errors: print("ERRORS", errors) for name, rep, typ in sorted(items, key=lambda x: x[0]): if name.startswith("__"): continue print("DUMPING", indent, object_expr, name) self._send_text_to_shell(" * " + name + " : " + typ, "stdout") if typ in ["", ""]: fp.write(indent + "def " + name + "():\n") fp.write(indent + " pass\n\n") elif typ in ["", "", ""]: fp.write(indent + name + " = " + rep + "\n") elif typ == "" and indent == "": # full expansion only on toplevel fp.write("\n") fp.write(indent + "class " + name + ":\n") # What about superclass? fp.write(indent + " ''\n") self._dump_object_stubs(fp, "{0}.{1}".format(object_expr, name), indent + " ") else: # keep only the name fp.write(indent + name + " = None\n") def _read_file(self, path): # TODO: read from mount when possible # file_size = self._get_file_size(path) block_size = 512 self._execute_without_output("__thonny_fp = open(%r, 'rb')" % path) if "binascii" in self._builtin_modules: self._execute_without_output("from binascii import hexlify as __temp_hexlify") while True: self._check_for_interrupt("local") if "binascii" in self._builtin_modules: block = binascii.unhexlify( self._evaluate("__temp_hexlify(__thonny_fp.read(%s))" % block_size) ) else: block = self._evaluate("__thonny_fp.read(%s)" % block_size) if block: yield block if len(block) < block_size: break self._execute_without_output( dedent( """ __thonny_fp.close() del __thonny_fp try: del __temp_hexlify except: pass """ ) ) def _write_file(self, content_blocks, target_path, notifier=None): try: result = self._write_file_via_serial(content_blocks, target_path, notifier) except ReadOnlyFilesystemError: result = self._write_file_via_mount(content_blocks, target_path, notifier) self._sync_all_filesystems() return result def _write_file_via_mount(self, content_blocks, target_path, notifier=None): mounted_target_path = self._internal_path_to_mounted_path(target_path) with open(mounted_target_path, "wb") as f: bytes_written = 0 for block in content_blocks: self._check_for_interrupt("local") bytes_written += f.write(block) f.flush() os.fsync(f) if notifier is not None: notifier(bytes_written) return bytes_written def _write_file_via_serial(self, content_blocks, target_path, notifier=None): # prelude try: _, err, _ = self._execute( dedent( """ __thonny_path = '{path}' __thonny_written = 0 __thonny_fp = open(__thonny_path, 'wb') """ ).format(path=target_path), capture_output=True, ) if "readonly" in err.replace("-", "").lower(): raise ReadOnlyFilesystemError() elif err: raise RuntimeError("Problem opening file for writing: " + err) # Define function to allow shorter write commands if "binascii" in self._builtin_modules: self._execute_without_output( dedent( """ from binascii import unhexlify as __thonny_unhex def __W(x): global __thonny_written __thonny_written += __thonny_fp.write(__thonny_unhex(x)) __thonny_fp.flush() """ ) ) else: self._execute_without_output( dedent( """ def __W(x): global __thonny_written __thonny_written += __thonny_fp.write(x) """ ) ) bytes_sent = 0 for block in content_blocks: self._check_for_interrupt("local") if "binascii" in self._builtin_modules: script = "__W(%r)" % binascii.hexlify(block) else: script = "__W(%r)" % block self._execute_without_output(script) bytes_sent += len(block) if notifier is not None: notifier(bytes_sent) bytes_received = self._evaluate("__thonny_written") if bytes_received != bytes_sent: raise UserError( "Expected %d written bytes but wrote %d" % (bytes_sent, bytes_received) ) finally: # clean up self._execute( dedent( """ try: del __W del __thonny_written del __thonny_path __thonny_fp.close() del __thonny_fp del __thonny_unhex except: pass """ ) ) return bytes_sent def _sync_all_filesystems(self): self._execute_without_output( dedent( """ try: from os import sync as __thonny_sync __thonny_sync() del __thonny_sync except ImportError: pass """ ) ) def _list_local_files_with_info(self, paths): def rec_list_with_size(path): result = {} if os.path.isfile(path): result[path] = os.path.getsize(path) elif os.path.isdir(path): for name in os.listdir(path): result.update(rec_list_with_size(os.path.join(path, name))) else: raise RuntimeError("Can't process " + path) return result result = [] for requested_path in paths: sizes = rec_list_with_size(requested_path) for path in sizes: result.append( { "path": path, "size": sizes[path], "original_context": os.path.dirname(requested_path), } ) result.sort(key=lambda rec: rec["path"]) return result def _list_remote_files_with_info(self, paths): # prepare universal functions self._execute_without_output( dedent( """ try: import os as __thonny_os from os import stat as __thonny_stat def __thonny_getsize(path): return __thonny_stat(path)[6] def __thonny_isdir(path): return __thonny_stat(path)[0] & 0o170000 == 0o040000 except ImportError: __thonny_stat = None # micro:bit from os import size as __thonny_getsize def __thonny_isdir(path): return False """ ) ) self._execute_without_output( dedent( """ def __thonny_rec_list_with_size(path): result = {} if __thonny_isdir(path): for name in __thonny_os.listdir(path): result.update(__thonny_rec_list_with_size(path + "/" + name)) else: result[path] = __thonny_getsize(path) return result """ ) ) result = [] for requested_path in paths: sizes = self._evaluate("__thonny_rec_list_with_size(%r)" % requested_path) for path in sizes: result.append( { "path": path, "size": sizes[path], "original_context": os.path.dirname(requested_path), } ) result.sort(key=lambda rec: rec["path"]) self._execute_without_output( dedent( """ del __thonny_os del __thonny_stat del __thonny_getsize del __thonny_isdir del __thonny_rec_list_with_size """ ) ) return result def _get_existing_remote_files(self, paths): if self._supports_directories(): func = "stat" else: func = "size" return self._evaluate( "__thonny_result", prelude=dedent( """ import os as __thonny_os __thonny_result = [] for __thonny_path in %r: try: __thonny_os.%s(__thonny_path) __thonny_result.append(__thonny_path) except OSError: pass """ ) % (paths, func), cleanup=dedent( """ del __thonny_os del __thonny_result del __thonny_path """ ), ) def _join_remote_path_parts(self, left, right): if left == "": # micro:bit assert not self._supports_directories() return right.strip("/") return left.rstrip("/") + "/" + right.strip("/") def _get_file_size(self, path): if self._supports_directories(): script = "__thonny_os.stat(%r)[6]" else: script = "os.stat(%r)[6]" return self._evaluate(script % path, prelude="import os as __thonny_os") def _makedirs(self, path): if path == "/": return try: self._makedirs_via_serial(path) except Exception as e: if "read-only" in str(e).lower(): self._makedirs_via_mount(path) def _makedirs_via_mount(self, path): mounted_path = self._internal_path_to_mounted_path(path) assert mounted_path is not None, "Couldn't find mounted path for " + path os.makedirs(mounted_path, exist_ok=True) def _makedirs_via_serial(self, path): if path == "/": return path = path.rstrip("/") script = ( dedent( """ import os as __thonny_os __thonny_parts = %r.split('/') for i in range(2, len(__thonny_parts) + 1): __thonny_path = "/".join(__thonny_parts[:i]) try: __thonny_os.stat(__thonny_path) except OSError: # does not exist __thonny_os.mkdir(__thonny_path) del __thonny_parts try: del __thonny_path except: pass """ ) % path ) self._execute_without_output(script) def _delete_via_mount(self, paths): for path in paths: mounted_path = self._internal_path_to_mounted_path(path) assert mounted_path is not None shutil.rmtree(mounted_path) def _delete_via_serial(self, paths): if not self._supports_directories(): self._execute_without_output( dedent( """ import os as __thonny_os for __thonny_path in %r: __thonny_os.remove(__thonny_path) del __thonny_path del __thonny_os """ ) % paths ) else: self._execute_without_output( dedent( """ import os as __thonny_os def __thonny_delete(path): if __thonny_os.stat(path)[0] & 0o170000 == 0o040000: for name in __thonny_os.listdir(path): child_path = path + "/" + name __thonny_delete(child_path) __thonny_os.rmdir(path) else: __thonny_os.remove(path) for __thonny_path in %r: __thonny_delete(__thonny_path) del __thonny_path del __thonny_delete del __thonny_os """ ) % paths ) def _upload_file(self, source, target, notifier): assert target.startswith("/") or not self._supports_directories() target_dir, _ = linux_dirname_basename(target) assert target_dir.startswith("/") or not self._supports_directories() self._makedirs(target_dir) def block_generator(): with open(source, "rb") as source_fp: while True: block = source_fp.read(512) if block: yield block else: break return self._write_file(block_generator(), target, notifier=notifier) def _download_file(self, source, target, notifier=None): os.makedirs(os.path.dirname(target), exist_ok=True) bytes_written = 0 with open(target, "wb") as out_fp: for block in self._read_file(source): out_fp.write(block) os.fsync(out_fp) bytes_written += len(block) notifier(bytes_written) return bytes_written def _get_fs_mount_label(self): # This method is most likely required with CircuitPython, # so try its approach first # https://learn.adafruit.com/welcome-to-circuitpython/the-circuitpy-drive result = self._evaluate( "__thonny_result", prelude=dedent( """ try: from storage import getmount as __thonny_getmount try: __thonny_result = __thonny_getmount("/").label finally: del __thonny_getmount except ImportError: __thonny_result = None except OSError: __thonny_result = None """ ), cleanup="del __thonny_result", ) if result is not None: return result if self._welcome_text is None: return None """ # following is not reliable and probably not needed markers_by_name = {"PYBFLASH": {"pyb"}, "CIRCUITPY": {"circuitpython"}} for name in markers_by_name: for marker in markers_by_name[name]: if marker.lower() in self._welcome_text.lower(): return name """ return None def _get_flash_prefix(self): if not self._supports_directories(): return "" elif ( "LoBo" in self._welcome_text or "WiPy with ESP32" in self._welcome_text or "PYBLITE" in self._welcome_text or "PYBv" in self._welcome_text or "PYBOARD" in self._welcome_text.upper() ): return "/flash/" else: return "/" def _get_fs_mount(self): label = self._get_fs_mount_label() if label is None: return None else: candidates = find_volumes_by_name( self._get_fs_mount_label(), # querying A can be very slow skip_letters="A", ) if len(candidates) == 0: raise RuntimeError("Could not find volume " + self._get_fs_mount_label()) elif len(candidates) > 1: raise RuntimeError("Found several possible mount points: %s" % candidates) else: return candidates[0] def _get_fs_info(self, path): result = self._evaluate( dedent( """{ "total" : __thonny_total, "used" : __thonny_used, "free": __thonny_free, "sizes": __thonny_sizes }""" ), prelude=dedent( """ try: from os import statvfs as __thonny_statvfs __thonny_stat = __thonny_statvfs(%r) __thonny_total = __thonny_stat[2] * __thonny_stat[0] __thonny_free = __thonny_stat[3] * __thonny_stat[0] __thonny_used = __thonny_total - __thonny_free __thonny_sizes = None del __thonny_statvfs del __thonny_stat except ImportError: import os as __thonny_os __thonny_sizes = [__thonny_os.size(name) for name in __thonny_os.listdir()] __thonny_used = None __thonny_total = None __thonny_free = None del __thonny_os """ ) % path, cleanup=dedent( """ del __thonny_total del __thonny_free del __thonny_used del __thonny_sizes """ ), ) if result["sizes"] is not None: if self._connected_to_microbit(): comment = "Assuming around 30 kB of storage space for user files." else: comment = "Don't know the size of storage space on this device." files_total_size = sum(result["sizes"]) # TODO: compute number of used blocks if files_total_size > 0: comment += "\n\n" + "At least %s of it is used by %d file(s)." % ( sizeof_fmt(files_total_size), len(result["sizes"]), ) result["comment"] = comment del result["sizes"] return result def _get_microbit_file_sizes(self): return self._evaluate( "{name : __thonny_os.size(name) for name in __thonny_os.listdir()}", prelude="import os as __thonny_os", cleanup="del __thonny_os", ) def _get_dirs_child_data_generic(self, paths): return self._evaluate( "__thonny_result", prelude=dedent( """ import os as __thonny_os # Init all vars, so that they can be deleted # even if the loop makes no iterations __thonny_result = {} __thonny_path = None __thonny_st = None __thonny_child_names = None __thonny_children = None __thonny_name = None __thonny_real_path = None __thonny_full = None for __thonny_path in %(paths)r: __thonny_real_path = __thonny_path or '/' try: __thonny_child_names = __thonny_os.listdir(__thonny_real_path) except OSError: # probably deleted directory __thonny_children = None else: __thonny_children = {} for __thonny_name in __thonny_child_names: if __thonny_name.startswith('.') or __thonny_name == "System Volume Information": continue __thonny_full = (__thonny_real_path + '/' + __thonny_name).replace("//", "/") try: __thonny_st = __thonny_os.stat(__thonny_full) if __thonny_st[0] & 0o170000 == 0o040000: # directory __thonny_children[__thonny_name] = {"kind" : "dir", "size" : None} else: __thonny_children[__thonny_name] = {"kind" : "file", "size" :__thonny_st[6]} # converting from 2000-01-01 epoch to Unix epoch __thonny_children[__thonny_name]["time"] = max(__thonny_st[8], __thonny_st[9]) + 946684800 except OverflowError: # Probably "System Volume Information" in trinket # https://github.com/thonny/thonny/issues/923 pass __thonny_result[__thonny_path] = __thonny_children """ ) % {"paths": paths}, cleanup=dedent( """ del __thonny_os del __thonny_st del __thonny_children del __thonny_name del __thonny_path del __thonny_full del __thonny_result del __thonny_real_path """ ), ) def _check_for_connection_errors(self): self._connection._check_for_error() def _on_connection_closed(self, error=None): message = "Connection lost" if error: message += " (" + str(error) + ")" self._send_output("\n" + message + "\n", "stderr") self._send_output("\n" + "Use Stop/Restart to reconnect." + "\n", "stderr") sys.exit(EXPECTED_TERMINATION_CODE) def _show_error(self, msg): self._send_output(msg + "\n", "stderr") class ExecutionError(Exception): pass def _report_internal_error(): print("PROBLEM WITH THONNY'S BACK-END:\n", file=sys.stderr) traceback.print_exc() def parse_api_information(file_path): with tokenize.open(file_path) as fp: source = fp.read() tree = ast.parse(source) defs = {} # TODO: read also docstrings ? for toplevel_item in tree.body: if isinstance(toplevel_item, ast.ClassDef): class_name = toplevel_item.name member_names = [] for item in toplevel_item.body: if isinstance(item, ast.FunctionDef): member_names.append(item.name) elif isinstance(item, ast.Assign): # TODO: check Python 3.4 "TODO: item.targets[0].id" defs[class_name] = member_names return defs def linux_dirname_basename(path): if path == "/": return ("/", "") if "/" not in path: # micro:bit return "", path path = path.rstrip("/") dir_, file_ = path.rsplit("/", maxsplit=1) if dir_ == "": dir_ = "/" return dir_, file_ def to_remote_path(path): return path.replace("\\", "/") class ReadOnlyFilesystemError(RuntimeError): pass if __name__ == "__main__": import argparse parser = argparse.ArgumentParser() parser.add_argument("--clean", type=lambda s: True if s == "True" else False) parser.add_argument("--port", type=str) parser.add_argument("--url", type=str) parser.add_argument("--password", type=str) parser.add_argument("--api_stubs_path", type=str) args = parser.parse_args() port = None if args.port == "None" else args.port try: if port is None: # remain busy while True: time.sleep(1000) elif port == "webrepl": from thonny.plugins.micropython.webrepl_connection import WebReplConnection connection = WebReplConnection(args.url, args.password) else: from thonny.plugins.micropython.serial_connection import SerialConnection connection = SerialConnection(port, BAUDRATE) vm = MicroPythonBackend(connection, clean=args.clean, api_stubs_path=args.api_stubs_path) except ConnectionFailedException as e: text = "\n" + str(e) + "\n" msg = BackendEvent(event_type="ProgramOutput", stream_name="stderr", data=text) sys.stdout.write(serialize_message(msg) + "\n") sys.stdout.flush() thonny-3.2.7/thonny/plugins/micropython/webrepl_connection.py0000644000175000017500000000556513611774245025705 0ustar annamaaannamaa00000000000000from thonny.plugins.micropython.connection import MicroPythonConnection from queue import Queue import threading import sys class WebReplConnection(MicroPythonConnection): def __init__(self, url, password): super().__init__() self._url = url self._password = password # Some tricks are needed to use async library in sync program # use thread-safe queues to communicate with async world in another thread self._write_queue = Queue() self._connection_result = Queue() self._ws_thread = threading.Thread(target=self._wrap_ws_main, daemon=True) self._ws_thread.start() # Wait until connection was made res = self._connection_result.get() if res != "OK": raise res def _wrap_ws_main(self): import asyncio loop = asyncio.new_event_loop() loop.set_debug(True) loop.run_until_complete(self._ws_main()) async def _ws_main(self): import asyncio try: await self._ws_connect() except Exception as e: self._connection_result.put_nowait(e) return self._connection_result.put_nowait("OK") await asyncio.gather(self._ws_keep_reading(), self._ws_keep_writing()) async def _ws_connect(self): import asyncio import websockets self._ws = await asyncio.wait_for(websockets.connect(self._url, ping_interval=None), 3) debug("GOT WS", self._ws) # read password prompt and send password read_chars = "" while read_chars != "Password: ": debug("prelude", read_chars) ch = await self._ws.recv() debug("GOT", ch) read_chars += ch debug("sending password") await self._ws.send(self._password + "\n") debug("sent password") async def _ws_keep_reading(self): while True: data = (await self._ws.recv()).encode("UTF-8") if len(data) == 0: self._error = "EOF" break self.num_bytes_received += len(data) self._read_queue.put(data, block=False) async def _ws_keep_writing(self): import asyncio while True: while not self._write_queue.empty(): data = self._write_queue.get(block=False).decode("UTF-8") debug("Wrote:", repr(data)) await self._ws.send(data) # Allow reading loop to progress await asyncio.sleep(0.01) def write(self, data, block_size=32, delay=0.01): self._write_queue.put_nowait(data) async def _async_close(self): await self._ws.close() def close(self): """ import asyncio asyncio.get_event_loop().run_until_complete(self.async_close()) """ def debug(*args, file=sys.stderr): return print(*args, file=file) thonny-3.2.7/thonny/plugins/micropython/connection.py0000644000175000017500000001001613611773167024152 0ustar annamaaannamaa00000000000000import queue from thonny.misc_utils import TimeHelper from queue import Queue import re class MicroPythonConnection: """Utility class for using Serial or WebSocket connection Uses background thread to read from the source as soon as possible to avoid loss of data (because buffer overflow or the device discarding unread data). Allows writing with delays after each n bytes. Allows unreading data. """ def __init__(self): self._read_queue = Queue() # populated by reader thread self._read_buffer = bytearray() # used for unreading and postponing bytes self.num_bytes_received = 0 self._error = None def read(self, size, timeout=1): if timeout == 0: raise TimeoutError() timer = TimeHelper(timeout) while len(self._read_buffer) < size: self._check_for_error() try: self._read_buffer.extend(self._read_queue.get(True, timer.time_left)) except queue.Empty: raise TimeoutError("Reaction timeout. Bytes read: %s" % self._read_buffer) try: data = self._read_buffer[:size] return data finally: del self._read_buffer[:size] def soft_read_until(self, terminator, timeout=1000000): return self.read_until(terminator, timeout, timeout_is_soft=True) def read_until(self, terminator, timeout=1000000, timeout_is_soft=False): timer = TimeHelper(timeout) if isinstance(terminator, str): terminator = re.compile(re.escape(terminator)) match = None while True: self._check_for_error() match = re.search(terminator, self._read_buffer) if match: break try: data = self._read_queue.get(True, timer.time_left) # print("RR", repr(data), file=sys.stderr) assert len(data) > 0 self._read_buffer.extend(data) except queue.Empty: if timeout_is_soft: break else: raise TimeoutError("Reaction timeout. Bytes read: %s" % self._read_buffer) if match: size = match.end() else: assert timeout_is_soft size = len(self._read_buffer) data = self._read_buffer[:size] del self._read_buffer[:size] return data def _fetch_to_buffer(self): while not self._read_queue.empty(): self._read_buffer.extend(self._read_queue.get(True)) def peek_incoming(self): self._fetch_to_buffer() return self._read_buffer def read_all(self): self._fetch_to_buffer() if len(self._read_buffer) == 0: self._check_for_error() try: return self._read_buffer finally: self._read_buffer = bytearray() def _check_for_error(self): if self._error is None: return raise ConnectionClosedException(self._error) def unread(self, data): self._read_buffer = data + self._read_buffer def write(self, data, block_size=32, delay=0.01): raise NotImplementedError() def _log_data(self, data): print( data.decode("Latin-1") .replace("\r\n", "\n") .replace("\x01", "①") .replace("\x02", "②") .replace("\x03", "③") .replace("\x04", "④"), end="", ) def incoming_is_empty(self): return self._read_queue.empty() and len(self._read_buffer) == 0 def outgoing_is_empty(self): return True def buffers_are_empty(self): return self.incoming_is_empty() and self.outgoing_is_empty() def reset_input_buffer(self): return self.read_all() def reset_output_buffer(self): pass def close(self): raise NotImplementedError() class ConnectionFailedException(Exception): pass class ConnectionClosedException(Exception): pass thonny-3.2.7/thonny/plugins/help/0000755000175000017500000000000013611777205020015 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/help/__init__.py0000644000175000017500000000425213611773167022134 0ustar annamaaannamaa00000000000000import os.path import tkinter as tk import tkinter.font from tkinter import ttk import thonny from thonny import get_workbench, rst_utils, tktextext, ui_utils from thonny.config import try_load_configuration from thonny.tktextext import TextFrame from thonny.ui_utils import scrollbar_style class HelpView(TextFrame): def __init__(self, master): TextFrame.__init__( self, master, text_class=rst_utils.RstText, vertical_scrollbar_style=scrollbar_style("Vertical"), horizontal_scrollbar_style=scrollbar_style("Horizontal"), horizontal_scrollbar_class=ui_utils.AutoScrollbar, borderwidth=0, wrap="word", relief="flat", padx=20, pady=0, read_only=True, ) self.language_dir = os.path.join( os.path.dirname(thonny.__file__), "locale", get_workbench().get_option("general.language"), "HELP_CONTENT", ) self.load_rst_file("index.rst") def load_topic(self, topic, fragment=None): self.load_rst_file(topic + ".rst") # TODO: scroll to fragment def load_rst_file(self, filename): self.text.clear() self.text.direct_insert("1.0", "\n") if os.path.isabs(filename): full_path = filename else: # try to access filename in a language subdirectory full_path = os.path.join(self.language_dir, filename) if not os.path.exists(full_path): # if the localized file does not exist, default to English full_path = os.path.join(os.path.dirname(__file__), filename) with open(full_path, encoding="UTF-8") as fp: rst_source = fp.read() if not filename.endswith("index.rst"): rst_source = "`" + _("Home") + " `_\n\n" + rst_source self.text.append_rst(rst_source) def open_help(): get_workbench().show_view("HelpView") def load_plugin() -> None: get_workbench().add_view(HelpView, _("Help"), "ne") get_workbench().add_command("help_contents", "help", _("Help contents"), open_help, group=30) thonny-3.2.7/thonny/plugins/help/debuggers.rst0000644000175000017500000000765513611773167022536 0ustar annamaaannamaa00000000000000Using debuggers ========================== If you want to see how Python executes your program step-by-step then you should run it in "nicer" or "faster" *debug-mode*. You can also run it with `Birdseye `_ and explore the execution steps later. "Nicer" mode ------------ This mode is recommended for total beginners. Start by selecting *Debug current script (nicer)* from the *Run* menu or by pressing Ctrl+F5 (`in XFCE you need to use Shift+Ctrl+F5 `__). You'll see that first statement of the program gets highlighted and nothing more happens. In this mode you need to notify Thonny that you're ready to let Python make the next step. For this you have two main options: * *Run → Step over* (or F6) makes big steps, ie. it executes the highlighted code and highlights the next part of the code. * *Run → Step into* (or F7) tries to make smaller steps. If the highlighted code is made of smaller parts (statements or expressions), then first of these gets highlighted and Thonny waits for next command. If you have reached to a program component which doesn't have any sub-parts (eg. variable name) then *Step into* works like *Step over*, ie. executes (or evaluates) the code. If you have stepped into the depths of a statement or expression and want to move on faster, then you can use *Run → Step out*, which executes currently highlighted code and all following program parts on the same level. There is a bit similar command called *Resume*, which will run the command without stepping till it completes (or till next breakpoint, see below). If you accidentally made a big step and stepped over an interesting piece of code, you can **take back the step** by selecting *Run → Step back*. Thonny will show the state of program as it was before the last step. Now you can continue with small steps and zoom into this piece of code. (How does it work? Even when you take a big step, Thonny saves all intermediate program states, which it can replay after you take the step back.) If you want to reach a specific part of the code, then you can speed up the process by placing your cursor on that line and selecting *Run → Run to cursor*. This makes Thonny automatically step until this line. You can take the command from there. If you have editor line numbers enabled (Tools → Options → Editor), then you can also use **breakpoints**. When you double click next to a statement in the editor left margin, a dot appears. When you now start the debugger, it doesn't stop before first statement but runs to the statement marked with the dot a.k.a breakpoint. You can place as many breakpoints to your programs as required. Breakpoints can be removed by double clicking on the dots. "Faster" mode ------------- When your programs grow bigger, you may notice that taking big steps with nicer debugger take sometimes long time. It is because the niceties (eg. possibility of stepping through expression evaluation and taking back steps) require heavy and slow machinery. With *Debug current script (faster)* you lose the niceties but you can step through your program much faster. You can use same commands (except "Step back") as with nicer debugger. This is the debugging style most professional programmers are accustomed with. Different styles for showing the call stack ------------------------------------------- By default Thonny uses stacked windows for presenting the call stack. This gives good intuition about the concept, but it may become cumbersome to use. Therefore, since version 3.0 one can choose between two different styles for presenting call stack. In “Tools → Options → Debugger” you can switch to more traditional style with a separate view for presenting and switching call frames. Note that both styles can be used with both debugging modes. Birdseye -------- Command *Debug current script (Birdseye)* is explained at a `separate page `_ thonny-3.2.7/thonny/plugins/help/debugging.rst0000644000175000017500000001177213611773167022515 0ustar annamaaannamaa00000000000000Debugging techniques ==================== If your program is not working properly then don't panic. You have several possibilities for fixing the situation. For example: * Let somebody else fix it. * Change *something* in the code and try again. * Approach the problem in two phases: 1) diagnosing the problem and 2) fixing it. Asking for help may be a very good idea, but it won't give you this sweet sense of accomplishment. Anyway, it's better not to use this without first putting in some effort on your own. If your programs are small, then you may hit the jackpot by changing something randomly and trying again (repeat many times), but you'll lose even if you win as you won't learn anything. If you want to become good in programming, then you really need to approach the problem more systematically. Among other things, this means that you need to pinpoint the reason your program misbehaves before attempting to fix it. The process of finding the source of the problem is called *debugging*. Tracing the program flow / thinking along with Python ------------------------------------------------------ Most likely your program isn't entirely wrong. There may be a typo somewhere or you overlooked or misunderstood something. *NB! Don't get into the habit of thinking that Python misunderstood you -- it is a machine that doesn't even try to understand you.* The key to debugging is finding out precisely where and when your assumptions about program behavior diverge from the actual behavior. If your program prints out wrong final answer then this tells you something about the program behavior, but it is usually not enough to locate the problem precisely. You need to also check which of the **intermediate steps** align with your assumptions and which don't. One obvious (and very useful) technique is to add **extra print statements** into the code, which tell you where Python is and what it has accomplished so far, eg. .. code:: print("friends before for-loop", friends) NB! Sometimes you need to introduce new variables and break complex expressions into smaller parts in order to print out more detailed information. Although print-debugging is used even by the professionals (they may call it *logging*), there is an alternative, which is more comfortable in most cases. It's called **stepping through the code** and it is Thonny's bread and butter. Move on to the chapter `Using debuggers `_ to learn more. Code review --------------------- Another useful technique is code review. It is somewhat similar to tracing the program flow, but you do it in your head and you are trying to see the bigger picture instead of following small steps. Look at each of the statements in your code and try understand its purpose and how it relates to your task. For each **variable** ask yourself: * Does the name of the variable reaveal its purpose? Is it better to name it in singular or in plural? * Which type of values can end up in this variable? Strings, integers, lists of strings, lists of floats, ...? * What is the role of the variable? Is it meant to updated repeatedly so that it eventually contain useful information? Is it meant to use same information in several places and reduce copy-pasting? Anything else? For each **loop** ask yourself: * How do you know the loop is required? * How many times should the body of the loop be executed? What does this depend of? * Which code should be inside the loop and which should be outside? * What must be done before loop and what must be done after it? For each complex **expression** ask yourself: * In which order should be the steps of evaluating this expression? Does Python agree with this? When in doubt, use the debugger or introduce helper variables and break the expression into smaller parts. * What type of value should come out of this expression? String? List of strings? You may be also missing some important parts in your program: * Does your task require treating different situations differently? If yes, then you probably need an if-statement. * Does the task require doing something several times? If yes, then you probably need a loop. Still losing track? ------------------------------ "Find you the place where your assumptions break" -- this is definitely easier said than done. In case of complex programs it's easy to arrive to the situation where you're not sure anymore what do you assume and why did you start with this programming thing at all. In this case it's useful to simplify your task as much as possible and try to implement the simpler problem first. Take a new editor and either start from scratch or copy existing code and throw out everything that is not essential to the problem. For example, you can assume that user is cooperative and always inputs "good" data. If the task requires doing something repeatedly, then throw out the "repeatedly" part, if the task involves a complex condition for doing something, make the condition simpler etc. After solving the simplified problem you are much better equipped to solve the original task as well. thonny-3.2.7/thonny/plugins/help/birdseye.rst0000644000175000017500000000257313611773167022367 0ustar annamaaannamaa00000000000000Birdseye ========================== Birdseye is a cool Python debugger by Alex Hall, which records the values of expressions when the program runs and lets you explore them after the program completes. See `https://birdseye.readthedocs.io `_ for more info. Birdseye is not installed by default, but it is easy to install via *Tools → Manage plug-ins*. You need to install the package named ``birdseye``. Birdseye works differently than `Thonny's built-in debuggers `_. When you execute your program with *Run → Debug current script (Birdseye)*, the execution takes a bit longer than usual, but otherwise your program should run just as if you executed it with *Run current script*. This means breakpoints are ignored and you can't step through the program. But when the program completes, Thonny opens a webpage (served by a local server provided by Birdseye), which allows you to dig into the execution process and learn how final results were composed of intermediate values. NB! When using Birdseye in Thonny you don't need to import ``birdseye.eye`` or use it for decorating your functions. Thonny executes Birdseye such that it records information about all functions. The local server uses port 7777 by default. If this is used by another application, then configure another port (Tools → Options → Debugger) and restart Thonny.thonny-3.2.7/thonny/plugins/help/flask.rst0000644000175000017500000000330713611773167021655 0ustar annamaaannamaa00000000000000Web development with Flask ========================== `Flask `__ is a popular framework for building web apps in Python. Flask tutorials usually instruct running Flask programs by entering some commands in Terminal, but this may intimidate some beginners. Thonny tries make things easeir and allows running Flask programs just like any other program (with simple F5). If it detects you are running a Flask program, then it executes it with some lines of code appended, which start the development server with suitable settings. Debugging --------- If you want to step through your Flask program, set a breakpoint inside some function and invoke the debugger (both nicer and faster work, but faster is ... faster). Reload your page and start stepping inside the function. You may want to turn off "Frames in separate windows" (Tools => Options => Run & Debug) for more comfortable operation. Details ------- Thonny will start the development server approximately like this: .. code:: os.environ["FLASK_ENV"] = "development" app.run(threaded=False, use_reloader=False, debug=False) ``threaded=False`` is used because Thonny's debugger supports only single-threaded programs, ``use_reloader=False`` is used because `automatic reloading is not reliable when Flask is started like this `_ and ``debug=False`` is used because this seems to cause less "Address already in use" errors. If you want more control over the settings then you should call the ``run``-method yourself, eg: .. code:: ... if __name__ == "__main__": app.run(port=5005, threaded=False, use_reloader=True, debug=True) In this case Thonny won't add anything to your code.thonny-3.2.7/thonny/plugins/help/plotter.rst0000644000175000017500000000420713611773167022246 0ustar annamaaannamaa00000000000000Plotter ========================== Plotter is an add-on for the Shell, which extracts numbers from the program output and displays them as line chart. It can be useful for observing live sensor data coming from attached devices or even for analyzing static data (if you don't bother using more serious tools). It is inspired by `Mu Python editor `__. You can open it from the "View" menu or from the Shell's context menu. For an examply try following program (you can stop it with Ctrl+C or with "Stop / reset" button on the toolbar): .. code:: from time import sleep from random import randint p1 = 0 while True: p1 += randint(-1, 1) p2 = randint(-10, 10) print("Random walk:", p1, " just random:", p2) sleep(0.05) When you run it with Plotter opened, you'll see a line chart with two series forming. Each column on the chart corresponds to one line in the Shell. The rightmost column on the chart always corresponds the bottom-most visible line in the shell, even if you stop the program and scroll the text in the shell. Plotter starts drawing when it detects at least two consecutive lines containing same pattern of numbers and surrounding text. The numbers get plotted and the surrounding text becomes the legend in the lower-right corner of the Plotter. Speed of the animation -------------------------------- Unless you are plotting a fixed number of lines, it is good idea not to flood the shell and plotter with data. This is why the example above makes a little pause (``sleep(0.05)``) before outputting next line. Range of the y-axis ------------------- Plotter tries to detect a suitable range for your plot without having to change it too often. For this reason it extends the range if required, but only shrinks it at the start of a new series. If some outliers have made the range too large, then you can manually shrink it by waiting until the outliers are out of the picture and clicking on the Plotter. If you want make the range larger (or just compare your data against certain values), then simply include suitable constant(s) in your data lines, eg: ``print(0, measure1, measure2, 100)``. thonny-3.2.7/thonny/plugins/help/program_arguments.rst0000644000175000017500000000202113611773167024301 0ustar annamaaannamaa00000000000000Running your programs with command line arguments ================================================= When you are editing *my_program.py* and press F5, Thonny constructs a magic command ``%Run my_program.py`` and sends it to the shell, which asks Thonny's back-end to run that script. When you go to shell and take the ``%Run`` command back (with up-arrow), you can add *command line arguments* to it. For example change the command to ``%Run my_program.py first second`` and press ENTER. When you run your program like this, you can access the arguments from ``sys.argv``: .. code:: import sys print(sys.argv) Fixing the command line arguments --------------------------------- If you need to use same set of arguments several times, it may become tedious to construct the ``%Run`` by hand. In this case check **Program arguments** in the **View menu**. This opens a small entry box next to the toolbar buttons. From now on, everything you type in this box gets appended to ``%Run thonny-3.2.7/thonny/plugins/esp/0000755000175000017500000000000013611777205017654 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/esp/__init__.py0000644000175000017500000002465313611774245022000 0ustar annamaaannamaa00000000000000from thonny.plugins.micropython import ( MicroPythonProxy, MicroPythonConfigPage, add_micropython_backend, list_serial_ports_with_descriptions, ) from thonny import get_workbench, get_runner, ui_utils import os import subprocess from thonny.ui_utils import ( SubprocessDialog, CommonDialog, CommonDialogEx, ems_to_pixels, show_dialog, ) from thonny.running import get_frontend_python, get_interpreter_for_subprocess from time import sleep import tkinter as tk from tkinter import ttk, filedialog, messagebox from collections import OrderedDict import tkinter from thonny.plugins.micropython.serial_connection import SerialConnection from thonny.misc_utils import running_on_mac_os, construct_cmd_line import time class ESPProxy(MicroPythonProxy): pass class ESP8266Proxy(ESPProxy): description = "MicroPython on ESP8266" config_page_constructor = "ESP8266" @property def known_usb_vids_pids(self): return super().known_usb_vids_pids | { # eg. Adafruit Feather Huzzah (0x10C4, 0xEA60), # Silicon Labs CP210x USB to UART Bridge, (0x1A86, 0x7523), # USB-SERIAL CH340, } def _get_api_stubs_path(self): return os.path.join(os.path.dirname(__file__), "esp8266_api_stubs") class ESP32Proxy(ESPProxy): @property def known_usb_vids_pids(self): return super().known_usb_vids_pids | { # eg. ESP-WROOM-32 (0x10C4, 0xEA60) # Silicon Labs CP210x USB to UART Bridge } def _get_api_stubs_path(self): return os.path.join(os.path.dirname(__file__), "esp32_api_stubs") class ESPConfigPage(MicroPythonConfigPage): def __init__(self, master, chip, firmware_start_address): self._chip = chip self._firmware_start_address = firmware_start_address super().__init__(master) def _get_flashing_frame(self): frame = super()._get_flashing_frame() return frame def _has_flashing_dialog(self): return True def _open_flashing_dialog(self): dlg = ESPFlashingDialog(get_workbench(), self._chip, self._firmware_start_address) ui_utils.show_dialog(dlg) @property def allow_webrepl(self): return False class ESP8266ConfigPage(ESPConfigPage): def __init__(self, master): super().__init__(master, "esp8266", "0x0") class ESP32ConfigPage(ESPConfigPage): def __init__(self, master): super().__init__(master, "esp32", "0x1000") class ESPFlashingDialog(CommonDialogEx): def __init__(self, master, chip, start_address, initial_port_desc=""): super().__init__(master) self.title("Install %s firmware with esptool" % chip.upper()) self._chip = chip self._start_address = start_address self._esptool_command = self._get_esptool_command() if not self._esptool_command: messagebox.showerror( "Can't find esptool", "esptool not found.\n" + "Install it via 'Tools => Manage plug-ins'\n" + "or using your OP-system package manager.", ) return self._close() self.main_frame.columnconfigure(2, weight=1) epadx = ems_to_pixels(2) ipadx = ems_to_pixels(0.5) epady = epadx ipady = ipadx # Port port_label = ttk.Label(self.main_frame, text="Port") port_label.grid(row=1, column=1, sticky="w", padx=(epadx, 0), pady=(epady, 0)) self._port_desc_variable = tk.StringVar(value=initial_port_desc) self._port_combo = ttk.Combobox( self.main_frame, exportselection=False, textvariable=self._port_desc_variable, values=[] ) self._port_combo.state(["!disabled", "readonly"]) self._port_combo.grid(row=1, column=2, sticky="nsew", padx=ipadx, pady=(epady, 0)) port_reload_button = ttk.Button(self.main_frame, text="Reload", command=self._reload_ports) port_reload_button.grid(row=1, column=3, sticky="ew", padx=(0, epadx), pady=(epady, 0)) # Firmware firmware_label = ttk.Label(self.main_frame, text="Firmware") firmware_label.grid(row=2, column=1, sticky="w", padx=(epadx, 0), pady=(ipady, 0)) self._firmware_entry = ttk.Entry(self.main_frame, width=65) self._firmware_entry.grid(row=2, column=2, sticky="nsew", padx=ipadx, pady=(ipady, 0)) browse_button = ttk.Button(self.main_frame, text="Browse...", command=self._browse) browse_button.grid(row=2, column=3, sticky="we", padx=(0, epadx), pady=(ipady, 0)) # Erase self._erase_variable = tk.BooleanVar(value=True) self._erase_checkbutton = ttk.Checkbutton( self.main_frame, text="Erase flash before installing", variable=self._erase_variable ) self._erase_checkbutton.grid( row=3, column=1, columnspan=3, sticky="w", padx=(epadx, 0), pady=(ipady, 0) ) # Buttons install_button = ttk.Button(self.main_frame, text="Install", command=self._install) install_button.grid(row=4, column=1, columnspan=2, sticky="e", padx=ipadx, pady=(0, epady)) cancel_button = ttk.Button(self.main_frame, text="Close", command=self._close) cancel_button.grid( row=4, column=3, columnspan=1, sticky="we", padx=(0, epadx), pady=(0, epady) ) self._reload_ports() def _get_esptool_command(self): try: import esptool return [get_interpreter_for_subprocess(), "-u", "-m", "esptool"] except ImportError: import shutil result = shutil.which("esptool") if result: return [result] else: result = shutil.which("esptool.py") if result: return [result] else: return None def _reload_ports(self): pairs = list_serial_ports_with_descriptions() self._ports_by_desc = OrderedDict(pairs) self._port_combo.configure(values=list(self._ports_by_desc.keys())) def _browse(self): path = ui_utils.askopenfilename(filetypes=[("bin-files", ".bin"), ("all files", ".*")]) if path: self._firmware_entry.delete(0, "end") self._firmware_entry.insert(0, path) def _check_connection(self, port): proxy = get_runner().get_backend_proxy() if isinstance(proxy, MicroPythonProxy): # Most likely it is using the same port proxy.disconnect() time.sleep(1.5) # Maybe another program is connected # or the user doesn't have sufficient permissions? try: conn = SerialConnection(port, 115200, skip_reader=True) conn.close() return True except Exception as e: messagebox.showerror( "Can't connect", str(e), master=None if running_on_mac_os() else self ) return False def _install(self): if not self._port_desc_variable.get(): messagebox.showerror("Select port", "Please select port") return port = self._ports_by_desc[self._port_desc_variable.get()] firmware_path = self._firmware_entry.get() if not os.path.exists(firmware_path): messagebox.showerror("Bad firmware path", "Can't find firmware, please check path") return erase_command = self._esptool_command + [ "--chip", self._chip, "--port", port, "erase_flash", ] write_command = self._esptool_command + [ "--chip", self._chip, "--port", port, "write_flash", self._start_address, firmware_path, ] if not self._check_connection(port): return # unknown problem with first dialog appearing at 0,0 # self.update_idletasks() if self.winfo_screenwidth() >= 1024: min_left = ems_to_pixels(15) min_top = ems_to_pixels(5) else: min_left = 0 min_top = 0 def long_desc(cmd): return "Command:\n%s\n\nOutput:\n" % construct_cmd_line(cmd) self.update_idletasks() if self._erase_variable.get(): proc = self._create_subprocess(erase_command) dlg = SubprocessDialog( self, proc, "Erasing flash", long_description=long_desc(erase_command), autoclose=True, ) show_dialog(dlg, master=self, min_left=min_left, min_top=min_top) if dlg.cancelled or dlg.returncode: return proc = self._create_subprocess(write_command) dlg = SubprocessDialog( self, proc, "Installing firmware", long_description=long_desc(write_command), autoclose=False, ) show_dialog(dlg, master=self, min_left=min_left, min_top=min_top) def _create_subprocess(self, cmd): return subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True ) def _close(self): self.closed = True self.destroy() def load_plugin(): add_micropython_backend("ESP8266", ESP8266Proxy, "MicroPython (ESP8266)", ESP8266ConfigPage) add_micropython_backend("ESP32", ESP32Proxy, "MicroPython (ESP32)", ESP32ConfigPage) def upload_micropython(): proxy = get_runner().get_backend_proxy() proxy.select_and_upload_micropython() def upload_micropython_enabled(): proxy = get_runner().get_backend_proxy() return getattr(proxy, "micropython_upload_enabled", False) and isinstance(proxy, ESPProxy) def erase_flash(): proxy = get_runner().get_backend_proxy() proxy.erase_flash() def erase_flash_enabled(): return ( isinstance(get_runner().get_backend_proxy(), ESPProxy) and get_runner().get_backend_proxy().micropython_upload_enabled ) get_workbench().add_command( "uploadmicropythonesp", "device", "Install MicroPython to ESP8266/ESP32 ...", upload_micropython, upload_micropython_enabled, group=40, ) get_workbench().add_command( "erasespflash", "device", "Erase ESP8266/ESP32 flash", erase_flash, tester=erase_flash_enabled, group=40, ) thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/0000755000175000017500000000000013611777205022661 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/os.py0000644000175000017500000000150513611773167023660 0ustar annamaaannamaa00000000000000class VfsFat: "" def chdir(): pass def getcwd(): pass def ilistdir(): pass def mkdir(): pass def mkfs(): pass def mount(): pass def open(): pass def remove(): pass def rename(): pass def rmdir(): pass def stat(): pass def statvfs(): pass def umount(): pass def chdir(): pass def dupterm(): pass def dupterm_notify(): pass def getcwd(): pass def ilistdir(): pass def listdir(): pass def mkdir(): pass def mount(): pass def remove(): pass def rename(): pass def rmdir(): pass def stat(): pass def statvfs(): pass def umount(): pass def uname(): pass def urandom(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/upysh.py0000644000175000017500000000001013611773167024375 0ustar annamaaannamaa00000000000000# empty thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/webrepl.py0000644000175000017500000000042413611773167024676 0ustar annamaaannamaa00000000000000_webrepl = None def accept_conn(): pass client_s = None listen_s = None network = None def setup_conn(): pass socket = None def start(): pass def start_foreground(): pass def stop(): pass uos = None websocket = None websocket_helper = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/ubinascii.py0000644000175000017500000000020613611773167025202 0ustar annamaaannamaa00000000000000def a2b_base64(): pass def b2a_base64(): pass def crc32(): pass def hexlify(): pass def unhexlify(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/uselect.py0000644000175000017500000000014013611773167024675 0ustar annamaaannamaa00000000000000POLLERR = 8 POLLHUP = 16 POLLIN = 1 POLLOUT = 4 def poll(): pass def select(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/_onewire.py0000644000175000017500000000023113611773167025041 0ustar annamaaannamaa00000000000000def crc8(): pass def readbit(): pass def readbyte(): pass def reset(): pass def writebit(): pass def writebyte(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/uctypes.py0000644000175000017500000000105313611773167024731 0ustar annamaaannamaa00000000000000ARRAY = -1073741824 BFINT16 = -671088640 BFINT32 = -402653184 BFINT8 = -939524096 BFUINT16 = -805306368 BFUINT32 = -536870912 BFUINT8 = -1073741824 BF_LEN = 22 BF_POS = 17 BIG_ENDIAN = 1 FLOAT32 = -268435456 FLOAT64 = -134217728 INT16 = 402653184 INT32 = 671088640 INT64 = 939524096 INT8 = 134217728 LITTLE_ENDIAN = 0 NATIVE = 2 PTR = 536870912 UINT16 = 268435456 UINT32 = 536870912 UINT64 = 805306368 UINT8 = 0 VOID = 0 def addressof(): pass def bytearray_at(): pass def bytes_at(): pass def sizeof(): pass class struct: "" thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/_boot.py0000644000175000017500000000004113611773167024333 0ustar annamaaannamaa00000000000000bdev = None gc = None uos = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/random.py0000644000175000017500000000026513611773167024521 0ustar annamaaannamaa00000000000000def choice(): pass def getrandbits(): pass def randint(): pass def random(): pass def randrange(): pass def seed(): pass def uniform(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/errno.py0000644000175000017500000000050413611773167024362 0ustar annamaaannamaa00000000000000EACCES = 13 EADDRINUSE = 98 EAGAIN = 11 EALREADY = 114 EBADF = 9 ECONNABORTED = 103 ECONNREFUSED = 111 ECONNRESET = 104 EEXIST = 17 EHOSTUNREACH = 113 EINPROGRESS = 115 EINVAL = 22 EIO = 5 EISDIR = 21 ENOBUFS = 105 ENODEV = 19 ENOENT = 2 ENOMEM = 12 ENOTCONN = 107 EOPNOTSUPP = 95 EPERM = 1 ETIMEDOUT = 110 errorcode = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/apa106.py0000644000175000017500000000031213611773167024222 0ustar annamaaannamaa00000000000000class APA106: "" ORDER = None def fill(): pass def write(): pass class NeoPixel: "" ORDER = None def fill(): pass def write(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/uzlib.py0000644000175000017500000000022613611773167024363 0ustar annamaaannamaa00000000000000class DecompIO: "" def read(): pass def readinto(): pass def readline(): pass def decompress(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/ustruct.py0000644000175000017500000000020313611773167024742 0ustar annamaaannamaa00000000000000def calcsize(): pass def pack(): pass def pack_into(): pass def unpack(): pass def unpack_from(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/time.py0000644000175000017500000000044313611773167024175 0ustar annamaaannamaa00000000000000def localtime(): pass def mktime(): pass def sleep(): pass def sleep_ms(): pass def sleep_us(): pass def ticks_add(): pass def ticks_cpu(): pass def ticks_diff(): pass def ticks_ms(): pass def ticks_us(): pass def time(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/uerrno.py0000644000175000017500000000050413611773167024547 0ustar annamaaannamaa00000000000000EACCES = 13 EADDRINUSE = 98 EAGAIN = 11 EALREADY = 114 EBADF = 9 ECONNABORTED = 103 ECONNREFUSED = 111 ECONNRESET = 104 EEXIST = 17 EHOSTUNREACH = 113 EINPROGRESS = 115 EINVAL = 22 EIO = 5 EISDIR = 21 ENOBUFS = 105 ENODEV = 19 ENOENT = 2 ENOMEM = 12 ENOTCONN = 107 EOPNOTSUPP = 95 EPERM = 1 ETIMEDOUT = 110 errorcode = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/esp32.py0000644000175000017500000000044313611773167024173 0ustar annamaaannamaa00000000000000class ULP: "" RESERVE_MEM = 2040 def load_binary(): pass def run(): pass def set_wakeup_period(): pass WAKEUP_ALL_LOW = None WAKEUP_ANY_HIGH = None def wake_on_ext0(): pass def wake_on_ext1(): pass def wake_on_touch(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/re.py0000644000175000017500000000013013611773167023636 0ustar annamaaannamaa00000000000000DEBUG = 4096 def compile(): pass def match(): pass def search(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/ds18x20.py0000644000175000017500000000034213611773167024346 0ustar annamaaannamaa00000000000000class DS18X20: "" def convert_temp(): pass def read_scratch(): pass def read_temp(): pass def scan(): pass def write_scratch(): pass def const(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/zlib.py0000644000175000017500000000022613611773167024176 0ustar annamaaannamaa00000000000000class DecompIO: "" def read(): pass def readinto(): pass def readline(): pass def decompress(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/hashlib.py0000644000175000017500000000025213611773167024647 0ustar annamaaannamaa00000000000000class sha1: "" def digest(): pass def update(): pass class sha256: "" def digest(): pass def update(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/websocket.py0000644000175000017500000000032713611773167025226 0ustar annamaaannamaa00000000000000class websocket: "" def close(): pass def ioctl(): pass def read(): pass def readinto(): pass def readline(): pass def write(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/urandom.py0000644000175000017500000000026513611773167024706 0ustar annamaaannamaa00000000000000def choice(): pass def getrandbits(): pass def randint(): pass def random(): pass def randrange(): pass def seed(): pass def uniform(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/utime.py0000644000175000017500000000044313611773167024362 0ustar annamaaannamaa00000000000000def localtime(): pass def mktime(): pass def sleep(): pass def sleep_ms(): pass def sleep_us(): pass def ticks_add(): pass def ticks_cpu(): pass def ticks_diff(): pass def ticks_ms(): pass def ticks_us(): pass def time(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/gc.py0000644000175000017500000000027213611773167023630 0ustar annamaaannamaa00000000000000def collect(): pass def disable(): pass def enable(): pass def isenabled(): pass def mem_alloc(): pass def mem_free(): pass def threshold(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/ujson.py0000644000175000017500000000013413611773167024372 0ustar annamaaannamaa00000000000000def dump(): pass def dumps(): pass def load(): pass def loads(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/builtins.py0000644000175000017500000001354713611773167025101 0ustar annamaaannamaa00000000000000class ArithmeticError: "" class AssertionError: "" class AttributeError: "" class BaseException: "" class EOFError: "" Ellipsis = None class Exception: "" class GeneratorExit: "" class ImportError: "" class IndentationError: "" class IndexError: "" class KeyError: "" class KeyboardInterrupt: "" class LookupError: "" class MemoryError: "" class NameError: "" NotImplemented = None class NotImplementedError: "" class OSError: "" class OverflowError: "" class RuntimeError: "" class StopAsyncIteration: "" class StopIteration: "" class SyntaxError: "" class SystemExit: "" class TypeError: "" class UnicodeError: "" class ValueError: "" class ZeroDivisionError: "" def abs(): pass def all(): pass def any(): pass def bin(): pass class bool: "" class bytearray: "" def append(): pass def extend(): pass class bytes: "" def center(): pass def count(): pass def decode(): pass def endswith(): pass def find(): pass def format(): pass def index(): pass def isalpha(): pass def isdigit(): pass def islower(): pass def isspace(): pass def isupper(): pass def join(): pass def lower(): pass def lstrip(): pass def partition(): pass def replace(): pass def rfind(): pass def rindex(): pass def rpartition(): pass def rsplit(): pass def rstrip(): pass def split(): pass def splitlines(): pass def startswith(): pass def strip(): pass def upper(): pass def callable(): pass def chr(): pass class classmethod: "" def compile(): pass class complex: "" def delattr(): pass class dict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass def dir(): pass def divmod(): pass class enumerate: "" def eval(): pass def exec(): pass def execfile(): pass class filter: "" class float: "" class frozenset: "" def copy(): pass def difference(): pass def intersection(): pass def isdisjoint(): pass def issubset(): pass def issuperset(): pass def symmetric_difference(): pass def union(): pass def getattr(): pass def globals(): pass def hasattr(): pass def hash(): pass def help(): pass def hex(): pass def id(): pass def input(): pass class int: "" def from_bytes(): pass def to_bytes(): pass def isinstance(): pass def issubclass(): pass def iter(): pass def len(): pass class list: "" def append(): pass def clear(): pass def copy(): pass def count(): pass def extend(): pass def index(): pass def insert(): pass def pop(): pass def remove(): pass def reverse(): pass def sort(): pass def locals(): pass class map: "" def max(): pass class memoryview: "" def min(): pass def next(): pass class object: "" def oct(): pass def open(): pass def ord(): pass def pow(): pass def print(): pass class property: "" def deleter(): pass def getter(): pass def setter(): pass class range: "" def repr(): pass class reversed: "" def round(): pass class set: "" def add(): pass def clear(): pass def copy(): pass def difference(): pass def difference_update(): pass def discard(): pass def intersection(): pass def intersection_update(): pass def isdisjoint(): pass def issubset(): pass def issuperset(): pass def pop(): pass def remove(): pass def symmetric_difference(): pass def symmetric_difference_update(): pass def union(): pass def update(): pass def setattr(): pass class slice: "" def sorted(): pass class staticmethod: "" class str: "" def center(): pass def count(): pass def encode(): pass def endswith(): pass def find(): pass def format(): pass def index(): pass def isalpha(): pass def isdigit(): pass def islower(): pass def isspace(): pass def isupper(): pass def join(): pass def lower(): pass def lstrip(): pass def partition(): pass def replace(): pass def rfind(): pass def rindex(): pass def rpartition(): pass def rsplit(): pass def rstrip(): pass def split(): pass def splitlines(): pass def startswith(): pass def strip(): pass def upper(): pass def sum(): pass class super: "" class tuple: "" def count(): pass def index(): pass class type: "" class zip: "" thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/ussl.py0000644000175000017500000000003413611773167024221 0ustar annamaaannamaa00000000000000def wrap_socket(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/esp.py0000644000175000017500000000061413611773167024026 0ustar annamaaannamaa00000000000000LOG_DEBUG = 4 LOG_ERROR = 1 LOG_INFO = 3 LOG_NONE = 0 LOG_VERBOSE = 5 LOG_WARNING = 2 def dht_readinto(): pass def flash_erase(): pass def flash_read(): pass def flash_size(): pass def flash_user_start(): pass def flash_write(): pass def gpio_matrix_in(): pass def gpio_matrix_out(): pass def neopixel_write(): pass def osdebug(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/select.py0000644000175000017500000000014013611773167024510 0ustar annamaaannamaa00000000000000POLLERR = 8 POLLHUP = 16 POLLIN = 1 POLLOUT = 4 def poll(): pass def select(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/_thread.py0000644000175000017500000000041413611773167024643 0ustar annamaaannamaa00000000000000class LockType: "" def acquire(): pass def locked(): pass def release(): pass def allocate_lock(): pass def exit(): pass def get_ident(): pass def stack_size(): pass def start_new_thread(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/json.py0000644000175000017500000000013413611773167024205 0ustar annamaaannamaa00000000000000def dump(): pass def dumps(): pass def load(): pass def loads(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/ntptime.py0000644000175000017500000000017413611773167024720 0ustar annamaaannamaa00000000000000NTP_DELTA = 3155673600 host = "pool.ntp.org" def settime(): pass socket = None struct = None def time(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/flashbdev.py0000644000175000017500000000032013611773167025167 0ustar annamaaannamaa00000000000000class FlashBdev: "" SEC_SIZE = 4096 START_SEC = 512 def ioctl(): pass def readblocks(): pass def writeblocks(): pass bdev = None esp = None size = 4194304 thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/dht.py0000644000175000017500000000052213611773167024014 0ustar annamaaannamaa00000000000000class DHT11: "" def humidity(): pass def measure(): pass def temperature(): pass class DHT22: "" def humidity(): pass def measure(): pass def temperature(): pass class DHTBase: "" def measure(): pass def dht_readinto(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/onewire.py0000644000175000017500000000100013611773167024675 0ustar annamaaannamaa00000000000000class OneWire: "" MATCH_ROM = 85 SEARCH_ROM = 240 SKIP_ROM = 204 def _search_rom(): pass def crc8(): pass def readbit(): pass def readbyte(): pass def readinto(): pass def reset(): pass def scan(): pass def select_rom(): pass def write(): pass def writebit(): pass def writebyte(): pass class OneWireError: "" _ow = None def const(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/uos.py0000644000175000017500000000150513611773167024045 0ustar annamaaannamaa00000000000000class VfsFat: "" def chdir(): pass def getcwd(): pass def ilistdir(): pass def mkdir(): pass def mkfs(): pass def mount(): pass def open(): pass def remove(): pass def rename(): pass def rmdir(): pass def stat(): pass def statvfs(): pass def umount(): pass def chdir(): pass def dupterm(): pass def dupterm_notify(): pass def getcwd(): pass def ilistdir(): pass def listdir(): pass def mkdir(): pass def mount(): pass def remove(): pass def rename(): pass def rmdir(): pass def stat(): pass def statvfs(): pass def umount(): pass def uname(): pass def urandom(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/heapq.py0000644000175000017500000000011513611773167024331 0ustar annamaaannamaa00000000000000def heapify(): pass def heappop(): pass def heappush(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/cmath.py0000644000175000017500000000035313611773167024333 0ustar annamaaannamaa00000000000000def cos(): pass e = 2.718282 def exp(): pass def log(): pass def log10(): pass def phase(): pass pi = 3.141593 def polar(): pass def rect(): pass def sin(): pass def sqrt(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/uhashlib.py0000644000175000017500000000025213611773167025034 0ustar annamaaannamaa00000000000000class sha1: "" def digest(): pass def update(): pass class sha256: "" def digest(): pass def update(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/btree.py0000644000175000017500000000005113611773167024333 0ustar annamaaannamaa00000000000000DESC = 2 INCL = 1 def open(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/ssl.py0000644000175000017500000000003413611773167024034 0ustar annamaaannamaa00000000000000def wrap_socket(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/machine.py0000644000175000017500000000513413611773167024645 0ustar annamaaannamaa00000000000000class ADC: "" ATTN_0DB = 0 ATTN_11DB = 3 ATTN_2_5DB = 1 ATTN_6DB = 2 WIDTH_10BIT = 1 WIDTH_11BIT = 2 WIDTH_12BIT = 3 WIDTH_9BIT = 0 def atten(): pass def read(): pass def width(): pass class DAC: "" def write(): pass DEEPSLEEP = 4 DEEPSLEEP_RESET = 4 EXT0_WAKE = 1 EXT1_WAKE = 2 HARD_RESET = 2 class I2C: "" def init(): pass def readfrom(): pass def readfrom_into(): pass def readfrom_mem(): pass def readfrom_mem_into(): pass def readinto(): pass def scan(): pass def start(): pass def stop(): pass def write(): pass def writeto(): pass def writeto_mem(): pass PIN_WAKE = 1 class PWM: "" def deinit(): pass def duty(): pass def freq(): pass def init(): pass PWRON_RESET = 1 class Pin: "" IN = 1 IRQ_FALLING = 2 IRQ_RISING = 1 OPEN_DRAIN = 7 OUT = 3 PULL_DOWN = 1 PULL_UP = 0 WAKE_HIGH = 5 WAKE_LOW = 4 def init(): pass def irq(): pass def value(): pass class RTC: "" def datetime(): pass def init(): pass def memory(): pass SLEEP = 2 SOFT_RESET = 5 class SPI: "" LSB = 1 MSB = 0 def deinit(): pass def init(): pass def read(): pass def readinto(): pass def write(): pass def write_readinto(): pass class Signal: "" def off(): pass def on(): pass def value(): pass TIMER_WAKE = 3 TOUCHPAD_WAKE = 4 class Timer: "" ONE_SHOT = 0 PERIODIC = 1 def deinit(): pass def init(): pass def value(): pass class TouchPad: "" def config(): pass def read(): pass class UART: "" def any(): pass def init(): pass def read(): pass def readinto(): pass def readline(): pass def write(): pass ULP_WAKE = 5 class WDT: "" def feed(): pass WDT_RESET = 3 def deepsleep(): pass def disable_irq(): pass def enable_irq(): pass def freq(): pass def idle(): pass mem16 = None mem32 = None mem8 = None def reset(): pass def reset_cause(): pass def sleep(): pass def time_pulse_us(): pass def unique_id(): pass def wake_reason(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/upip.py0000644000175000017500000000124613611773167024216 0ustar annamaaannamaa00000000000000class NotFoundError: "" def _makedirs(): pass def cleanup(): pass cleanup_files = None debug = None errno = None def expandhome(): pass def fatal(): pass file_buf = None gc = None def get_install_path(): pass def get_pkg_metadata(): pass gzdict_sz = 31 def help(): pass def install(): pass install_path = None def install_pkg(): pass def install_tar(): pass json = None def main(): pass def op_basename(): pass def op_split(): pass os = None def save_file(): pass sys = None tarfile = None def url_open(): pass usocket = None ussl = None uzlib = None warn_ussl = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/framebuf.py0000644000175000017500000000072213611773167025026 0ustar annamaaannamaa00000000000000class FrameBuffer: "" def blit(): pass def fill(): pass def fill_rect(): pass def hline(): pass def line(): pass def pixel(): pass def rect(): pass def scroll(): pass def text(): pass def vline(): pass def FrameBuffer1(): pass GS2_HMSB = 5 GS4_HMSB = 2 GS8 = 6 MONO_HLSB = 3 MONO_HMSB = 4 MONO_VLSB = 0 MVLSB = 0 RGB565 = 1 thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/collections.py0000644000175000017500000000075113611773167025557 0ustar annamaaannamaa00000000000000class OrderedDict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass class deque: "" def append(): pass def popleft(): pass def namedtuple(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/binascii.py0000644000175000017500000000020613611773167025015 0ustar annamaaannamaa00000000000000def a2b_base64(): pass def b2a_base64(): pass def crc32(): pass def hexlify(): pass def unhexlify(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/array.py0000644000175000017500000000012413611773167024351 0ustar annamaaannamaa00000000000000class array: "" def append(): pass def extend(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/io.py0000644000175000017500000000242213611773167023645 0ustar annamaaannamaa00000000000000class BufferedWriter: "" def flush(): pass def write(): pass class BytesIO: "" def close(): pass def flush(): pass def getvalue(): pass def read(): pass def readinto(): pass def readline(): pass def seek(): pass def write(): pass class FileIO: "" def close(): pass def flush(): pass def read(): pass def readinto(): pass def readline(): pass def readlines(): pass def seek(): pass def tell(): pass def write(): pass class StringIO: "" def close(): pass def flush(): pass def getvalue(): pass def read(): pass def readinto(): pass def readline(): pass def seek(): pass def write(): pass class TextIOWrapper: "" def close(): pass def flush(): pass def read(): pass def readinto(): pass def readline(): pass def readlines(): pass def seek(): pass def tell(): pass def write(): pass def open(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/utimeq.py0000644000175000017500000000016213611773167024541 0ustar annamaaannamaa00000000000000class utimeq: "" def peektime(): pass def pop(): pass def push(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/webrepl_setup.py0000644000175000017500000000043713611773167026122 0ustar annamaaannamaa00000000000000CONFIG = "./webrepl_cfg.py" RC = "./boot.py" def change_daemon(): pass def exists(): pass def get_daemon_status(): pass def getpass(): pass def input_choice(): pass def input_pass(): pass machine = None def main(): pass os = None sys = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/ucollections.py0000644000175000017500000000075113611773167025744 0ustar annamaaannamaa00000000000000class OrderedDict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass class deque: "" def append(): pass def popleft(): pass def namedtuple(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/upip_utarfile.py0000644000175000017500000000051513611773167026107 0ustar annamaaannamaa00000000000000DIRTYPE = "dir" class FileSection: "" def read(): pass def readinto(): pass def skip(): pass REGTYPE = "file" TAR_HEADER = None class TarFile: "" def extractfile(): pass def next(): pass class TarInfo: "" def roundup(): pass uctypes = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/struct.py0000644000175000017500000000020313611773167024555 0ustar annamaaannamaa00000000000000def calcsize(): pass def pack(): pass def pack_into(): pass def unpack(): pass def unpack_from(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/_webrepl.py0000644000175000017500000000026013611773167025033 0ustar annamaaannamaa00000000000000class _webrepl: "" def close(): pass def read(): pass def readinto(): pass def write(): pass def password(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/usocket.py0000644000175000017500000000034613611773167024716 0ustar annamaaannamaa00000000000000AF_INET = 2 AF_INET6 = 10 IPPROTO_IP = 0 IPPROTO_TCP = 6 IPPROTO_UDP = 17 IP_ADD_MEMBERSHIP = 3 SOCK_DGRAM = 2 SOCK_RAW = 3 SOCK_STREAM = 1 SOL_SOCKET = 4095 SO_REUSEADDR = 4 def getaddrinfo(): pass def socket(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/micropython.py0000644000175000017500000000044513611773167025614 0ustar annamaaannamaa00000000000000def alloc_emergency_exception_buf(): pass def const(): pass def heap_lock(): pass def heap_unlock(): pass def kbd_intr(): pass def mem_info(): pass def opt_level(): pass def qstr_info(): pass def schedule(): pass def stack_use(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/urequests.py0000644000175000017500000000045713611773167025304 0ustar annamaaannamaa00000000000000class Response: "" def close(): pass content = None def json(): pass text = None def delete(): pass def get(): pass def head(): pass def patch(): pass def post(): pass def put(): pass def request(): pass usocket = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/uheapq.py0000644000175000017500000000011513611773167024516 0ustar annamaaannamaa00000000000000def heapify(): pass def heappop(): pass def heappush(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/uio.py0000644000175000017500000000242213611773167024032 0ustar annamaaannamaa00000000000000class BufferedWriter: "" def flush(): pass def write(): pass class BytesIO: "" def close(): pass def flush(): pass def getvalue(): pass def read(): pass def readinto(): pass def readline(): pass def seek(): pass def write(): pass class FileIO: "" def close(): pass def flush(): pass def read(): pass def readinto(): pass def readline(): pass def readlines(): pass def seek(): pass def tell(): pass def write(): pass class StringIO: "" def close(): pass def flush(): pass def getvalue(): pass def read(): pass def readinto(): pass def readline(): pass def seek(): pass def write(): pass class TextIOWrapper: "" def close(): pass def flush(): pass def read(): pass def readinto(): pass def readline(): pass def readlines(): pass def seek(): pass def tell(): pass def write(): pass def open(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/websocket_helper.py0000644000175000017500000000017613611773167026567 0ustar annamaaannamaa00000000000000DEBUG = 0 binascii = None def client_handshake(): pass hashlib = None def server_handshake(): pass sys = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/ure.py0000644000175000017500000000013013611773167024023 0ustar annamaaannamaa00000000000000DEBUG = 4096 def compile(): pass def match(): pass def search(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/socket.py0000644000175000017500000000034613611773167024531 0ustar annamaaannamaa00000000000000AF_INET = 2 AF_INET6 = 10 IPPROTO_IP = 0 IPPROTO_TCP = 6 IPPROTO_UDP = 17 IP_ADD_MEMBERSHIP = 3 SOCK_DGRAM = 2 SOCK_RAW = 3 SOCK_STREAM = 1 SOL_SOCKET = 4095 SO_REUSEADDR = 4 def getaddrinfo(): pass def socket(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/inisetup.py0000644000175000017500000000016013611773167025073 0ustar annamaaannamaa00000000000000bdev = None def check_bootsec(): pass def fs_corrupted(): pass def setup(): pass uos = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/neopixel.py0000644000175000017500000000020613611773167025057 0ustar annamaaannamaa00000000000000class NeoPixel: "" ORDER = None def fill(): pass def write(): pass def neopixel_write(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/sys.py0000644000175000017500000000040613611773167024054 0ustar annamaaannamaa00000000000000argv = None byteorder = "little" def exit(): pass implementation = None maxsize = 2147483647 modules = None path = None platform = "esp32" def print_exception(): pass stderr = None stdin = None stdout = None version = "3.4.0" version_info = None thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/math.py0000644000175000017500000000163513611773167024174 0ustar annamaaannamaa00000000000000def acos(): pass def acosh(): pass def asin(): pass def asinh(): pass def atan(): pass def atan2(): pass def atanh(): pass def ceil(): pass def copysign(): pass def cos(): pass def cosh(): pass def degrees(): pass e = 2.718282 def erf(): pass def erfc(): pass def exp(): pass def expm1(): pass def fabs(): pass def floor(): pass def fmod(): pass def frexp(): pass def gamma(): pass def isfinite(): pass def isinf(): pass def isnan(): pass def ldexp(): pass def lgamma(): pass def log(): pass def log10(): pass def log2(): pass def modf(): pass pi = 3.141593 def pow(): pass def radians(): pass def sin(): pass def sinh(): pass def sqrt(): pass def tan(): pass def tanh(): pass def trunc(): pass thonny-3.2.7/thonny/plugins/esp/esp32_api_stubs/network.py0000644000175000017500000000040613611773167024727 0ustar annamaaannamaa00000000000000AP_IF = 1 AUTH_MAX = 6 AUTH_OPEN = 0 AUTH_WEP = 1 AUTH_WPA2_PSK = 3 AUTH_WPA_PSK = 2 AUTH_WPA_WPA2_PSK = 4 def LAN(): pass MODE_11B = 1 MODE_11G = 2 MODE_11N = 4 PHY_LAN8720 = 0 PHY_TLK110 = 1 STA_IF = 0 def WLAN(): pass def phy_mode(): pass thonny-3.2.7/thonny/plugins/backend/0000755000175000017500000000000013611777205020454 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/backend/__init__.py0000644000175000017500000000002113611773167022561 0ustar annamaaannamaa00000000000000# Package marker thonny-3.2.7/thonny/plugins/backend/dock_user_windows_backend.py0000644000175000017500000000404413611773167026232 0ustar annamaaannamaa00000000000000import os from thonny.backend import get_vm from thonny.common import BackendEvent _last_pos = (None, None) _notification_is_sent = False _LAST_POS_SETTING = "dock_user_windows.last_position" def on_configure(event): global _last_pos, _notification_is_sent pos = event.x, event.y if pos != _last_pos: get_vm().set_option(_LAST_POS_SETTING, pos) if not _notification_is_sent: get_vm().send_message(BackendEvent("UserWindowAppeared")) _notification_is_sent = True def patch_tkinter(module): flag_name = "has_docking_patch" if getattr(module, flag_name, False): return original_constructor = module.Tk.__init__ def patched_Tk_constructor(self, *args, **kw): original_constructor(self, *args, **kw) try: # move window to the same place it was previously last_pos = get_vm().get_option(_LAST_POS_SETTING) if isinstance(last_pos, tuple): self.geometry("+%d+%d" % last_pos) self.wm_attributes("-topmost", 1) # self.overrideredirect(1) # I'm using bind_class because turtle._Screen later overwrites the bind handler self.bind_class("Tk", "", on_configure, True) except Exception: # expected to fail when constructing Tcl for _cmd_process_gui_events pass module.Tk.__init__ = patched_Tk_constructor setattr(module, flag_name, True) def patch_turtle(module): # Turtle needs more tweaking because it later overrides the position set in the Tk constructor turtle_config = getattr(module, "_CFG", None) if isinstance(turtle_config, dict): last_pos = get_vm().get_option(_LAST_POS_SETTING) if isinstance(last_pos, tuple): turtle_config["leftright"], turtle_config["topbottom"] = last_pos def load_plugin(): if os.environ.get("DOCK_USER_WINDOWS", "False").lower() == "true": vm = get_vm() vm.add_import_handler("tkinter", patch_tkinter) vm.add_import_handler("turtle", patch_turtle) thonny-3.2.7/thonny/plugins/backend/matplotlib_backend.py0000644000175000017500000000210213611773167024642 0ustar annamaaannamaa00000000000000from thonny.backend import get_vm import os.path import platform local_conf_file = "matplotlibrc" user_conf_file1 = os.path.expanduser("~/.config/matplotlib/matplotlibrc") user_conf_file2 = os.path.expanduser("~/.matplotlib/matplotlibrc") done = False def set_default_backend(matplotlib): global done # Tried with overwriting settings only when MacOSX backend is selected # but querying this failed because of strange import behavior if ( done or "MPLBACKEND" in os.environ or os.path.exists(local_conf_file) or os.path.exists(user_conf_file1) or os.path.exists(user_conf_file2) ): # done or the user knows what (s)he's doing pass else: try: import tkinter # @UnusedImport os.environ["MPLBACKEND"] = "TkAgg" except ImportError: pass done = True def load_plugin(): if platform.system() == "Darwin": # https://github.com/thonny/thonny/issues/676 vm = get_vm() vm.add_import_handler("matplotlib", set_default_backend) thonny-3.2.7/thonny/plugins/backend/flask_backend.py0000644000175000017500000000330713611773167023603 0ustar annamaaannamaa00000000000000import ast from thonny.backend import get_vm def augment_source(source, cmd): if "Flask" not in source: # don't bother analyzing further return source try: tree = ast.parse(source) except SyntaxError: return source var_name = None found_run = False for node in ast.walk(tree): if ( isinstance(node, ast.Assign) and isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) # TODO: could be also flask.Flask and node.value.func.id == "Flask" and len(node.targets) == 1 and isinstance(node.targets[0], ast.Name) ): var_name = node.targets[0].id elif ( isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute) and isinstance(node.func.value, ast.Name) and node.func.value.id == var_name and node.func.attr == "run" ): found_run = True if not var_name or found_run: return source else: return ( source + """ if "{app_name}" in globals(): import os as __temp_os__ if "FLASK_ENV" not in __temp_os__.environ: __temp_os__.environ["FLASK_ENV"] = "development" del __temp_os__ # Conservative options for minimum technical risks. # Users who need more control should call run explicitly. print(" # Running the app with options chosen by Thonny. See Help for details.") {app_name}.run(threaded=False, debug=False, use_reloader=False) """.format( app_name=var_name ) ) def load_plugin(): get_vm().add_source_preprocessor(augment_source) thonny-3.2.7/thonny/plugins/backend/birdseye_backend.py0000644000175000017500000000235513611773167024313 0ustar annamaaannamaa00000000000000import os from thonny.backend import get_vm, Executor, prepare_hooks, return_execution_result import webbrowser def _cmd_Birdseye(cmd): vm = get_vm() vm.switch_env_to_script_mode(cmd) return vm._execute_file(cmd, BirdsEyeRunner) class BirdsEyeRunner(Executor): @return_execution_result @prepare_hooks def execute_source(self, source, filename, mode, ast_postprocessors): assert mode == "exec" # ignore ast_postprocessors, because birdseye requires source if isinstance(source, bytes): source = source.decode("utf-8") import __main__ # @UnresolvedImport global_vars = __main__.__dict__ # Following is a trick, which allows importing birdseye in the backends, # which doesn't have it installed (provided it is installed for frontend Python) self._vm.load_modules_with_frontend_path(["birdseye.bird"]) from birdseye.bird import eye eye.exec_string(source, filename, globs=global_vars, locs=global_vars, deep=True) port = os.environ.get("BIRDSEYE_PORT", "7777") webbrowser.open_new_tab("http://localhost:%s/ipython_call/" % port + eye._last_call_id) def load_plugin(): get_vm().add_command("Birdseye", _cmd_Birdseye) thonny-3.2.7/thonny/plugins/backend/pgzero_backend.py0000644000175000017500000000503013611773167024004 0ustar annamaaannamaa00000000000000import os import ast import sys from thonny.backend import VM, get_vm def augment_ast(root): mode = os.environ.get("PGZERO_MODE", "False") assert mode != "False" warning_prelude = "WARNING: Pygame Zero mode is turned on (Run → Pygame Zero mode)" try: import pgzero # @UnusedImport except ImportError: if mode == "True": print( warning_prelude + ",\nbut pgzero module is not found. Running program in regular mode.\n", file=sys.stderr, ) else: assert mode == "auto" return # Check if draw is defined for stmt in root.body: if isinstance(stmt, ast.FunctionDef) and stmt.name == "draw": break else: if mode == "auto": return else: print( warning_prelude + ",\nbut your program doesn't look like usual Pygame Zero program\n" + "(draw function is missing).\n", file=sys.stderr, ) # need more checks in auto mode if mode == "auto": # check that draw method is not called in the code for node in ast.walk(root): if ( isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == "draw" ): return # prepend "import pgzrun as __pgzrun" imp = ast.Import([ast.alias("pgzrun", "__pgzrun")]) imp.lineno = 0 imp.col_offset = 0 ast.fix_missing_locations(imp) imp.tags = {"ignore"} root.body.insert(0, imp) # append "__pgzrun.go()" go = ast.Expr( ast.Call(ast.Attribute(ast.Name("__pgzrun", ast.Load()), "go", ast.Load()), [], []) ) go.lineno = 1000000 go.col_offset = 0 ast.fix_missing_locations(go) go.tags = {"ignore"} root.body.append(go) def patched_editor_autocomplete(self, cmd): # Make extra builtins visible for Jedi prefix = "from pgzero.builtins import *\n" cmd["source"] = prefix + cmd["source"] cmd["row"] = cmd["row"] + 1 result = get_vm()._original_editor_autocomplete(cmd) result["row"] = result["row"] - 1 result["source"] = result["source"][len(prefix) :] return result def load_plugin(): if os.environ.get("PGZERO_MODE", "False").lower() == "false": return get_vm().add_ast_postprocessor(augment_ast) VM._original_editor_autocomplete = VM._cmd_editor_autocomplete VM._cmd_editor_autocomplete = patched_editor_autocomplete thonny-3.2.7/thonny/plugins/pip_gui.py0000644000175000017500000013075513611773167021111 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import json import logging import os import re import subprocess import sys import tkinter as tk import urllib.error import urllib.parse import webbrowser from concurrent.futures.thread import ThreadPoolExecutor from distutils.version import LooseVersion, StrictVersion from logging import exception from os import makedirs from tkinter import messagebox, ttk from tkinter.messagebox import showerror from urllib.request import urlopen, urlretrieve import thonny from thonny import get_runner, get_workbench, running, tktextext, ui_utils from thonny.common import InlineCommand, normpath_with_actual_case, is_same_path, path_startswith from thonny.ui_utils import ( AutoScrollbar, SubprocessDialog, askopenfilename, get_busy_cursor, lookup_style_option, open_path_in_system_file_manager, scrollbar_style, CommonDialog, ) from thonny.running import get_interpreter_for_subprocess PIP_INSTALLER_URL = "https://bootstrap.pypa.io/get-pip.py" class PipDialog(CommonDialog): def __init__(self, master): self._state = "idle" # possible values: "listing", "fetching", "idle" self._process = None self._active_distributions = {} self.current_package_data = None super().__init__(master) main_frame = ttk.Frame(self) main_frame.grid(sticky=tk.NSEW, ipadx=15, ipady=15) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.title(self._get_title()) self._create_widgets(main_frame) self.search_box.focus_set() self.bind("", self._on_close, True) self.protocol("WM_DELETE_WINDOW", self._on_close) self._show_instructions() self._start_update_list() def _create_widgets(self, parent): header_frame = ttk.Frame(parent) header_frame.grid(row=1, column=0, sticky="nsew", padx=15, pady=(15, 0)) header_frame.columnconfigure(0, weight=1) header_frame.rowconfigure(1, weight=1) name_font = tk.font.nametofont("TkDefaultFont").copy() name_font.configure(size=16) self.search_box = ttk.Entry(header_frame) self.search_box.grid(row=1, column=0, sticky="nsew") self.search_box.bind("", self._on_search, False) self.search_button = ttk.Button( header_frame, text=_("Find package from PyPI"), command=self._on_search, width=25 ) self.search_button.grid(row=1, column=1, sticky="nse", padx=(10, 0)) main_pw = tk.PanedWindow( parent, orient=tk.HORIZONTAL, background=lookup_style_option("TPanedWindow", "background"), sashwidth=15, ) main_pw.grid(row=2, column=0, sticky="nsew", padx=15, pady=15) parent.rowconfigure(2, weight=1) parent.columnconfigure(0, weight=1) listframe = ttk.Frame(main_pw, relief="flat", borderwidth=1) listframe.rowconfigure(0, weight=1) listframe.columnconfigure(0, weight=1) self.listbox = ui_utils.ThemedListbox( listframe, activestyle="dotbox", width=20, height=20, selectborderwidth=0, relief="flat", # highlightthickness=4, # highlightbackground="red", # highlightcolor="green", borderwidth=0, ) self.listbox.insert("end", " <" + _("INSTALL") + ">") self.listbox.bind("<>", self._on_listbox_select, True) self.listbox.grid(row=0, column=0, sticky="nsew") list_scrollbar = AutoScrollbar( listframe, orient=tk.VERTICAL, style=scrollbar_style("Vertical") ) list_scrollbar.grid(row=0, column=1, sticky="ns") list_scrollbar["command"] = self.listbox.yview self.listbox["yscrollcommand"] = list_scrollbar.set info_frame = ttk.Frame(main_pw) info_frame.columnconfigure(0, weight=1) info_frame.rowconfigure(1, weight=1) main_pw.add(listframe) main_pw.add(info_frame) self.name_label = ttk.Label(info_frame, text="", font=name_font) self.name_label.grid(row=0, column=0, sticky="w", padx=5) info_text_frame = tktextext.TextFrame( info_frame, read_only=True, horizontal_scrollbar=False, background=lookup_style_option("TFrame", "background"), vertical_scrollbar_class=AutoScrollbar, vertical_scrollbar_style=scrollbar_style("Vertical"), horizontal_scrollbar_style=scrollbar_style("Horizontal"), width=70, height=10, ) info_text_frame.configure(borderwidth=0) info_text_frame.grid(row=1, column=0, columnspan=4, sticky="nsew", pady=(0, 10)) self.info_text = info_text_frame.text link_color = lookup_style_option("Url.TLabel", "foreground", "red") self.info_text.tag_configure("url", foreground=link_color, underline=True) self.info_text.tag_bind("url", "", self._handle_url_click) self.info_text.tag_bind("url", "", lambda e: self.info_text.config(cursor="hand2")) self.info_text.tag_bind("url", "", lambda e: self.info_text.config(cursor="")) self.info_text.tag_configure("install_reqs", foreground=link_color, underline=True) self.info_text.tag_bind( "install_reqs", "", self._handle_install_requirements_click ) self.info_text.tag_bind( "install_reqs", "", lambda e: self.info_text.config(cursor="hand2") ) self.info_text.tag_bind( "install_reqs", "", lambda e: self.info_text.config(cursor="") ) self.info_text.tag_configure("install_file", foreground=link_color, underline=True) self.info_text.tag_bind( "install_file", "", self._handle_install_file_click ) self.info_text.tag_bind( "install_file", "", lambda e: self.info_text.config(cursor="hand2") ) self.info_text.tag_bind( "install_file", "", lambda e: self.info_text.config(cursor="") ) default_font = tk.font.nametofont("TkDefaultFont") self.info_text.configure(font=default_font, wrap="word") bold_font = default_font.copy() # need to explicitly copy size, because Tk 8.6 on certain Ubuntus use bigger font in copies bold_font.configure(weight="bold", size=default_font.cget("size")) self.info_text.tag_configure("caption", font=bold_font) self.info_text.tag_configure("bold", font=bold_font) self.command_frame = ttk.Frame(info_frame) self.command_frame.grid(row=2, column=0, sticky="w") self.install_button = ttk.Button( self.command_frame, text=" " + _("Upgrade") + " ", command=self._on_click_install ) self.install_button.grid(row=0, column=0, sticky="w", padx=0) self.uninstall_button = ttk.Button( self.command_frame, text=_("Uninstall"), command=lambda: self._perform_action("uninstall"), width=len(_("Uninstall")), ) self.uninstall_button.grid(row=0, column=1, sticky="w", padx=(5, 0)) self.advanced_button = ttk.Button( self.command_frame, text="...", width=3, command=lambda: self._perform_action("advanced"), ) self.advanced_button.grid(row=0, column=2, sticky="w", padx=(5, 0)) self.close_button = ttk.Button(info_frame, text=_("Close"), command=self._on_close) self.close_button.grid(row=2, column=3, sticky="e") def _on_click_install(self): self._perform_action("install") def _set_state(self, state, force_normal_cursor=False): self._state = state widgets = [ self.listbox, # self.search_box, # looks funny when disabled self.search_button, self.install_button, self.advanced_button, self.uninstall_button, ] if state == "idle": self.config(cursor="") for widget in widgets: widget["state"] = tk.NORMAL else: if force_normal_cursor: self.config(cursor="") else: self.config(cursor=get_busy_cursor()) for widget in widgets: widget["state"] = tk.DISABLED def _get_state(self): return self._state def _handle_outdated_or_missing_pip(self, error): raise NotImplementedError() def _install_pip(self): self._clear() self.info_text.direct_insert("end", ("Installing pip") + "\n\n", ("caption",)) self.info_text.direct_insert( "end", ( "pip, a required module for managing packages is missing or too old.\n\n" + "Downloading pip installer (about 1.5 MB), please wait ..." ) + "\n", ) self.update() self.update_idletasks() installer_filename, _ = urlretrieve(PIP_INSTALLER_URL) self.info_text.direct_insert("end", ("Installing pip, please wait ...") + "\n") self.update() self.update_idletasks() proc, _ = self._create_python_process([installer_filename], stderr=subprocess.PIPE) out, err = proc.communicate() os.remove(installer_filename) if err != "": raise RuntimeError("Error while installing pip:\n" + err) self.info_text.direct_insert("end", out + "\n") self.update() self.update_idletasks() # update list self._start_update_list() def _provide_pip_install_instructions(self, error): self._clear() self.info_text.direct_insert("end", error) self.info_text.direct_insert( "end", ("You seem to have problems with pip" + "\n\n"), ("caption",) ) self.info_text.direct_insert( "end", ( "pip, a required module for managing packages is missing or too old for Thonny.\n\n" + "If your system package manager doesn't provide recent pip (9.0.0 or later), " + "then you can install newest version by downloading" ) + " ", ) self.info_text.direct_insert("end", PIP_INSTALLER_URL, ("url",)) self.info_text.direct_insert( "end", " " + ("and running it with") + " " + self._get_interpreter() + " " + ("(probably needs admin privileges).") + "\n\n", ) self.info_text.direct_insert("end", self._instructions_for_command_line_install()) self._set_state("disabled", True) def _instructions_for_command_line_install(self): return ( "Alternatively, if you have an older pip installed, then you can install packages " + "on the command line (Tools → Open system shell...)" ) def _start_update_list(self, name_to_show=None): raise NotImplementedError() def _update_list(self, name_to_show): self.listbox.delete(1, "end") for name in sorted(self._active_distributions.keys()): self.listbox.insert("end", " " + name) if name_to_show is None: self._show_instructions() else: self._start_show_package_info(name_to_show) def _on_listbox_select(self, event): self.listbox.focus_set() selection = self.listbox.curselection() if len(selection) == 1: self.listbox.activate(selection[0]) if selection[0] == 0: # special first item self._show_instructions() else: self._start_show_package_info(self.listbox.get(selection[0]).strip()) def _on_search(self, event=None): if self._get_state() != "idle": # Search box is not made inactive for busy-states return if self.search_box.get().strip() == "": return self._start_show_package_info(self.search_box.get().strip()) def _clear(self): self.current_package_data = None self.name_label.grid_remove() self.command_frame.grid_remove() self.info_text.direct_delete("1.0", "end") def _show_instructions(self): self._clear() if self._read_only(): self.info_text.direct_insert("end", _("Browse the packages") + "\n", ("caption",)) self.info_text.direct_insert( "end", _( "With current interpreter you can only browse the packages here.\n" + "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." ) + "\n\n", ) if self._get_target_directory(): self.info_text.direct_insert("end", _("Packages' directory") + "\n", ("caption",)) self.info_text.direct_insert( "end", self._get_target_directory(), ("target_directory") ) else: self.info_text.direct_insert("end", _("Install from PyPI") + "\n", ("caption",)) self.info_text.direct_insert( "end", _( "If you don't know where to get the package from, " + "then most likely you'll want to search the Python Package Index. " + "Start by entering the name of the package in the search box above and pressing ENTER." ) + "\n\n", ) self.info_text.direct_insert( "end", _("Install from requirements file") + "\n", ("caption",) ) self.info_text.direct_insert("end", _("Click" + " ")) self.info_text.direct_insert("end", _("here"), ("install_reqs",)) self.info_text.direct_insert( "end", " " + _("to locate requirements.txt file and install the packages specified in it.") + "\n\n", ) self.info_text.direct_insert("end", _("Install from local file") + "\n", ("caption",)) self.info_text.direct_insert("end", _("Click") + " ") self.info_text.direct_insert("end", _("here"), ("install_file",)) self.info_text.direct_insert( "end", " " + _( "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." ) + "\n\n", ) self.info_text.direct_insert("end", _("Upgrade or uninstall") + "\n", ("caption",)) self.info_text.direct_insert( "end", _("Start by selecting the package from the left.") + "\n\n" ) if self._get_target_directory(): self.info_text.direct_insert("end", _("Target:") + " ", ("caption",)) if self._should_install_to_site_packages(): self.info_text.direct_insert( "end", _("virtual environment") + "\n", ("caption",) ) else: self.info_text.direct_insert( "end", _("user site packages") + "\n", ("caption",) ) self.info_text.direct_insert( "end", _( "This dialog lists all available packages," + " but allows upgrading and uninstalling only packages from" ) + " ", ) self.info_text.direct_insert("end", self._get_target_directory(), ("url")) self.info_text.direct_insert( "end", ". " + _( "New packages will be also installed into this directory." + " Other locations must be managed by alternative means." ), ) self._select_list_item(0) def _start_show_package_info(self, name): self.current_package_data = None # Fetch info from PyPI self._set_state("fetching") # Follwing fetches info about latest version. # This is OK even when we're looking an installed older version # because new version may have more relevant and complete info. _start_fetching_package_info(name, None, self._show_package_info) self.info_text.direct_delete("1.0", "end") self.name_label["text"] = "" self.name_label.grid() self.command_frame.grid() active_dist = self._get_active_dist(name) if active_dist is not None: self.name_label["text"] = active_dist["project_name"] self.info_text.direct_insert("end", _("Installed version:") + " ", ("caption",)) self.info_text.direct_insert("end", active_dist["version"] + "\n") self.info_text.direct_insert("end", _("Installed to:") + " ", ("caption",)) self.info_text.direct_insert( "end", normpath_with_actual_case(active_dist["location"]), ("url",) ) self.info_text.direct_insert("end", "\n\n") self._select_list_item(name) else: self._select_list_item(0) # update gui if self._is_read_only_package(name): self.install_button.grid_remove() self.uninstall_button.grid_remove() self.advanced_button.grid_remove() else: self.install_button.grid(row=0, column=0) self.advanced_button.grid(row=0, column=2) if active_dist is not None: # existing package in target directory self.install_button["text"] = _("Upgrade") self.install_button["state"] = "disabled" self.uninstall_button.grid(row=0, column=1) else: # new package self.install_button["text"] = _("Install") self.uninstall_button.grid_remove() def _show_package_info(self, name, data, error_code=None): self._set_state("idle") self.current_package_data = data def write(s, tag=None): if tag is None: tags = () else: tags = (tag,) self.info_text.direct_insert("end", s, tags) def write_att(caption, value, value_tag=None): write(caption + ": ", "caption") write(value, value_tag) write("\n") if error_code is not None: if error_code == 404: write(_("Could not find the package from PyPI.")) if not self._get_active_version(name): # new package write( "\n" + _("Please check your spelling!") + "\n" + _("You need to enter") + " " ) write(_("exact package name"), "bold") write("!") else: write( _("Could not find the package info from PyPI.") + " " + _("Error code:") + " " + str(error_code) ) return info = data["info"] self.name_label["text"] = info["name"] # search name could have been a bit different latest_stable_version = _get_latest_stable_version(data["releases"].keys()) if latest_stable_version is not None: write_att(_("Latest stable version"), latest_stable_version) else: write_att(_("Latest version"), data["info"]["version"]) write_att(_("Summary"), info["summary"]) write_att(_("Author"), info["author"]) write_att(_("Homepage"), info["home_page"], "url") if info.get("bugtrack_url", None): write_att(_("Bugtracker"), info["bugtrack_url"], "url") if info.get("docs_url", None): write_att(_("Documentation"), info["docs_url"], "url") if info.get("package_url", None): write_att(_("PyPI page"), info["package_url"], "url") if info.get("requires_dist", None): # Available only when release is created by a binary wheel # https://github.com/pypa/pypi-legacy/issues/622#issuecomment-305829257 write_att(_("Requires"), ", ".join(info["requires_dist"])) if self._get_active_version(name) != latest_stable_version or not self._get_active_version( name ): self.install_button["state"] = "normal" else: self.install_button["state"] = "disabled" def _is_read_only_package(self, name): dist = self._get_active_dist(name) if dist is None: return False else: return normpath_with_actual_case(dist["location"]) != self._get_target_directory() def _normalize_name(self, name): # looks like (in some cases?) pip list gives the name as it was used during install # ie. the list may contain lowercase entry, when actual metadata has uppercase name # Example: when you "pip install cx-freeze", then "pip list" # really returns "cx-freeze" although correct name is "cx_Freeze" # https://www.python.org/dev/peps/pep-0503/#id4 return re.sub(r"[-_.]+", "-", name).lower().strip() def _select_list_item(self, name_or_index): if isinstance(name_or_index, int): index = name_or_index else: normalized_items = list(map(self._normalize_name, self.listbox.get(0, "end"))) try: index = normalized_items.index(self._normalize_name(name_or_index)) except Exception: exception(_("Can't find package name from the list:") + " " + name_or_index) return old_state = self.listbox["state"] try: self.listbox["state"] = "normal" self.listbox.select_clear(0, "end") self.listbox.select_set(index) self.listbox.activate(index) self.listbox.see(index) finally: self.listbox["state"] = old_state def _perform_action(self, action): assert self._get_state() == "idle" assert self.current_package_data is not None data = self.current_package_data name = self.current_package_data["info"]["name"] install_args = ["install", "--no-cache-dir"] if self._use_user_install(): install_args.append("--user") if action == "install": if not self._confirm_install(self.current_package_data): return args = install_args if self._get_active_version(name) is not None: args.append("--upgrade") args.append(name) elif action == "uninstall": if name in ["pip", "setuptools"] and not messagebox.askyesno( _("Really uninstall?"), _( "Package '{}' is required for installing and uninstalling other packages." ).format(name) + "\n\n" + _("Are you sure you want to uninstall it?"), ): return args = ["uninstall", "-y", name] elif action == "advanced": details = _ask_installation_details( self, data, _get_latest_stable_version(list(data["releases"].keys())) ) if details is None: # Cancel return version, package_data, upgrade_deps = details if not self._confirm_install(package_data): return args = install_args if upgrade_deps: args.append("--upgrade") args.append(name + "==" + version) else: raise RuntimeError("Unknown action") proc, cmd = self._create_pip_process(args) title = subprocess.list2cmdline(cmd) # following call blocks _show_subprocess_dialog(self, proc, title) if action == "uninstall": self._show_instructions() # Make the old package go away as fast as possible self._start_update_list(None if action == "uninstall" else name) def _handle_install_file_click(self, event): if self._get_state() != "idle": return filename = askopenfilename( master=self, filetypes=[(_("Package"), ".whl .zip .tar.gz"), (_("all files"), ".*")], initialdir=get_workbench().get_local_cwd, ) if filename: # Note that missing filename may be "" or () depending on tkinter version self._install_local_file(filename, False) def _handle_install_requirements_click(self, event): if self._get_state() != "idle": return filename = askopenfilename( master=self, filetypes=[("requirements", ".txt"), (_("all files"), ".*")], initialdir=get_workbench().get_local_cwd, ) if filename: # Note that missing filename may be "" or () depending on tkinter version self._install_local_file(filename, True) def _handle_target_directory_click(self, event): if self._get_target_directory(): open_path_in_system_file_manager(self._get_target_directory()) def _install_local_file(self, filename, is_requirements_file): args = ["install"] if self._use_user_install(): args.append("--user") if is_requirements_file: args.append("-r") args.append(filename) proc, cmd = self._create_pip_process(args) # following call blocks title = subprocess.list2cmdline(cmd) _, out, _ = _show_subprocess_dialog(self, proc, title) # Try to find out the name of the package we're installing name = None # output should include a line like this: # Installing collected packages: pytz, six, python-dateutil, numpy, pandas inst_lines = re.findall( "^Installing collected packages:.*?$", out, re.MULTILINE | re.IGNORECASE ) # @UndefinedVariable if len(inst_lines) == 1: # take last element elements = re.split(",|:", inst_lines[0]) name = elements[-1].strip() self._start_update_list(name) def _handle_url_click(self, event): url = _extract_click_text(self.info_text, event, "url") if url is not None: if url.startswith("http:") or url.startswith("https:"): webbrowser.open(url) else: os.makedirs(url, exist_ok=True) open_path_in_system_file_manager(url) def _on_close(self, event=None): self.destroy() def _get_active_version(self, name): dist = self._get_active_dist(name) if dist is None: return None else: return dist["version"] def _get_active_dist(self, name): normname = self._normalize_name(name) for key in self._active_distributions: if self._normalize_name(key) == normname: return self._active_distributions[key] return None def _create_python_process(self, args, stderr): raise NotImplementedError() def _create_pip_process(self, args, stderr=subprocess.STDOUT): if "--disable-pip-version-check" not in args: args.append("--disable-pip-version-check") return self._create_python_process(["-m", "pip"] + args, stderr=stderr) def _get_interpreter(self): pass def _should_install_to_site_packages(self): raise NotImplementedError() def _use_user_install(self): return not self._should_install_to_site_packages() def _get_target_directory(self): raise NotImplementedError() def _get_title(self): return _("Manage packages for %s") % self._get_interpreter() def _confirm_install(self, package_data): return True def _read_only(self): if self._should_install_to_site_packages(): return False else: # readonly if not in a virtual environment # and user site packages is disabled import site return not site.ENABLE_USER_SITE class BackendPipDialog(PipDialog): def __init__(self, master): self._backend_proxy = get_runner().get_backend_proxy() super().__init__(master) assert isinstance(self._backend_proxy, running.CPythonProxy) self._last_name_to_show = None def _start_update_list(self, name_to_show=None): assert self._get_state() in [None, "idle"] self._set_state("listing") get_workbench().bind("get_active_distributions_response", self._complete_update_list, True) self._last_name_to_show = name_to_show get_runner().send_command(InlineCommand("get_active_distributions")) def _complete_update_list(self, msg): get_workbench().unbind("get_active_distributions_response", self._complete_update_list) if "error" in msg: self.info_text.direct_delete("1.0", "end") self.info_text.direct_insert("1.0", msg["error"]) self._set_state("idle", True) return self._active_distributions = msg.distributions self._set_state("idle", True) self._update_list(self._last_name_to_show) def _get_interpreter(self): return get_runner().get_local_executable() def _create_python_process(self, args, stderr): proc = running.create_backend_python_process(args, stderr=stderr) return proc, proc.cmd def _confirm_install(self, package_data): name = package_data["info"]["name"] if name.lower().startswith("thonny"): return messagebox.askyesno( _("Confirmation"), _( "Looks like you are installing a Thonny-related package.\n" + "If you meant to install a Thonny plugin, then you should\n" + "choose 'Tools → Manage plugins...' instead\n" + "\n" + "Are you sure you want to install %s for the back-end?" ) % name, ) else: return True def _handle_outdated_or_missing_pip(self, error): if get_runner().using_venv(): self._install_pip() else: self._provide_pip_install_instructions(error) def _get_target_directory(self): if self._should_install_to_site_packages(): return normpath_with_actual_case(self._backend_proxy.get_site_packages()) else: usp = self._backend_proxy.get_user_site_packages() os.makedirs(usp, exist_ok=True) return normpath_with_actual_case(usp) def _should_install_to_site_packages(self): return self._targets_virtual_environment() def _targets_virtual_environment(self): return get_runner().using_venv() class PluginsPipDialog(PipDialog): def __init__(self, master): PipDialog.__init__(self, master) # make sure directory exists, so user can put her plug-ins there d = self._get_target_directory() makedirs(d, exist_ok=True) def _start_update_list(self, name_to_show=None): assert self._get_state() in [None, "idle"] import pkg_resources pkg_resources._initialize_master_working_set() self._active_distributions = { dist.key: { "project_name": dist.project_name, "key": dist.key, "location": dist.location, "version": dist.version, } for dist in pkg_resources.working_set # pylint: disable=not-an-iterable } self._update_list(name_to_show) def _conflicts_with_thonny_version(self, req_strings): import pkg_resources try: conflicts = [] for req_string in req_strings: req = pkg_resources.Requirement.parse(req_string) if req.project_name == "thonny" and thonny.get_version() not in req: conflicts.append(req_string) return conflicts except Exception: logging.exception("Problem computing conflicts") return None def _get_interpreter(self): return get_interpreter_for_subprocess(sys.executable) def _should_install_to_site_packages(self): return self._targets_virtual_environment() def _targets_virtual_environment(self): # https://stackoverflow.com/a/42580137/261181 return ( hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix or hasattr(sys, "real_prefix") and getattr(sys, "real_prefix") != sys.prefix ) def _create_python_process(self, args, stderr): proc = running.create_frontend_python_process(args, stderr=stderr) return proc, proc.cmd def _confirm_install(self, package_data): name = package_data["info"]["name"] reqs = package_data["info"].get("requires_dist", None) other_version_text = _( "NB! There may be another version available " + "which is compatible with current Thonny version. " + "Click on '...' button to choose the version to install." ) if name.lower().startswith("thonny-") and not reqs: showerror( _("Thonny plugin without requirements"), _( "Looks like you are trying to install an outdated Thonny\n" + "plug-in (it doesn't specify required Thonny version).\n\n" + "If you still want it, then please install it from the command line." ) + "\n\n" + other_version_text, ) return False elif reqs: conflicts = self._conflicts_with_thonny_version(reqs) if conflicts: showerror( _("Unsuitable requirements"), _("This package requires different Thonny version:") + "\n\n " + "\n ".join(conflicts) + "\n\n" + _("If you still want it, then please install it from the command line.") + "\n\n" + other_version_text, ) return False return True def _get_target_directory(self): if self._use_user_install(): import site assert hasattr(site, "getusersitepackages") os.makedirs(site.getusersitepackages(), exist_ok=True) return normpath_with_actual_case(site.getusersitepackages()) else: for d in sys.path: if ("site-packages" in d or "dist-packages" in d) and path_startswith( d, sys.prefix ): return normpath_with_actual_case(d) return None def _create_widgets(self, parent): bg = "#ffff99" banner = tk.Label(parent, background=bg) banner.grid(row=0, column=0, sticky="nsew") banner_msg = ( _( "This dialog is for managing Thonny plug-ins and their dependencies.\n" + "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" ) + "\n" ) runner = get_runner() if ( runner is not None and runner.get_local_executable() is not None and is_same_path(self._get_interpreter(), get_runner().get_local_executable()) ): banner_msg += ( _( "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" ) + "\n" ) banner_msg += "\n" + _( "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." ) banner_text = tk.Label(banner, text=banner_msg, background=bg, justify="left") banner_text.grid(pady=10, padx=10) PipDialog._create_widgets(self, parent) def _get_title(self): return _("Thonny plug-ins") def _handle_outdated_or_missing_pip(self, error): return self._provide_pip_install_instructions(error) class DetailsDialog(CommonDialog): def __init__(self, master, package_metadata, selected_version): super().__init__(master) self.result = None self._closed = False self._version_data = None self._package_name = package_metadata["info"]["name"] self.title(_("Advanced install / upgrade / downgrade")) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) main_frame = ttk.Frame(self) # To get styled background main_frame.grid(sticky="nsew") main_frame.rowconfigure(0, weight=1) main_frame.columnconfigure(0, weight=1) version_label = ttk.Label(main_frame, text=_("Desired version")) version_label.grid(row=0, column=0, columnspan=2, padx=20, pady=(15, 0), sticky="w") def version_sort_key(s): # Trying to massage understandable versions into valid StrictVersions if s.replace(".", "").isnumeric(): # stable release s2 = s + "b999" # make it latest beta version elif "rc" in s: s2 = s.replace("rc", "b8") else: s2 = s try: return StrictVersion(s2) except Exception: # use only numbers nums = re.findall(r"\d+", s) while len(nums) < 2: nums.append("0") return StrictVersion(".".join(nums[:3])) version_strings = list(package_metadata["releases"].keys()) version_strings.sort(key=version_sort_key, reverse=True) self.version_var = ui_utils.create_string_var( selected_version, self._start_fetching_version_info ) self.version_combo = ttk.Combobox( main_frame, textvariable=self.version_var, values=version_strings, exportselection=False ) self.version_combo.state(["!disabled", "readonly"]) self.version_combo.grid(row=1, column=0, columnspan=2, pady=(0, 15), padx=20, sticky="ew") self.requires_label = ttk.Label(main_frame, text="") self.requires_label.grid(row=2, column=0, columnspan=2, pady=(0, 15), padx=20, sticky="ew") self.update_deps_var = tk.IntVar() self.update_deps_var.set(0) self.update_deps_cb = ttk.Checkbutton( main_frame, text=_("Upgrade dependencies"), variable=self.update_deps_var ) self.update_deps_cb.grid(row=3, column=0, columnspan=2, padx=20, sticky="w") self.ok_button = ttk.Button(main_frame, text=_("Install"), command=self._ok) self.ok_button.grid(row=4, column=0, pady=15, padx=(20, 0), sticky="se") self.cancel_button = ttk.Button(main_frame, text=_("Cancel"), command=self._cancel) self.cancel_button.grid(row=4, column=1, pady=15, padx=(5, 20), sticky="se") # self.resizable(height=tk.FALSE, width=tk.FALSE) self.version_combo.focus_set() self.bind("", self._cancel, True) self.protocol("WM_DELETE_WINDOW", self._cancel) if self.version_var.get().strip(): self._start_fetching_version_info() def _set_state(self, state): self._state = state widgets = [ self.version_combo, # self.search_box, # looks funny when disabled self.ok_button, self.update_deps_cb, ] if state == "idle": self.config(cursor="") for widget in widgets: if widget == self.version_combo: widget.state(["!disabled", "readonly"]) else: widget["state"] = tk.NORMAL else: self.config(cursor=get_busy_cursor()) for widget in widgets: widget["state"] = tk.DISABLED if self.version_var.get().strip() == "" or not self._version_data: self.ok_button["state"] = tk.DISABLED def _start_fetching_version_info(self): self._set_state("busy") _start_fetching_package_info( self._package_name, self.version_var.get(), self._show_version_info ) def _show_version_info(self, name, info, error_code=None): if self._closed: return self._version_data = info if ( not error_code and "requires_dist" in info["info"] and isinstance(info["info"]["requires_dist"], list) ): reqs = _("Requires:") + "\n * " + "\n * ".join(info["info"]["requires_dist"]) elif error_code: reqs = _("Error code:") + " " + str(error_code) if "error" in info: reqs += "\n" + _("Error:") + " " + info["error"] else: reqs = "" self.requires_label.configure(text=reqs) self._set_state("idle") def _ok(self, event=None): self.result = (self.version_var.get(), self._version_data, bool(self.update_deps_var.get())) self._closed = True self.destroy() def _cancel(self, event=None): self.result = None self._closed = True self.destroy() def _fetch_url_future(url, timeout=10): def load_url(): with urlopen(url, timeout=timeout) as conn: return (conn, conn.read()) executor = ThreadPoolExecutor(max_workers=1) return executor.submit(load_url) def _get_latest_stable_version(version_strings): versions = [] for s in version_strings: if s.replace(".", "").isnumeric(): # Assuming stable versions have only dots and numbers versions.append( LooseVersion(s) ) # LooseVersion __str__ doesn't change the version string if len(versions) == 0: return None return str(sorted(versions)[-1]) def _show_subprocess_dialog(master, proc, title): dlg = SubprocessDialog(master, proc, title) ui_utils.show_dialog(dlg, master) return dlg.returncode, dlg.stdout, dlg.stderr def _ask_installation_details(master, data, selected_version): dlg = DetailsDialog(master, data, selected_version) ui_utils.show_dialog(dlg, master) return dlg.result def _start_fetching_package_info(name, version_str, completion_handler): # Fetch info from PyPI if version_str is None: url = "https://pypi.org/pypi/{}/json".format(urllib.parse.quote(name)) else: url = "https://pypi.org/pypi/{}/{}/json".format( urllib.parse.quote(name), urllib.parse.quote(version_str) ) url_future = _fetch_url_future(url) def poll_fetch_complete(): if url_future.done(): try: _, bin_data = url_future.result() raw_data = bin_data.decode("UTF-8") completion_handler(name, json.loads(raw_data)) except urllib.error.HTTPError as e: completion_handler( name, {"info": {"name": name}, "error": str(e), "releases": {}}, e.code ) else: tk._default_root.after(200, poll_fetch_complete) poll_fetch_complete() def _extract_click_text(widget, event, tag): # http://stackoverflow.com/a/33957256/261181 try: index = widget.index("@%s,%s" % (event.x, event.y)) tag_indices = list(widget.tag_ranges(tag)) for start, end in zip(tag_indices[0::2], tag_indices[1::2]): # check if the tag matches the mouse click index if widget.compare(start, "<=", index) and widget.compare(index, "<", end): return widget.get(start, end) except Exception: logging.exception("extracting click text") return None def load_plugin() -> None: def open_backend_pip_gui(*args): pg = BackendPipDialog(get_workbench()) ui_utils.show_dialog(pg) def open_backend_pip_gui_enabled(): return "pip_gui" in get_runner().get_supported_features() def open_frontend_pip_gui(*args): pg = PluginsPipDialog(get_workbench()) ui_utils.show_dialog(pg) get_workbench().add_command( "backendpipgui", "tools", _("Manage packages..."), open_backend_pip_gui, tester=open_backend_pip_gui_enabled, group=80, ) get_workbench().add_command( "pluginspipgui", "tools", _("Manage plug-ins..."), open_frontend_pip_gui, group=180 ) thonny-3.2.7/thonny/plugins/shell_macro.py0000644000175000017500000000665213611773167021743 0ustar annamaaannamaa00000000000000import tkinter as tk from tkinter import ttk from thonny import get_runner, get_workbench, misc_utils, ui_utils from thonny.codeview import CodeView from thonny.ui_utils import CommonDialog class ShellMacroDialog(CommonDialog): def __init__(self, master): super().__init__(master) self.title("Configure shell macro") if misc_utils.running_on_mac_os(): self.configure(background="systemSheetBackground") self.transient(master) self.grab_set() # to make it active # self.grab_release() # to allow eg. copy something from the editor self._create_widgets() self.bind("", self._on_close, True) self.protocol("WM_DELETE_WINDOW", self._on_close) self.main_command_text.focus_set() def _create_widgets(self): bg = "#ffff99" banner_frame = tk.Frame(self, background=bg) banner_frame.grid(row=0, column=0, sticky="nsew") banner_frame.rowconfigure(0, weight=1) banner_frame.columnconfigure(0, weight=1) banner_text = tk.Label( banner_frame, text="These\nare\ninstructions asdfa afs fa sfasdf", background=bg, justify="left", ) banner_text.grid(column=0, row=0, pady=10, padx=10, sticky="nsew") main_frame = ttk.Frame(self) main_frame.grid(row=1, column=0, sticky=tk.NSEW, padx=15, pady=15) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.main_command_text = CodeView(main_frame, height=5) self.main_command_text.grid(column=0, row=1, sticky="nsew") # main_command_text["relief"] = "groove" main_frame.rowconfigure(1, weight=1) main_frame.columnconfigure(0, weight=1) button_frame = ttk.Frame(main_frame) button_frame.grid(row=2, column=0, sticky="nsew") run_button = ttk.Button(button_frame, text="Save and execute", command=self._save_exec) run_button.grid(row=0, column=1, sticky="nsew") ok_button = ttk.Button(button_frame, text="Save", command=self._save) ok_button.grid(row=0, column=2, sticky="nsew") cancel_button = ttk.Button(button_frame, text="Cancel", command=self._cancel) cancel_button.grid(row=0, column=3, sticky="nsew") button_frame.columnconfigure(0, weight=1) def _on_close(self, event=None): self.destroy() def _save_exec(self, event=None): self._save(event) execute_macro() def _save(self, event=None): source = self.main_command_text.text.get("1.0", "end") get_workbench().set_option("run.shell_macro_main", repr(source)) self.destroy() def _cancel(self, event=None): self.destroy() def show_dialog(): dlg = ShellMacroDialog(get_workbench()) ui_utils.show_dialog(dlg) def execute_macro(): if get_runner().is_waiting_toplevel_command(): source = get_workbench().get_option("run.shell_macro_main") if source is not None: shell = get_workbench().show_view("ShellView") shell.submit_python_code(source.strip() + "\n") def _load_plugin(): get_workbench().set_default("run.shell_macro_main", None) get_workbench().add_command( "configure_shell_macro", "run", "Configure shell macro...", show_dialog ) get_workbench().add_command( "execute_shell_macro", "run", "Execute shell macro", execute_macro, default_sequence="" ) thonny-3.2.7/thonny/plugins/event_logging.py0000644000175000017500000001432313611773167022274 0ustar annamaaannamaa00000000000000import json import os.path import time import tkinter as tk import zipfile from datetime import datetime from thonny import THONNY_USER_DIR, get_workbench from thonny.shell import ShellView from thonny.ui_utils import asksaveasfilename from thonny.workbench import WorkbenchEvent class EventLogger: def __init__(self, filename): self._filename = filename self._events = [] wb = get_workbench() wb.bind("WorkbenchClose", self._on_worbench_close, True) for sequence in [ "<>", "<>", "<>", "<>", "<>", # "<>", # "", # "", "", "", "", ]: self._bind_all(sequence) for sequence in [ "UiCommandDispatched", "MagicCommand", "Open", "Save", "SaveAs", "NewFile", "EditorTextCreated", # "ShellTextCreated", # Too bad, this event happens before event_logging is loaded "ShellCommand", "ShellInput", "ShowView", "HideView", "TextInsert", "TextDelete", ]: self._bind_workbench(sequence) self._bind_workbench("", True) self._bind_workbench("", True) ### log_user_event(KeyPressEvent(self, e.char, e.keysym, self.text.index(tk.INSERT))) # TODO: if event data includes an Editor, then look up also text id def _bind_workbench(self, sequence, only_workbench_widget=False): def handle(event): if not only_workbench_widget or event.widget == get_workbench(): self._log_event(sequence, event) get_workbench().bind(sequence, handle, True) def _bind_all(self, sequence): def handle(event): self._log_event(sequence, event) tk._default_root.bind_all(sequence, handle, True) def _extract_interesting_data(self, event, sequence): attributes = vars(event) # generate some new attributes if "text_widget" not in attributes: if "editor" in attributes: attributes["text_widget"] = attributes["editor"].get_text_widget() if "widget" in attributes and isinstance(attributes["widget"], tk.Text): attributes["text_widget"] = attributes["widget"] if "text_widget" in attributes: widget = attributes["text_widget"] if isinstance(widget.master.master, ShellView): attributes["text_widget_context"] = "shell" # select attributes data = {} for name in attributes: # skip some attributes if ( name.startswith("_") or isinstance(event, WorkbenchEvent) and name in ["update", "setdefault"] or isinstance(event, tk.Event) and name not in ["widget", "text_widget", "text_widget_context"] ): continue value = attributes[name] if isinstance(value, (tk.BaseWidget, tk.Tk)): data[name + "_id"] = id(value) data[name + "_class"] = value.__class__.__name__ elif isinstance(value, (str, int, float)): data[name] = value else: data[name] = repr(value) return data def _log_event(self, sequence, event): data = self._extract_interesting_data(event, sequence) data["sequence"] = sequence data["time"] = datetime.now().isoformat() self._events.append(data) def _on_worbench_close(self, event=None): with open(self._filename, encoding="UTF-8", mode="w") as fp: json.dump(self._events, fp, indent=" ") self._check_compress_logs() def _check_compress_logs(self): # if uncompressed logs have grown over 10MB, # compress these into new zipfile log_dir = _get_log_dir() total_size = 0 uncompressed_files = [] for item in os.listdir(log_dir): if item.endswith(".txt"): full_name = os.path.join(log_dir, item) total_size += os.stat(full_name).st_size uncompressed_files.append((item, full_name)) if total_size > 10 * 1024 * 1024: zip_filename = _generate_timestamp_file_name("zip") with zipfile.ZipFile(zip_filename, "w", compression=zipfile.ZIP_DEFLATED) as zipf: for item, full_name in uncompressed_files: zipf.write(full_name, arcname=item) for _, full_name in uncompressed_files: os.remove(full_name) def _generate_timestamp_file_name(extension): # generate log filename folder = _get_log_dir() if not os.path.exists(folder): os.makedirs(folder) for i in range(100): filename = os.path.join( folder, time.strftime("%Y-%m-%d_%H-%M-%S_{}.{}".format(i, extension)) ) if not os.path.exists(filename): return filename raise RuntimeError() def _get_log_dir(): return os.path.join(THONNY_USER_DIR, "user_logs") def export(): filename = asksaveasfilename( filetypes=[("Zip-files", ".zip"), ("all files", ".*")], defaultextension=".zip", initialdir=get_workbench().get_local_cwd(), initialfile=time.strftime("ThonnyUsageLogs_%Y-%m-%d.zip"), ) if not filename: return log_dir = _get_log_dir() with zipfile.ZipFile(filename, "w", compression=zipfile.ZIP_DEFLATED) as zipf: for item in os.listdir(log_dir): if item.endswith(".txt") or item.endswith(".zip"): zipf.write(os.path.join(log_dir, item), arcname=item) def load_plugin() -> None: get_workbench().set_default("general.event_logging", False) if get_workbench().get_option("general.event_logging"): get_workbench().add_command( "export_usage_logs", "tools", _("Export usage logs..."), export, group=110 ) filename = _generate_timestamp_file_name("txt") # create logger EventLogger(filename) thonny-3.2.7/thonny/plugins/assistant_config_page.py0000644000175000017500000000603713611773167024002 0ustar annamaaannamaa00000000000000from tkinter import ttk from thonny.config_ui import ConfigurationPage from thonny import get_workbench, ui_utils from thonny.tktextext import TextFrame from thonny.ui_utils import scrollbar_style class AssistantConfigPage(ConfigurationPage): def __init__(self, master): super().__init__(master) ui_utils.create_url_label( self, "https://github.com/thonny/thonny/wiki/Friendly-traceback", text=_("Friendly traceback level"), ).grid(row=1, column=0, sticky="w") self.add_combobox( "assistance.friendly_traceback_level", values=[0, 1, 2, 3, 4, 5, 6, 7, 9], row=1, column=1, width=3, padx=5, ) self.add_checkbox( "assistance.open_assistant_on_errors", _("Open Assistant automatically when program crashes with an exception"), row=2, columnspan=2, ) self.add_checkbox( "assistance.open_assistant_on_warnings", _("Open Assistant automatically when it has warnings for your code"), row=3, columnspan=2, ) if get_workbench().get_option("assistance.use_pylint", "missing") != "missing": self.add_checkbox( "assistance.use_pylint", _("Perform selected Pylint checks"), row=4, columnspan=2 ) if get_workbench().get_option("assistance.use_mypy", "missing") != "missing": self.add_checkbox("assistance.use_mypy", _("Perform MyPy checks"), row=5, columnspan=2) disabled_checks_label = ttk.Label(self, text=_("Disabled checks (one id per line)")) disabled_checks_label.grid(row=8, sticky="nw", pady=(10, 0), columnspan=2) self.disabled_checks_box = TextFrame( self, vertical_scrollbar_style=scrollbar_style("Vertical"), horizontal_scrollbar_style=scrollbar_style("Horizontal"), horizontal_scrollbar_class=ui_utils.AutoScrollbar, wrap="word", font="TkDefaultFont", # cursor="arrow", padx=5, pady=5, height=4, borderwidth=1, relief="groove", ) self.disabled_checks_box.grid(row=9, sticky="nsew", pady=(0, 10), columnspan=2) self.disabled_checks_box.text.insert( "1.0", "\n".join(get_workbench().get_option("assistance.disabled_checks")) ) self.columnconfigure(1, weight=1) self.rowconfigure(9, weight=1) def apply(self): disabled_checks_str = ( self.disabled_checks_box.text.get("1.0", "end") .replace("\r", "") .replace('"', "") .replace("'", "") .strip() ) get_workbench().set_option("assistance.disabled_checks", disabled_checks_str.splitlines()) def load_plugin(): get_workbench().set_default("assistance.friendly_traceback_level", 0) get_workbench().add_configuration_page("assistant", _("Assistant"), AssistantConfigPage, 80) thonny-3.2.7/thonny/plugins/debugger.py0000644000175000017500000013645613611773167021245 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- """ Adds debugging commands and features. """ import ast import logging import os.path import tkinter as tk from tkinter import ttk from tkinter.messagebox import showinfo from typing import List, Union # @UnusedImport from thonny import ast_utils, code, get_runner, get_workbench, memory, misc_utils, ui_utils, running from thonny.codeview import CodeView, get_syntax_options_for_tag, SyntaxText from thonny.common import DebuggerCommand, InlineCommand from thonny.memory import VariablesFrame from thonny.misc_utils import shorten_repr, running_on_rpi, running_on_mac_os from thonny.tktextext import TextFrame from thonny.ui_utils import select_sequence, CommonDialog from _tkinter import TclError _current_debugger = None RESUME_COMMAND_CAPTION = "" # Init later when gettext is loaded class Debugger: def __init__(self): self._last_progress_message = None self._last_brought_out_frame_id = None self._editor_context_menu = None def check_issue_command(self, command, **kwargs): cmd = DebuggerCommand(command, **kwargs) self._last_debugger_command = cmd if get_runner().is_waiting_debugger_command(): logging.debug("_check_issue_debugger_command: %s", cmd) # tell VM the state we are seeing cmd.setdefault( frame_id=self._last_progress_message.stack[-1].id, breakpoints=self.get_effective_breakpoints(command), state=self._last_progress_message.stack[-1].event, focus=self._last_progress_message.stack[-1].focus, allow_stepping_into_libraries=get_workbench().get_option( "debugger.allow_stepping_into_libraries" ), ) if command == "run_to_cursor": # cursor position was added as another breakpoint cmd.name = "resume" get_runner().send_command(cmd) if command == "resume": self.clear_last_frame() else: logging.debug("Bad state for sending debugger command " + str(command)) def get_run_to_cursor_breakpoint(self): return None def get_effective_breakpoints(self, command): result = code.get_current_breakpoints() if command == "run_to_cursor": bp = self.get_run_to_cursor_breakpoint() if bp != None: filename, lineno = bp result.setdefault(filename, set()) result[filename].add(lineno) return result def command_enabled(self, command): if not get_runner().is_waiting_debugger_command(): return False if command == "run_to_cursor": return self.get_run_to_cursor_breakpoint() is not None elif command == "step_back": return ( self._last_progress_message and self._last_progress_message["tracer_class"] == "NiceTracer" ) else: return True def handle_debugger_progress(self, msg): self._last_brought_out_frame_id = None def handle_debugger_return(self, msg): pass def close(self) -> None: self._last_brought_out_frame_id = None if get_workbench().get_option("debugger.automatic_stack_view"): get_workbench().hide_view("StackView") def clear_last_frame(self): pass def get_frame_by_id(self, frame_id): for frame_info in self._last_progress_message.stack: if frame_info.id == frame_id: return frame_info raise ValueError("Could not find frame %d" % frame_id) def bring_out_frame(self, frame_id, force=False): # called by StackView raise NotImplementedError() def get_editor_context_menu(self): def create_edit_command_handler(virtual_event_sequence): def handler(event=None): widget = get_workbench().focus_get() if widget: return widget.event_generate(virtual_event_sequence) return None return handler if self._editor_context_menu is None: menu = tk.Menu(get_workbench()) menu.add( "command", label=_("Run to cursor"), command=lambda: self.check_issue_command("run_to_cursor"), ) menu.add("separator") menu.add("command", label="Copy", command=create_edit_command_handler("<>")) menu.add( "command", label=_("Select all"), command=create_edit_command_handler("<>"), ) self._editor_context_menu = menu return self._editor_context_menu class SingleWindowDebugger(Debugger): def __init__(self): super().__init__() self._last_frame_visualizer = None # Make sure StackView is created get_workbench().get_view("StackView") def get_run_to_cursor_breakpoint(self): editor = get_workbench().get_editor_notebook().get_current_editor() if editor: filename = editor.get_filename() selection = editor.get_code_view().get_selected_range() lineno = selection.lineno if filename and lineno: return filename, lineno return None def handle_debugger_progress(self, msg): super().handle_debugger_progress(msg) self._last_progress_message = msg self.bring_out_frame(self._last_progress_message.stack[-1].id, force=True) if get_workbench().get_option("debugger.automatic_stack_view"): if len(msg.stack) > 1: get_workbench().show_view("StackView") get_workbench().get_view("ExceptionView").set_exception( msg["exception_info"]["lines_with_frame_info"] ) def close(self): super().close() if self._last_frame_visualizer is not None: self._last_frame_visualizer.close() self._last_frame_visualizer = None def clear_last_frame(self): if self._last_frame_visualizer is not None: self._last_frame_visualizer.clear() def bring_out_frame(self, frame_id, force=False): if not force and frame_id == self._last_brought_out_frame_id: return self._last_brought_out_frame_id = frame_id frame_info = self.get_frame_by_id(frame_id) if ( self._last_frame_visualizer is not None and self._last_frame_visualizer._frame_id != frame_info.id ): self._last_frame_visualizer.close() self._last_frame_visualizer = None if self._last_frame_visualizer is None: self._last_frame_visualizer = EditorVisualizer(frame_info) self._last_frame_visualizer._update_this_frame(self._last_progress_message, frame_info) # show variables var_view = get_workbench().get_view("VariablesView") if frame_info.code_name == "": var_view.show_globals(frame_info.globals, frame_info.module_name) else: var_view.show_frame_variables( frame_info.locals, frame_info.globals, frame_info.freevars, frame_info.module_name if frame_info.code_name == "" else frame_info.code_name, ) def handle_debugger_return(self, msg): if self._last_frame_visualizer is not None and self._last_frame_visualizer.get_frame_id() == msg.get( "frame_id" ): self._last_frame_visualizer.close() class StackedWindowsDebugger(Debugger): def __init__(self): super().__init__() self._main_frame_visualizer = None def get_run_to_cursor_breakpoint(self): visualizer = self._get_topmost_selected_visualizer() if visualizer: assert isinstance(visualizer._text_frame, CodeView) code_view = visualizer._text_frame selection = code_view.get_selected_range() target_lineno = visualizer._firstlineno - 1 + selection.lineno return visualizer._filename, target_lineno else: return None def handle_debugger_progress(self, msg): super().handle_debugger_progress(msg) self._last_progress_message = msg main_frame_id = msg.stack[0].id # clear obsolete main frame visualizer if ( self._main_frame_visualizer and self._main_frame_visualizer.get_frame_id() != main_frame_id ): self._main_frame_visualizer.close() self._main_frame_visualizer = None if not self._main_frame_visualizer: self._main_frame_visualizer = EditorVisualizer(msg.stack[0]) self._main_frame_visualizer.update_this_and_next_frames(msg) self.bring_out_frame(msg.stack[-1].id, force=True) get_workbench().get_view("ExceptionView").set_exception( msg["exception_info"]["lines_with_frame_info"] ) def close(self): super().close() if self._main_frame_visualizer is not None: self._main_frame_visualizer.close() self._main_frame_visualizer = None def clear_last_frame(self): visualizer = self._get_topmost_visualizer() if visualizer is not None: visualizer.clear() def _get_topmost_visualizer(self): visualizer = self._main_frame_visualizer if visualizer is None: return None while visualizer._next_frame_visualizer is not None: visualizer = visualizer._next_frame_visualizer return visualizer def _get_topmost_selected_visualizer(self): visualizer = self._get_topmost_visualizer() if visualizer is None: return None topmost_text_widget = visualizer._text focused_widget = get_workbench().focus_get() if focused_widget is None: return None elif focused_widget == topmost_text_widget: return visualizer else: return None def bring_out_frame(self, frame_id, force=False): if not force and frame_id == self._last_brought_out_frame_id: return self._last_brought_out_frame_id = frame_id self._main_frame_visualizer.bring_out_frame(frame_id) # show variables var_view = get_workbench().get_view("VariablesView") frame_info = self.get_frame_by_id(frame_id) var_view.show_globals(frame_info.globals, frame_info.module_name) def handle_debugger_return(self, msg): if self._main_frame_visualizer is None: return self._main_frame_visualizer.close(msg["frame_id"]) if msg["frame_id"] == self._main_frame_visualizer.get_frame_id(): self._main_frame_visualizer = None class FrameVisualizer: """ Is responsible for stepping through statements and updating corresponding UI in Editor-s, FunctionCallDialog-s, ModuleDialog-s """ def __init__(self, text_frame, frame_info): self._text_frame = text_frame self._text = text_frame.text self._frame_info = frame_info self._frame_id = frame_info.id self._filename = frame_info.filename self._firstlineno = None if running_on_mac_os(): self._expression_box = ToplevelExpressionBox(text_frame) else: self._expression_box = PlacedExpressionBox(text_frame) self._note_box = ui_utils.NoteBox(text_frame.winfo_toplevel()) self._next_frame_visualizer = None self._prev_frame_visualizer = None self._text.set_read_only(True) self._line_debug = frame_info.current_statement is None self._reconfigure_tags() def _translate_lineno(self, lineno): return lineno - self._firstlineno + 1 def _reconfigure_tags(self): for tag in ["active_focus", "exception_focus"]: conf = get_syntax_options_for_tag(tag).copy() if self._line_debug: # meaning data comes from line-debug conf["borderwidth"] = 0 self._text.tag_configure(tag, **conf) def close(self, frame_id=None): if self._next_frame_visualizer: self._next_frame_visualizer.close(frame_id) if frame_id is None or self._next_frame_visualizer.get_frame_id() == frame_id: self._next_frame_visualizer = None if frame_id is None or frame_id == self._frame_id: self._text.set_read_only(False) self.clear() # self._expression_box.destroy() def clear(self): self.remove_focus_tags() self.hide_expression_box() self.close_note() def get_frame_id(self): return self._frame_id def update_this_and_next_frames(self, msg): """Must not be used on obsolete frame""" # debug("State: %s, focus: %s", msg.state, msg.focus) frame_info, next_frame_info = self._find_this_and_next_frame(msg.stack) self._update_this_frame(msg, frame_info) # clear obsolete next frame visualizer if self._next_frame_visualizer and ( not next_frame_info or self._next_frame_visualizer.get_frame_id() != next_frame_info.id ): self._next_frame_visualizer.close() self._next_frame_visualizer = None if next_frame_info and not self._next_frame_visualizer: self._next_frame_visualizer = self._create_next_frame_visualizer(next_frame_info) self._next_frame_visualizer._prev_frame_visualizer = self if self._next_frame_visualizer: self._next_frame_visualizer.update_this_and_next_frames(msg) def remove_focus_tags(self): for name in [ "exception_focus", "active_focus", "completed_focus", "suspended_focus", "sel", ]: self._text.tag_remove(name, "0.0", "end") def hide_expression_box(self): if self._expression_box is not None: self._expression_box.clear_debug_view() def _update_this_frame(self, msg, frame_info): self._frame_info = frame_info self.remove_focus_tags() if frame_info.event == "line": if ( frame_info.id in msg["exception_info"]["affected_frame_ids"] and msg["exception_info"]["is_fresh"] ): self._tag_range(frame_info.focus, "exception_focus") else: self._tag_range(frame_info.focus, "active_focus") else: if "statement" in frame_info.event: if msg["exception_info"]["msg"] is not None and msg["exception_info"]["is_fresh"]: stmt_tag = "exception_focus" elif frame_info.event.startswith("before"): stmt_tag = "active_focus" else: stmt_tag = "completed_focus" else: assert "expression" in frame_info.event stmt_tag = "suspended_focus" if frame_info.current_statement is not None: self._tag_range(frame_info.current_statement, stmt_tag) else: logging.warning("Missing current_statement: %s", frame_info) self._expression_box.update_expression(msg, frame_info) if ( frame_info.id in msg["exception_info"]["affected_frame_ids"] and msg["exception_info"]["is_fresh"] ): self._show_exception(msg["exception_info"]["lines_with_frame_info"], frame_info) else: self.close_note() def _show_exception(self, lines, frame_info): last_line_text = lines[-1][0] self.show_note( last_line_text.strip() + " ", ("...", lambda _: get_workbench().show_view("ExceptionView")), focus=frame_info.focus, ) def _find_this_and_next_frame(self, stack): for i in range(len(stack)): if stack[i].id == self._frame_id: if i == len(stack) - 1: # last frame return stack[i], None else: return stack[i], stack[i + 1] raise AssertionError("Frame doesn't exist anymore") def _tag_range(self, text_range, tag): # For most statements I want to highlight block of whole lines # but for pseudo-statements (like header in for-loop) I want to highlight only the indicated range self._text.tag_raise(tag) line_prefix = self._text.get( "%d.0" % self._translate_lineno(text_range.lineno), "%d.%d" % (self._translate_lineno(text_range.lineno), text_range.col_offset), ) if line_prefix.strip(): # pseudo-statement first_line = self._translate_lineno(text_range.lineno) last_line = self._translate_lineno(text_range.end_lineno) self._text.tag_add( tag, "%d.%d" % (first_line, text_range.col_offset), "%d.%d" % (last_line, text_range.end_col_offset), ) else: # normal statement first_line, first_col, last_line = self._get_text_range_block(text_range) for lineno in range(first_line, last_line + 1): self._text.tag_add(tag, "%d.%d" % (lineno, first_col), "%d.0" % (lineno + 1)) self._text.update_idletasks() self._text.see("%d.0" % (last_line)) self._text.see("%d.0" % (first_line)) if last_line - first_line < 3: # if it's safe to assume that whole code fits into screen # then scroll it down a bit so that expression view doesn't hide behind # lower edge of the editor self._text.update_idletasks() self._text.see("%d.0" % (first_line + 3)) def _get_text_range_block(self, text_range): first_line = text_range.lineno - self._firstlineno + 1 last_line = ( text_range.end_lineno - self._firstlineno + (1 if text_range.end_col_offset > 0 else 0) ) first_line_content = self._text.get("%d.0" % first_line, "%d.end" % first_line) if first_line_content.strip().startswith("elif "): first_col = first_line_content.find("elif ") else: first_col = text_range.col_offset return (first_line, first_col, last_line) def _create_next_frame_visualizer(self, next_frame_info): if next_frame_info.code_name == "": return ModuleLoadDialog(self._text, next_frame_info) else: dialog = FunctionCallDialog(self._text.master, next_frame_info) if self._expression_box.winfo_ismapped(): dialog.title(self._expression_box.get_focused_text()) else: dialog.title("Function call at " + hex(self._frame_id)) return dialog def bring_out_frame(self, frame_id): if self._frame_id == frame_id: self.bring_out_this_frame() elif self._next_frame_visualizer is not None: self._next_frame_visualizer.bring_out_frame(frame_id) def bring_out_this_frame(self): pass def show_note(self, *content_items: Union[str, List], target=None, focus=None) -> None: if target is None: target = self._text self._note_box.show_note(*content_items, target=target, focus=focus) def close_note(self): self._note_box.close() class EditorVisualizer(FrameVisualizer): """ Takes care of stepping in the editor (main module in case of StackedWindowsDebugger) """ def __init__(self, frame_info): self.editor = ( get_workbench().get_editor_notebook().show_file(frame_info.filename, set_focus=False) ) FrameVisualizer.__init__(self, self.editor.get_code_view(), frame_info) self._firstlineno = 1 def _update_this_frame(self, msg, frame_info): FrameVisualizer._update_this_frame(self, msg, frame_info) if msg.in_present: self._decorate_editor_title("") else: self._decorate_editor_title(" <<< REPLAYING >>> ") def _decorate_editor_title(self, suffix): self.editor.master.update_editor_title(self.editor, self.editor.get_title() + suffix) def bring_out_this_frame(self): get_workbench().focus_set() def clear(self): super().clear() self._decorate_editor_title("") class BaseExpressionBox: def __init__(self, codeview, text): self.text = text self._codeview = codeview self._last_focus = None self._last_root_expression = None self.text.tag_configure("value", get_syntax_options_for_tag("value")) self.text.tag_configure("before", get_syntax_options_for_tag("active_focus")) self.text.tag_configure("after", get_syntax_options_for_tag("completed_focus")) self.text.tag_configure("exception", get_syntax_options_for_tag("exception_focus")) self.text.tag_raise("exception", "before") self.text.tag_raise("exception", "after") def get_text_options(self): opts = dict( height=1, width=1, relief=tk.RAISED, background="#DCEDF2", borderwidth=1, highlightthickness=0, padx=7, pady=7, wrap=tk.NONE, font="EditorFont", ) opts.update(get_syntax_options_for_tag("expression_box")) return opts def update_expression(self, msg, frame_info): focus = frame_info.focus event = frame_info.event if frame_info.current_root_expression is not None: with open(frame_info.filename, "rb") as fp: whole_source = fp.read() lines = whole_source.splitlines() if len(lines) < frame_info.current_root_expression.end_lineno: # it must be on a synthetical line which is not actually present in the editor self.clear_debug_view() return self._load_expression( whole_source, frame_info.filename, frame_info.current_root_expression ) for subrange, value in frame_info.current_evaluations: self._replace(subrange, value) if "expression" in event: # Event may be also after_statement_again self._highlight_range( focus, event, ( frame_info.id in msg["exception_info"]["affected_frame_ids"] and msg["exception_info"]["is_fresh"] ), ) self._last_focus = focus self._update_position(frame_info.current_root_expression) self._update_size() else: # hide and clear on non-expression events self.clear_debug_view() self._last_root_expression = frame_info.current_root_expression def get_focused_text(self): if self._last_focus: start_mark = self._get_mark_name(self._last_focus.lineno, self._last_focus.col_offset) end_mark = self._get_mark_name( self._last_focus.end_lineno, self._last_focus.end_col_offset ) return self.text.get(start_mark, end_mark) else: return "" def clear_debug_view(self): self._main_range = None self._last_focus = None self._clear_expression() def _clear_expression(self): for tag in self.text.tag_names(): self.text.tag_remove(tag, "1.0", "end") self.text.mark_unset(*self.text.mark_names()) self.text.delete("1.0", "end") def _replace(self, focus, value): start_mark = self._get_mark_name(focus.lineno, focus.col_offset) end_mark = self._get_mark_name(focus.end_lineno, focus.end_col_offset) self.text.delete(start_mark, end_mark) id_str = memory.format_object_id(value.id) if get_workbench().in_heap_mode(): value_str = id_str else: value_str = shorten_repr(value.repr, 100) object_tag = "object_" + str(value.id) self.text.insert(start_mark, value_str, ("value", object_tag)) if misc_utils.running_on_mac_os(): sequence = "" else: sequence = "" self.text.tag_bind( object_tag, sequence, lambda _: get_workbench().event_generate("ObjectSelect", object_id=value.id), ) def _load_expression(self, whole_source, filename, text_range): root = ast_utils.parse_source(whole_source, filename) main_node = ast_utils.find_expression(root, text_range) source = ast_utils.extract_text_range(whole_source, text_range) logging.debug("EV.load_exp: %s", (text_range, main_node, source)) self._clear_expression() self.text.insert("1.0", source) # create node marks def _create_index(lineno, col_offset): local_lineno = lineno - main_node.lineno + 1 if lineno == main_node.lineno: local_col_offset = col_offset - main_node.col_offset else: local_col_offset = col_offset return str(local_lineno) + "." + str(local_col_offset) for node in ast.walk(main_node): if "lineno" in node._attributes and hasattr(node, "end_lineno"): index1 = _create_index(node.lineno, node.col_offset) index2 = _create_index(node.end_lineno, node.end_col_offset) start_mark = self._get_mark_name(node.lineno, node.col_offset) if not start_mark in self.text.mark_names(): self.text.mark_set(start_mark, index1) # print("Creating mark", start_mark, index1) self.text.mark_gravity(start_mark, tk.LEFT) end_mark = self._get_mark_name(node.end_lineno, node.end_col_offset) if not end_mark in self.text.mark_names(): self.text.mark_set(end_mark, index2) # print("Creating mark", end_mark, index2) self.text.mark_gravity(end_mark, tk.RIGHT) def _get_mark_name(self, lineno, col_offset): return str(lineno) + "_" + str(col_offset) def _get_tag_name(self, node_or_text_range): return ( str(node_or_text_range.lineno) + "_" + str(node_or_text_range.col_offset) + "_" + str(node_or_text_range.end_lineno) + "_" + str(node_or_text_range.end_col_offset) ) def _highlight_range(self, text_range, state, has_exception): logging.debug("EV._highlight_range: %s", text_range) self.text.tag_remove("after", "1.0", "end") self.text.tag_remove("before", "1.0", "end") self.text.tag_remove("exception", "1.0", "end") if state.startswith("after"): tag = "after" elif state.startswith("before"): tag = "before" else: return start_index = self._get_mark_name(text_range.lineno, text_range.col_offset) end_index = self._get_mark_name(text_range.end_lineno, text_range.end_col_offset) self.text.tag_add(tag, start_index, end_index) if has_exception: self.text.tag_add("exception", start_index, end_index) def _update_position(self, text_range): self._codeview.update_idletasks() text_line_number = text_range.lineno - self._codeview._first_line_number + 1 bbox = self._codeview.text.bbox(str(text_line_number) + "." + str(text_range.col_offset)) if isinstance(bbox, tuple): x = bbox[0] - self._codeview.text.cget("padx") + 6 y = bbox[1] - self._codeview.text.cget("pady") - 6 else: x = 30 y = 30 self._set_position_make_visible(x, y) def _update_size(self): content = self.text.get("1.0", tk.END) lines = content.splitlines() self.text["height"] = len(lines) self.text["width"] = max(map(len, lines)) class PlacedExpressionBox(BaseExpressionBox, tk.Text): def __init__(self, codeview): tk.Text.__init__(self, codeview.winfo_toplevel(), self.get_text_options()) BaseExpressionBox.__init__(self, codeview, self) def clear_debug_view(self): if self.winfo_ismapped(): self.place_forget() super().clear_debug_view() def _set_position_make_visible(self, rel_x, rel_y): x = rel_x y = rel_y widget = self._codeview.text while widget != self.master: x += widget.winfo_x() y += widget.winfo_y() widget = widget.master if not self.winfo_ismapped(): self.place(x=x, y=y, anchor=tk.NW) self.update() class ToplevelExpressionBox(BaseExpressionBox, tk.Toplevel): def __init__(self, codeview): tk.Toplevel.__init__(self, codeview.winfo_toplevel()) text = tk.Text(self, **self.get_text_options()) BaseExpressionBox.__init__(self, codeview, text) self.text.grid() if running_on_mac_os(): try: # NB! Must be the first thing to do after creation # https://wiki.tcl-lang.org/page/MacWindowStyle self.tk.call( "::tk::unsupported::MacWindowStyle", "style", self._w, "help", "noActivates" ) except TclError: pass else: raise RuntimeError("Should be used only on Mac") self.resizable(False, False) self.wm_transient(codeview.winfo_toplevel()) self.lift() def clear_debug_view(self): if self.winfo_ismapped(): self.withdraw() super().clear_debug_view() def _set_position_make_visible(self, rel_x, rel_y): """ widget = self._codeview.text while widget is not None: x += widget.winfo_x() y += widget.winfo_y() widget = widget.master """ x = rel_x + self._codeview.text.winfo_rootx() y = rel_y + self._codeview.text.winfo_rooty() if not self.winfo_ismapped(): self.update() self.deiconify() self.geometry("+%d+%d" % (x, y)) def get_text_options(self): opts = super().get_text_options() opts["relief"] = "flat" opts["borderwidth"] = 0 return opts class DialogVisualizer(CommonDialog, FrameVisualizer): def __init__(self, master, frame_info): CommonDialog.__init__(self, master) self.transient(master) if misc_utils.running_on_windows(): self.wm_attributes("-toolwindow", 1) # TODO: take size from prefs editor_notebook = get_workbench().get_editor_notebook() if master.winfo_toplevel() == get_workbench(): position_reference = editor_notebook else: # align to previous frame position_reference = master.winfo_toplevel() self.geometry( "{}x{}+{}+{}".format( editor_notebook.winfo_width(), editor_notebook.winfo_height() - 20, position_reference.winfo_rootx(), position_reference.winfo_rooty(), ) ) self.protocol("WM_DELETE_WINDOW", self._on_close) self.bind("", self._on_focus, True) self._init_layout_widgets(master, frame_info) FrameVisualizer.__init__(self, self._text_frame, frame_info) self._firstlineno = frame_info.firstlineno self._load_code(frame_info) self._text_frame.text.focus() self.update() def _init_layout_widgets(self, master, frame_info): self.main_frame = ttk.Frame( self ) # just a backgroud behind padding of main_pw, without this OS X leaves white border self.main_frame.grid(sticky=tk.NSEW) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.main_pw = ui_utils.AutomaticPanedWindow(self.main_frame, orient=tk.VERTICAL) self.main_pw.grid(sticky=tk.NSEW, padx=10, pady=10) self.main_frame.rowconfigure(0, weight=1) self.main_frame.columnconfigure(0, weight=1) self._code_book = ttk.Notebook(self.main_pw) self._text_frame = CodeView( self._code_book, first_line_number=frame_info.firstlineno, font="EditorFont" ) self._code_book.add(self._text_frame, text="Source") self.main_pw.add(self._code_book, minsize=200) self._code_book.preferred_size_in_pw = 400 def _load_code(self, frame_info): self._text_frame.set_content(frame_info.source) def _update_this_frame(self, msg, frame_info): FrameVisualizer._update_this_frame(self, msg, frame_info) def bring_out_this_frame(self): self.focus_set() # no effect when clicking on stack view var_view = get_workbench().get_view("VariablesView") var_view.show_globals(self._frame_info.globals, self._frame_info.module_name) def _on_focus(self, event): # TODO: bring out main frame when main window gets focus self.bring_out_this_frame() def _on_close(self): showinfo( _("Can't close yet"), _('Use "Stop" command if you want to cancel debugging'), parent=None if running_on_mac_os() else self, ) def close(self, frame_id=None): super().close() if frame_id is None or frame_id == self._frame_id: self.destroy() class FunctionCallDialog(DialogVisualizer): def __init__(self, master, frame_info): DialogVisualizer.__init__(self, master, frame_info) def _init_layout_widgets(self, master, frame_info): DialogVisualizer._init_layout_widgets(self, master, frame_info) self._locals_book = ttk.Notebook(self.main_pw) self._locals_frame = VariablesFrame(self._locals_book) self._locals_book.preferred_size_in_pw = 200 self._locals_book.add(self._locals_frame, text="Local variables") self.main_pw.add(self._locals_book, minsize=100) def _load_code(self, frame_info): DialogVisualizer._load_code(self, frame_info) function_label = frame_info.code_name # change tab label self._code_book.tab(self._text_frame, text=function_label) def _update_this_frame(self, msg, frame_info): DialogVisualizer._update_this_frame(self, msg, frame_info) self._locals_frame.update_variables(frame_info.locals) class ModuleLoadDialog(DialogVisualizer): def __init__(self, text_frame, frame_info): DialogVisualizer.__init__(self, text_frame, frame_info) class StackView(ui_utils.TreeFrame): def __init__(self, master): super().__init__( master, ("function", "location", "id"), displaycolumns=("function", "location") ) # self.tree.configure(show="tree") self.tree.column("#0", width=0, anchor=tk.W, stretch=False) self.tree.column("function", width=120, anchor=tk.W, stretch=False) self.tree.column("location", width=450, anchor=tk.W, stretch=True) self.tree.heading("function", text="Function", anchor=tk.W) self.tree.heading("location", text="Location", anchor=tk.W) get_workbench().bind("DebuggerResponse", self._update_stack, True) get_workbench().bind("ToplevelResponse", lambda e=None: self._clear_tree(), True) get_workbench().bind("debugger_return_response", self._handle_debugger_return, True) def _update_stack(self, msg): self._clear_tree() node_id = None for frame in msg.stack: lineno = frame.focus.lineno node_id = self.tree.insert("", "end") self.tree.set(node_id, "function", frame.code_name) self.tree.set( node_id, "location", "%s, line %s" % (os.path.basename(frame.filename), lineno) ) self.tree.set(node_id, "id", frame.id) # select last frame if node_id is not None: self.tree.see(node_id) self.tree.selection_add(node_id) self.tree.focus(node_id) def _handle_debugger_return(self, msg): delete = False for iid in self.tree.get_children(): if self.tree.set(iid, "id") == msg["frame_id"]: # start deleting from this frame delete = True if delete: self.tree.delete(iid) def on_select(self, event): iid = self.tree.focus() if iid != "": # assuming id is in the last column frame_id = self.tree.item(iid)["values"][-1] if _current_debugger is not None: _current_debugger.bring_out_frame(frame_id) class ExceptionView(TextFrame): def __init__(self, master): super().__init__( master, borderwidth=0, relief="solid", undo=False, read_only=True, font="TkDefaultFont", text_class=SyntaxText, foreground=get_syntax_options_for_tag("stderr")["foreground"], highlightthickness=0, padx=5, pady=5, wrap="char", horizontal_scrollbar=False, ) self.text.tag_configure("hyperlink", **get_syntax_options_for_tag("hyperlink")) self.text.tag_bind("hyperlink", "", self._hyperlink_enter) self.text.tag_bind("hyperlink", "", self._hyperlink_leave) get_workbench().bind("ToplevelResponse", self._on_toplevel_response, True) self._prev_exception = None self._show_description() def _show_description(self): self.text.configure(foreground=get_syntax_options_for_tag("TEXT")["foreground"]) self.text.direct_insert( "end", "If last command raised an exception then this view will show the stacktrace." ) def set_exception(self, exception_lines_with_frame_info): if exception_lines_with_frame_info == self._prev_exception: return self.text.direct_delete("1.0", "end") if exception_lines_with_frame_info is None: self._show_description() return self.text.configure(foreground=get_syntax_options_for_tag("stderr")["foreground"]) for line, frame_id, filename, lineno in exception_lines_with_frame_info: if frame_id is not None: frame_tag = "frame_%d" % frame_id def handle_frame_click(event, frame_id=frame_id, filename=filename, lineno=lineno): get_runner().send_command(InlineCommand("get_frame_info", frame_id=frame_id)) if os.path.exists(filename): get_workbench().get_editor_notebook().show_file( filename, lineno, set_focus=False ) self.text.tag_bind(frame_tag, "<1>", handle_frame_click, True) start = max(line.find("File"), 0) end = line.replace("\r", "").find("\n") if end < 10: end = len(line) self.text.direct_insert("end", line[:start]) self.text.direct_insert("end", line[start:end], ("hyperlink", frame_tag)) self.text.direct_insert("end", line[end:]) else: self.text.direct_insert("end", line) self._prev_exception = exception_lines_with_frame_info def _on_toplevel_response(self, msg): if "user_exception" in msg: self.set_exception(msg["user_exception"]["items"]) else: self.set_exception(None) def _hyperlink_enter(self, event): self.text.config(cursor="hand2") def _hyperlink_leave(self, event): self.text.config(cursor="") def _debugger_command_enabled(command): if _current_debugger is None: return False else: return _current_debugger.command_enabled(command) def _issue_debugger_command(command): if _current_debugger is None: raise AssertionError("Trying to send debugger command without debugger") else: return _current_debugger.check_issue_command(command) def _start_debug_enabled(): return ( _current_debugger is None and get_workbench().get_editor_notebook().get_current_editor() is not None and "debug" in get_runner().get_supported_features() ) def _request_debug(command_name): # Don't assume Debug command gets issued after this # This may just call the %cd command # or the user may deny saving current editor if get_workbench().in_simple_mode(): get_workbench().show_view("VariablesView") get_runner().execute_current(command_name) def _debug_accepted(event): # Called when proxy accepted the debug command global _current_debugger cmd = event.command if cmd.get("name") in ["Debug", "FastDebug"]: assert _current_debugger is None if get_workbench().get_option("debugger.frames_in_separate_windows"): _current_debugger = StackedWindowsDebugger() else: _current_debugger = SingleWindowDebugger() def _handle_debugger_progress(msg): global _current_debugger assert _current_debugger is not None _current_debugger.handle_debugger_progress(msg) _update_run_or_resume_button() def _handle_toplevel_response(msg): global _current_debugger if _current_debugger is not None: _current_debugger.close() _current_debugger = None _update_run_or_resume_button() def _handle_debugger_return(msg): global _current_debugger assert _current_debugger is not None _current_debugger.handle_debugger_return(msg) def _run_or_resume(): state = get_runner().get_state() if state == "waiting_debugger_command": _issue_debugger_command("resume") elif state == "waiting_toplevel_command": get_runner().cmd_run_current_script() def _run_or_resume_enabled(): return get_runner().cmd_run_current_script_enabled() or _debugger_command_enabled("resume") def _update_run_or_resume_button(): if not get_workbench().in_simple_mode(): return state = get_runner().get_state() if state == "waiting_debugger_command": caption = RESUME_COMMAND_CAPTION image = get_workbench().get_image("resume") elif state == "waiting_toplevel_command": caption = running.RUN_COMMAND_CAPTION image = get_workbench().get_image("run-current-script") else: return button = get_workbench().get_toolbar_button("runresume") button.configure(text=caption, image=image) def get_current_debugger(): return _current_debugger def run_preferred_debug_command(): preferred_debugger = get_workbench().get_option("debugger.preferred_debugger").lower() if preferred_debugger == "faster": return _request_debug("FastDebug") elif preferred_debugger == "birdseye": from thonny.plugins.birdseye_frontend import debug_with_birdseye return debug_with_birdseye() else: return _request_debug("Debug") def load_plugin() -> None: global RESUME_COMMAND_CAPTION RESUME_COMMAND_CAPTION = _("Resume") if get_workbench().in_simple_mode(): get_workbench().set_default("debugger.frames_in_separate_windows", False) else: get_workbench().set_default("debugger.frames_in_separate_windows", True) get_workbench().set_default("debugger.automatic_stack_view", True) get_workbench().set_default( "debugger.preferred_debugger", "faster" if running_on_rpi() else "nicer" ) get_workbench().set_default("debugger.allow_stepping_into_libraries", False) get_workbench().add_command( "runresume", "run", _("Run / resume"), _run_or_resume, caption=running.RUN_COMMAND_CAPTION, tester=_run_or_resume_enabled, default_sequence=None, group=10, image="run-current-script", include_in_menu=False, include_in_toolbar=get_workbench().in_simple_mode(), alternative_caption=RESUME_COMMAND_CAPTION, ) get_workbench().add_command( "debug_preferred", "run", _("Debug current script"), run_preferred_debug_command, caption=_("Debug"), tester=_start_debug_enabled, group=10, image="debug-current-script", include_in_menu=False, include_in_toolbar=True, ) get_workbench().add_command( "debug_nicer", "run", _("Debug current script (nicer)"), lambda: _request_debug("Debug"), caption="Debug (nicer)", tester=_start_debug_enabled, default_sequence="", group=10, # image="debug-current-script", ) get_workbench().add_command( "debug_faster", "run", _("Debug current script (faster)"), lambda: _request_debug("FastDebug"), caption="Debug (faster)", tester=_start_debug_enabled, default_sequence="", group=10, ) get_workbench().add_command( "step_over", "run", _("Step over"), lambda: _issue_debugger_command("step_over"), caption=_("Over"), tester=lambda: _debugger_command_enabled("step_over"), default_sequence="", group=30, image="step-over", include_in_toolbar=True, ) get_workbench().add_command( "step_into", "run", _("Step into"), lambda: _issue_debugger_command("step_into"), caption=_("Into"), tester=lambda: _debugger_command_enabled("step_into"), default_sequence="", group=30, image="step-into", include_in_toolbar=True, ) get_workbench().add_command( "step_out", "run", _("Step out"), lambda: _issue_debugger_command("step_out"), caption=_("Out"), tester=lambda: _debugger_command_enabled("step_out"), group=30, image="step-out", include_in_toolbar=True, ) get_workbench().add_command( "resume", "run", RESUME_COMMAND_CAPTION, lambda: _issue_debugger_command("resume"), caption=RESUME_COMMAND_CAPTION, tester=lambda: _debugger_command_enabled("resume"), default_sequence="", group=30, image="resume", include_in_toolbar=not get_workbench().in_simple_mode(), ) get_workbench().add_command( "run_to_cursor", "run", _("Run to cursor"), lambda: _issue_debugger_command("run_to_cursor"), tester=lambda: _debugger_command_enabled("run_to_cursor"), default_sequence=select_sequence("", ""), group=30, image="run-to-cursor", include_in_toolbar=False, ) get_workbench().add_command( "step_back", "run", _("Step back"), lambda: _issue_debugger_command("step_back"), caption=_("Back"), tester=lambda: _debugger_command_enabled("step_back"), default_sequence=select_sequence("", ""), group=30, ) get_workbench().add_view(StackView, _("Stack"), "se") get_workbench().add_view(ExceptionView, _("Exception"), "s") get_workbench().bind("DebuggerResponse", _handle_debugger_progress, True) get_workbench().bind("ToplevelResponse", _handle_toplevel_response, True) get_workbench().bind("debugger_return_response", _handle_debugger_return, True) get_workbench().bind("CommandAccepted", _debug_accepted, True) thonny-3.2.7/thonny/plugins/clean_ui_themes.py0000644000175000017500000003270013611773167022570 0ustar annamaaannamaa00000000000000from typing import Optional from thonny import get_workbench from thonny.misc_utils import running_on_windows from thonny.ui_utils import scale from thonny.workbench import UiThemeSettings def clean( frame_background: str, text_background: str, normal_detail: str, high_detail: str, low_detail: str, normal_foreground: str, high_foreground: str, low_foreground: str, custom_menubar: Optional[ int ] = None, # NB! Should be 1 or 0, not True or False (Tk would convert False to "False") ) -> UiThemeSettings: # https://wiki.tcl.tk/37973 (Changing colors) # https://github.com/tcltk/tk/blob/master/library/ttk/clamTheme.tcl # https://github.com/tcltk/tk/blob/master/generic/ttk/ttkClamTheme.c return { ".": { "configure": { "foreground": normal_foreground, "background": frame_background, "lightcolor": frame_background, "darkcolor": frame_background, "bordercolor": frame_background, "selectbackground": high_detail, "selectforeground": high_foreground, }, "map": { "foreground": [("disabled", low_foreground), ("active", high_foreground)], "background": [("disabled", frame_background), ("active", high_detail)], "selectbackground": [("!focus", low_detail)], "selectforeground": [("!focus", normal_foreground)], }, }, "TNotebook": { # https://github.com/tcltk/tk/blob/master/generic/ttk/ttkNotebook.c "configure": { "bordercolor": normal_detail, "tabmargins": [scale(1), 0, 0, 0], # Margins around tab row } }, "ButtonNotebook.TNotebook": {"configure": {"bordercolor": frame_background}}, "AutomaticNotebook.TNotebook": {"configure": {"bordercolor": frame_background}}, "TNotebook.Tab": { "configure": {"background": frame_background, "bordercolor": normal_detail}, "map": { "background": [ ("selected", normal_detail), ("!selected", "!active", frame_background), ("active", "!selected", high_detail), ], "bordercolor": [("selected", frame_background), ("!selected", normal_detail)], "lightcolor": [("selected", normal_detail), ("!selected", frame_background)], }, }, "Treeview": { "configure": {"background": text_background, "borderwidth": 0, "relief": "flat"}, "map": { "background": [ ("selected", "focus", high_detail), ("selected", "!focus", low_detail), ], "foreground": [ ("selected", "focus", high_foreground), ("selected", "!focus", normal_foreground), ], }, }, "Treeview.Heading": { # https://stackoverflow.com/questions/32051780/how-to-edit-the-style-of-a-heading-in-treeview-python-ttk "configure": { "background": normal_detail, "lightcolor": normal_detail, "borderwidth": 0, }, "map": {"background": [("!active", normal_detail), ("active", normal_detail)]}, }, "TEntry": { "configure": { "fieldbackground": text_background, "lightcolor": normal_detail, "insertcolor": normal_foreground, }, "map": { "background": [("readonly", text_background)], "bordercolor": [], "lightcolor": [("focus", high_detail)], "darkcolor": [], }, }, "TCombobox": { "configure": { "background": text_background, "fieldbackground": text_background, "selectbackground": text_background, "lightcolor": text_background, "darkcolor": text_background, "bordercolor": text_background, "arrowcolor": normal_foreground, "foreground": normal_foreground, "seleftforeground": normal_foreground, # "padding" : [12,2,12,2], }, "map": { "background": [("active", text_background)], "fieldbackground": [], "selectbackground": [], "selectforeground": [], "foreground": [], "arrowcolor": [], }, }, "TScrollbar": { "configure": { "gripcount": 0, "borderwidth": 0, "relief": "flat", "darkcolor": normal_detail, "lightcolor": normal_detail, "bordercolor": text_background, "troughcolor": text_background, # arrowcolor="white" }, "map": { "background": [("!disabled", normal_detail), ("disabled", normal_detail)], "darkcolor": [("!disabled", text_background), ("disabled", text_background)], "lightcolor": [("!disabled", text_background), ("disabled", text_background)], }, }, "Vertical.TScrollbar": { # Remove scrollbar buttons/arrows: "layout": [ ( "Vertical.Scrollbar.trough", { "sticky": "ns", "children": [ ("Vertical.Scrollbar.thumb", {"expand": "1", "sticky": "nswe"}) ], }, ) ] }, "Horizontal.TScrollbar": { # Remove scrollbar buttons/arrows: "layout": [ ( "Horizontal.Scrollbar.trough", { "sticky": "we", "children": [ ("Horizontal.Scrollbar.thumb", {"expand": "1", "sticky": "nswe"}) ], }, ) ], "map": { # Make disabled Hor Scrollbar invisible "background": [("disabled", frame_background), ("!disabled", normal_detail)], "troughcolor": [("disabled", frame_background)], "bordercolor": [("disabled", frame_background)], "darkcolor": [("disabled", frame_background)], "lightcolor": [("disabled", frame_background)], }, }, "TButton": { "configure": {"background": normal_detail, "foreground": normal_foreground}, "map": { "foreground": [("disabled", low_foreground), ("alternate", high_foreground)], "background": [("pressed", low_detail), ("active", high_detail)], "bordercolor": [("alternate", high_detail)], }, }, "TCheckbutton": { "configure": { "indicatorforeground": normal_foreground, "indicatorbackground": text_background, }, "map": { "indicatorforeground": [ ("disabled", "alternate", low_foreground), ("disabled", low_foreground), ] }, }, "TRadiobutton": { "configure": { "indicatorforeground": normal_foreground, "indicatorbackground": text_background, }, "map": { "indicatorforeground": [ ("disabled", "alternate", low_foreground), ("disabled", low_foreground), ] }, }, "Toolbutton": { "configure": {"background": frame_background}, "map": {"background": [("disabled", frame_background), ("active", high_detail)]}, }, "TLabel": {"configure": {"foreground": normal_foreground}}, "Url.TLabel": {"configure": {"foreground": high_foreground}}, "TScale": { "configure": { "background": high_detail, "troughcolor": normal_detail, "lightcolor": high_detail, "darkcolor": high_detail, # "bordercolor" : "red", # "sliderlength" : 40, # "sliderthickness" : 60, "gripcount": 0, }, "map": {"background": [], "troughcolor": []}, }, "TScale.slider": { "configure": { "background": "red", "troughcolor": "yellow", "lightcolor": "green", "darkcolor": "white", # "sliderlength" : 40, # "sliderthickness" : 60, } }, "ViewBody.TFrame": {"configure": {"background": text_background}}, "ViewToolbar.TFrame": {"configure": {"background": normal_detail}}, "ViewToolbar.Toolbutton": {"configure": {"background": normal_detail}}, "ViewTab.TLabel": {"configure": {"background": normal_detail, "padding": [5, 0]}}, "ViewToolbar.TLabel": { "configure": {"background": normal_detail, "padding": [scale(4), 0]} }, "Active.ViewTab.TLabel": { "configure": { "foreground": high_foreground, # "font" : "BoldTkDefaultFont", "background": text_background, } }, "Inactive.ViewTab.TLabel": { "configure": {"foreground": normal_foreground, "font": "UnderlineTkDefaultFont"}, "map": {"background": [("hover", high_detail)]}, }, "Text": {"configure": {"background": text_background, "foreground": normal_foreground}}, "Gutter": {"configure": {"background": low_detail, "foreground": low_foreground}}, "Listbox": { "configure": { "background": text_background, "foreground": normal_foreground, "selectbackground": high_detail, "selectforeground": high_foreground, "disabledforeground": low_foreground, "highlightbackground": normal_detail, "highlightcolor": high_detail, "highlightthickness": 1, } }, "Menubar": { "configure": { # Regular, system-provided Windows menubar doesn't allow changing colors. # custom=True replaces it with a custom-built menubar. "custom": running_on_windows() if custom_menubar is None else custom_menubar, "background": frame_background, "foreground": normal_foreground, "activebackground": normal_foreground, "activeforeground": frame_background, "relief": "flat", } }, "Menu": { "configure": { "background": normal_detail, "foreground": high_foreground, "selectcolor": normal_foreground, # "borderwidth": 0, # Interacts badly with right-clicks in Linux "activebackground": normal_foreground, "activeforeground": frame_background, # "activeborderwidth": 0, # Interacts badly with right-clicks in Linux "relief": "flat", } }, "CustomMenubarLabel.TLabel": { "configure": {"padding": [scale(10), scale(2), 0, scale(15)]} }, } def load_plugin() -> None: dark_images = {"tab-close-active": "tab-close-active-clam-dark"} get_workbench().add_ui_theme( "Clean Dark", "Enhanced Clam", clean( frame_background="#252525", text_background="#2d2d2d", normal_detail="#3D3D3D", high_detail="#6E6E6E", low_detail="#404040", normal_foreground="#9f9f9f", high_foreground="#eeeeee", low_foreground="#595959", ), dark_images, ) get_workbench().add_ui_theme( "Clean Dark Green", "Enhanced Clam", clean( frame_background="#1D291A", text_background="#273627", normal_detail="#2D452F", high_detail="#3C6E40", low_detail="#33402F", normal_foreground="#9E9E9E", high_foreground="#eeeeee", low_foreground="#485C49", ), dark_images, ) get_workbench().add_ui_theme( "Clean Dark Blue", "Enhanced Clam", clean( frame_background="#1A1C29", text_background="#272936", normal_detail="#2D3345", high_detail="#3C436E", low_detail="#2F3640", normal_foreground="#9E9E9E", high_foreground="#eeeeee", low_foreground="#484A5C", ), dark_images, ) get_workbench().add_ui_theme( "Clean Sepia", "Enhanced Clam", clean( frame_background="#E8E7DC", text_background="#F7F6F0", normal_detail="#DEDCC8", high_detail="#eeebe7", low_detail="#D4D0B8", normal_foreground="#222222", high_foreground="#000000", low_foreground="#999999", custom_menubar=0, ), ) thonny-3.2.7/thonny/plugins/thonny_folders.py0000644000175000017500000000133113611773167022475 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- """Adds commands for opening certain Thonny folders""" from thonny import THONNY_USER_DIR, get_workbench from thonny.ui_utils import open_path_in_system_file_manager def load_plugin() -> None: def cmd_open_data_dir(): open_path_in_system_file_manager(THONNY_USER_DIR) def cmd_open_program_dir(): open_path_in_system_file_manager(get_workbench().get_package_dir()) get_workbench().add_command( "open_program_dir", "tools", _("Open Thonny program folder..."), cmd_open_program_dir, group=110, ) get_workbench().add_command( "open_data_dir", "tools", _("Open Thonny data folder..."), cmd_open_data_dir, group=110 ) thonny-3.2.7/thonny/plugins/paren_matcher.py0000644000175000017500000001737513611773167022267 0ustar annamaaannamaa00000000000000import io import token import tokenize from thonny import get_workbench from thonny.codeview import CodeViewText from thonny.shell import ShellText import time _OPENERS = {")": "(", "]": "[", "}": "{"} TOKTYPES = {token.LPAR, token.RPAR, token.LBRACE, token.RBRACE, token.LSQB, token.RSQB} BLANK_LINE_REGEX_STR = r"\n\s*\r?\n" BLANK_LINE_REGEX_STR = r"^\s*$" BLOCK_START_REGEX_STR = r"^\s*(class|def|while|elif|with|try|except|finally) " class ParenMatcher: def __init__(self, text): self.text = text self._update_scheduling_id = None self._delayed_scheduling_id = None self._tokens_cache = {} def schedule_update(self, delay=None): if self._update_scheduling_id is not None: self.text.after_cancel(self._update_scheduling_id) if delay is not None: self._update_scheduling_id = self.text.after(delay, self.perform_update) else: self._update_scheduling_id = self.text.after_idle(self.perform_update) def perform_update(self): try: self.update_highlighting() finally: self._update_scheduled = False def invalidate_token_cache(self): self._tokens_cache = {} def update_highlighting(self): clear_highlighting(self.text) if get_workbench().get_option("view.paren_highlighting"): self._update_highlighting_for_active_range() def _update_highlighting_for_active_range(self): start_index = "1.0" end_index = self.text.index("end") # Try to reduce search range for better performance. index = self._find_block_start("@0,0 linestart", True) if index: start_index = index lower_right = "@%d,%d" % (self.text.winfo_width(), self.text.winfo_height()) index = self._find_block_start(lower_right + " lineend", False) if index: end_index = index self._highlight(start_index, end_index) def _find_block_start(self, start_position, backwards): while True: index = self.text.search( BLOCK_START_REGEX_STR, start_position, regexp=True, backwards=backwards, stopindex="1.0" if backwards else "end", ) if not index: break tags = self.text.tag_names(index) if "string3" in tags or "open_string3" in tags: # not a block start if backwards: start_position = index else: start_position = index + " +1c" else: break return index def _highlight(self, start_index, end_index): stack = [] cursor_row, cursor_col = map(int, self.text.index("insert").split(".")) for t in self._get_paren_tokens(start_index, end_index): if t.string in "([{": stack.append(t) elif not stack: # stack is empty, ie. found a closer without opener close_index = "%d.%d" % (t.start[0], t.end[1]) self.text.tag_add("unclosed_expression", start_index, close_index) break elif stack[-1].string != _OPENERS[t.string]: # incorrect closure opener = stack[-1] open_index = "%d.%d" % opener.start self.text.tag_add("unclosed_expression", open_index, end_index) break else: # found a pair opener = stack[-1] closer = t # if cursor is right after opener or closer then highlight both if ( cursor_row == opener.start[0] and cursor_col == opener.end[1] or cursor_row == closer.start[0] and cursor_col == closer.end[1] ): self.text.tag_add("surrounding_parens", "%d.%d" % closer.start) self.text.tag_add("surrounding_parens", "%d.%d" % opener.start) stack.pop() if stack: # something was left without closure opener = stack[-1] open_index = "%d.%d" % opener.start self.text.tag_add("unclosed_expression", open_index, end_index) def _get_paren_tokens(self, start_index, end_index): if (start_index, end_index) in self._tokens_cache: return self._tokens_cache[(start_index, end_index)] start_row, start_col = map(int, start_index.split(".")) source = self.text.get(start_index, end_index) # prepend source with empty lines and spaces to make # token rows and columns match with widget indices source = ("\n" * (start_row - 1)) + (" " * start_col) + source result = [] try: tokens = tokenize.tokenize(io.BytesIO(source.encode("utf-8")).readline) for token in tokens: # if token.string != "" and token.string in "()[]{}": if token.exact_type in TOKTYPES: result.append(token) except Exception: # happens eg when parens are unbalanced or there is indentation error or ... pass if start_index == "1.0" and end_index == "end": self._tokens_cache[(start_index, end_index)] = result return result class ShellParenMatcher(ParenMatcher): def _update_highlighting_for_active_range(self): # TODO: check that cursor is in this range index_parts = self.text.tag_prevrange("command", "end") if index_parts: start_index, end_index = index_parts self._highlight(start_index, end_index) def _update_highlighting(event, text_changed, need_update, delay=None): text = event.widget if not hasattr(text, "paren_matcher"): if isinstance(text, CodeViewText): text.paren_matcher = ParenMatcher(text) elif isinstance(text, ShellText): text.paren_matcher = ShellParenMatcher(text) else: return if text_changed: text.paren_matcher.invalidate_token_cache() if need_update: text.paren_matcher.schedule_update(delay) def update_highlighting_full(event): _update_highlighting(event, True, True) def clear_highlighting(text): text.tag_remove("surrounding_parens", "0.1", "end") text.tag_remove("unclosed_expression", "0.1", "end") _last_move_time = 0 def update_highlighting_move(event): global _last_move_time # needs delay because selecting with mouse causes many events # and I don't know how to distinguish selection from other moves t = time.time() if t - _last_move_time > 0.1: delay = None else: delay = 300 _last_move_time = t _update_highlighting(event, False, True, delay=delay) def update_highlighting_edit_cw(event): if isinstance(event.text_widget, CodeViewText): event.widget = event.text_widget trivial = event.get("trivial_for_parens", False) _update_highlighting(event, True, not trivial) if trivial: event.text_widget.tag_remove("surrounding_parens", "0.1", "end") def load_plugin() -> None: wb = get_workbench() wb.set_default("view.paren_highlighting", True) wb.bind("TextInsert", update_highlighting_edit_cw, True) wb.bind("TextDelete", update_highlighting_edit_cw, True) wb.bind_class("CodeViewText", "<>", update_highlighting_move, True) wb.bind_class("CodeViewText", "<>", update_highlighting_move, True) wb.bind_class("ShellText", "<>", update_highlighting_full, True) wb.bind_class("ShellText", "<>", update_highlighting_full, True) wb.bind("<>", update_highlighting_full, True) thonny-3.2.7/thonny/plugins/circuitpython/0000755000175000017500000000000013611777205021771 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/circuitpython/__init__.py0000644000175000017500000000346213611773167024112 0ustar annamaaannamaa00000000000000import os.path import tkinter as tk from tkinter import ttk from thonny.plugins.micropython import ( MicroPythonProxy, MicroPythonConfigPage, add_micropython_backend, ) from thonny import get_workbench from thonny.ui_utils import create_url_label, show_dialog, askopenfilename import threading from tkinter.messagebox import showinfo from thonny.misc_utils import list_volumes class CircuitPythonProxy(MicroPythonProxy): @property def known_usb_vids_pids(self): """Copied from https://github.com/mu-editor/mu/blob/master/mu/modes/adafruit.py""" return { (0x239A, 0x8015), # Adafruit Feather M0 CircuitPython (0x239A, 0x8023), # Adafruit Feather M0 Express CircuitPython (0x239A, 0x801B), # Adafruit Feather M0 Express CircuitPython (0x239A, 0x8014), # Adafruit Metro M0 CircuitPython (0x239A, 0x8019), # Adafruit CircuitPlayground Express CircuitPython (0x239A, 0x801D), # Adafruit Gemma M0 (0x239A, 0x801F), # Adafruit Trinket M0 (0x239A, 0x8012), # Adafruit ItsyBitsy M0 (0x239A, 0x8021), # Adafruit Metro M4 (0x239A, 0x8025), # Adafruit Feather RadioFruit (0x239A, 0x8026), # Adafruit Feather M4 (0x239A, 0x8028), # Adafruit pIRKey M0 (0x239A, 0x802A), # Adafruit Feather 52840 (0x239A, 0x802C), # Adafruit Itsy M4 (0x239A, 0x802E), # Adafruit CRICKit M0 } class CircuitPythonConfigPage(MicroPythonConfigPage): def _get_usb_driver_url(self): return "https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython" def load_plugin(): add_micropython_backend( "CircuitPython", CircuitPythonProxy, _("CircuitPython (generic)"), CircuitPythonConfigPage ) thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/0000755000175000017500000000000013611777205023762 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/os.py0000644000175000017500000000051213611773167024756 0ustar annamaaannamaa00000000000000def chdir(): pass def getcwd(): pass def listdir(): pass def mkdir(): pass def remove(): pass def rename(): pass def rmdir(): pass sep = "/" def stat(): pass def statvfs(): pass def sync(): pass def uname(): pass def unlink(): pass def urandom(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/pulseio.py0000644000175000017500000000051113611773167026014 0ustar annamaaannamaa00000000000000class PWMOut: "" class PulseIn: "" def clear(): pass def deinit(): pass maxlen = None def pause(): pass paused = None def popleft(): pass def resume(): pass class PulseOut: "" def deinit(): pass def send(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/audiobusio.py0000644000175000017500000000050513611773167026502 0ustar annamaaannamaa00000000000000class I2SOut: "" def deinit(): pass def pause(): pass paused = None def play(): pass playing = None def resume(): pass def stop(): pass class PDMIn: "" def deinit(): pass def record(): pass sample_rate = None thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/random.py0000644000175000017500000000026513611773167025622 0ustar annamaaannamaa00000000000000def choice(): pass def getrandbits(): pass def randint(): pass def random(): pass def randrange(): pass def seed(): pass def uniform(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/rtc.py0000644000175000017500000000013713611773167025130 0ustar annamaaannamaa00000000000000class RTC: "" calibration = None datetime = None def set_time_source(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/errno.py0000644000175000017500000000016113611773167025462 0ustar annamaaannamaa00000000000000EACCES = 13 EAGAIN = 11 EEXIST = 17 EINVAL = 22 EIO = 5 EISDIR = 21 ENODEV = 19 ENOENT = 2 ENOMEM = 12 EPERM = 1 thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/ustruct.py0000644000175000017500000000020313611773167026043 0ustar annamaaannamaa00000000000000def calcsize(): pass def pack(): pass def pack_into(): pass def unpack(): pass def unpack_from(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/samd.py0000644000175000017500000000016313611773167025263 0ustar annamaaannamaa00000000000000def disable_autoreload(): pass def enable_autoreload(): pass def set_rgb_status_brightness(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/neopixel_write.py0000644000175000017500000000003713611773167027374 0ustar annamaaannamaa00000000000000def neopixel_write(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/time.py0000644000175000017500000000036713611773167025303 0ustar annamaaannamaa00000000000000def localtime(): pass def mktime(): pass def monotonic(): pass def monotonic_ns(): pass def sleep(): pass class struct_time: "" def count(): pass def index(): pass def time(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/nvm.py0000644000175000017500000000003013611773167025130 0ustar annamaaannamaa00000000000000class ByteArray: "" thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/re.py0000644000175000017500000000015613611773167024747 0ustar annamaaannamaa00000000000000DEBUG = 4096 def compile(): pass def match(): pass def search(): pass def sub(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/supervisor.py0000644000175000017500000000030413611773167026555 0ustar annamaaannamaa00000000000000def disable_autoreload(): pass def enable_autoreload(): pass def reload(): pass runtime = None def set_next_stack_limit(): pass def set_rgb_status_brightness(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/usb_hid.py0000644000175000017500000000016313611773167025754 0ustar annamaaannamaa00000000000000class Device: "" def send_report(): pass usage = None usage_page = None devices = None thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/gc.py0000644000175000017500000000000613611773167024724 0ustar annamaaannamaa00000000000000# ... thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/builtins.py0000644000175000017500000001346013611773167026174 0ustar annamaaannamaa00000000000000class ArithmeticError: "" class AssertionError: "" class AttributeError: "" class BaseException: "" class EOFError: "" Ellipsis = None class Exception: "" class GeneratorExit: "" class ImportError: "" class IndentationError: "" class IndexError: "" class KeyError: "" class KeyboardInterrupt: "" class LookupError: "" class MemoryError: "" class MpyError: "" class NameError: "" class NotImplementedError: "" class OSError: "" class OverflowError: "" class ReloadException: "" class RuntimeError: "" class StopIteration: "" class SyntaxError: "" class SystemExit: "" class TypeError: "" class UnicodeError: "" class ValueError: "" class ZeroDivisionError: "" def abs(): pass def all(): pass def any(): pass def bin(): pass class bool: "" class bytearray: "" def append(): pass def extend(): pass class bytes: "" def center(): pass def count(): pass def decode(): pass def endswith(): pass def find(): pass def format(): pass def index(): pass def isalpha(): pass def isdigit(): pass def islower(): pass def isspace(): pass def isupper(): pass def join(): pass def lower(): pass def lstrip(): pass def partition(): pass def replace(): pass def rfind(): pass def rindex(): pass def rpartition(): pass def rsplit(): pass def rstrip(): pass def split(): pass def splitlines(): pass def startswith(): pass def strip(): pass def upper(): pass def callable(): pass def chr(): pass class classmethod: "" class complex: "" def delattr(): pass class dict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass def dir(): pass def divmod(): pass class enumerate: "" def eval(): pass def exec(): pass class filter: "" class float: "" class frozenset: "" def copy(): pass def difference(): pass def intersection(): pass def isdisjoint(): pass def issubset(): pass def issuperset(): pass def symmetric_difference(): pass def union(): pass def getattr(): pass def globals(): pass def hasattr(): pass def hash(): pass def help(): pass def hex(): pass def id(): pass def input(): pass class int: "" def from_bytes(): pass def to_bytes(): pass def isinstance(): pass def issubclass(): pass def iter(): pass def len(): pass class list: "" def append(): pass def clear(): pass def copy(): pass def count(): pass def extend(): pass def index(): pass def insert(): pass def pop(): pass def remove(): pass def reverse(): pass def sort(): pass def locals(): pass class map: "" def max(): pass class memoryview: "" def min(): pass def next(): pass class object: "" def oct(): pass def open(): pass def ord(): pass def pow(): pass def print(): pass class property: "" def deleter(): pass def getter(): pass def setter(): pass class range: "" def repr(): pass class reversed: "" def round(): pass class set: "" def add(): pass def clear(): pass def copy(): pass def difference(): pass def difference_update(): pass def discard(): pass def intersection(): pass def intersection_update(): pass def isdisjoint(): pass def issubset(): pass def issuperset(): pass def pop(): pass def remove(): pass def symmetric_difference(): pass def symmetric_difference_update(): pass def union(): pass def update(): pass def setattr(): pass class slice: "" def sorted(): pass class staticmethod: "" class str: "" def center(): pass def count(): pass def encode(): pass def endswith(): pass def find(): pass def format(): pass def index(): pass def isalpha(): pass def isdigit(): pass def islower(): pass def isspace(): pass def isupper(): pass def join(): pass def lower(): pass def lstrip(): pass def partition(): pass def replace(): pass def rfind(): pass def rindex(): pass def rpartition(): pass def rsplit(): pass def rstrip(): pass def split(): pass def splitlines(): pass def startswith(): pass def strip(): pass def upper(): pass def sum(): pass class super: "" class tuple: "" def count(): pass def index(): pass class type: "" class zip: "" thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/digitalio.py0000644000175000017500000000062113611773167026303 0ustar annamaaannamaa00000000000000class DigitalInOut: "" def deinit(): pass direction = None drive_mode = None pull = None def switch_to_input(): pass def switch_to_output(): pass value = None class Direction: "" INPUT = None OUTPUT = None class DriveMode: "" OPEN_DRAIN = None PUSH_PULL = None class Pull: "" DOWN = None UP = None thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/analogio.py0000644000175000017500000000026213611773167026130 0ustar annamaaannamaa00000000000000class AnalogIn: "" def deinit(): pass reference_voltage = None value = None class AnalogOut: "" def deinit(): pass value = None thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/rotaryio.py0000644000175000017500000000012613611773167026206 0ustar annamaaannamaa00000000000000class IncrementalEncoder: "" def deinit(): pass position = None thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/busio.py0000644000175000017500000000165513611773167025467 0ustar annamaaannamaa00000000000000class I2C: "" def deinit(): pass def readfrom_into(): pass def scan(): pass def try_lock(): pass def unlock(): pass def writeto(): pass class OneWire: "" def deinit(): pass def read_bit(): pass def reset(): pass def write_bit(): pass class SPI: "" def configure(): pass def deinit(): pass frequency = None def readinto(): pass def try_lock(): pass def unlock(): pass def write(): pass def write_readinto(): pass class UART: "" Parity = None baudrate = None def deinit(): pass in_waiting = None def read(): pass def readinto(): pass def readline(): pass def reset_input_buffer(): pass def write(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/board.py0000644000175000017500000000132513611773167025427 0ustar annamaaannamaa00000000000000A0 = None A1 = None A2 = None A3 = None A4 = None A5 = None A6 = None A7 = None A8 = None A9 = None ACCELEROMETER_INTERRUPT = None ACCELEROMETER_SCL = None ACCELEROMETER_SDA = None BUTTON_A = None BUTTON_B = None D0 = None D1 = None D10 = None D12 = None D13 = None D2 = None D3 = None D4 = None D5 = None D6 = None D7 = None D8 = None D9 = None def I2C(): pass IR_PROXIMITY = None IR_RX = None IR_TX = None LIGHT = None MICROPHONE_CLOCK = None MICROPHONE_DATA = None MISO = None MOSI = None NEOPIXEL = None REMOTEIN = None REMOTEOUT = None RX = None SCK = None SCL = None SDA = None SLIDE_SWITCH = None SPEAKER = None SPEAKER_ENABLE = None def SPI(): pass TEMPERATURE = None TX = None def UART(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/touchio.py0000644000175000017500000000016213611773167026010 0ustar annamaaannamaa00000000000000class TouchIn: "" def deinit(): pass raw_value = None threshold = None value = None thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/gamepad.py0000644000175000017500000000013313611773167025732 0ustar annamaaannamaa00000000000000class GamePad: "" def deinit(): pass def get_pressed(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/audioio.py0000644000175000017500000000112313611773167025765 0ustar annamaaannamaa00000000000000class AudioOut: "" def deinit(): pass def pause(): pass paused = None def play(): pass playing = None def resume(): pass def stop(): pass class Mixer: "" def deinit(): pass def play(): pass playing = None sample_rate = None def stop_voice(): pass class RawSample: "" def deinit(): pass sample_rate = None class WaveFile: "" bits_per_sample = None channel_count = None def deinit(): pass sample_rate = None thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/framebuf.py0000644000175000017500000000067513611773167026136 0ustar annamaaannamaa00000000000000class FrameBuffer: "" def blit(): pass def fill(): pass def fill_rect(): pass def hline(): pass def line(): pass def pixel(): pass def rect(): pass def scroll(): pass def text(): pass def vline(): pass def FrameBuffer1(): pass GS4_HMSB = 2 MONO_HLSB = 3 MONO_HMSB = 4 MONO_VLSB = 0 MVLSB = 0 RGB565 = 1 thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/collections.py0000644000175000017500000000003313611773167026651 0ustar annamaaannamaa00000000000000def namedtuple(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/array.py0000644000175000017500000000012413611773167025452 0ustar annamaaannamaa00000000000000class array: "" def append(): pass def extend(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/ucollections.py0000644000175000017500000000003313611773167027036 0ustar annamaaannamaa00000000000000def namedtuple(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/usb_midi.py0000644000175000017500000000023313611773167026130 0ustar annamaaannamaa00000000000000class PortIn: "" def read(): pass def readinto(): pass class PortOut: "" def write(): pass ports = None thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/struct.py0000644000175000017500000000020313611773167025656 0ustar annamaaannamaa00000000000000def calcsize(): pass def pack(): pass def pack_into(): pass def unpack(): pass def unpack_from(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/bitbangio.py0000644000175000017500000000117013611773167026274 0ustar annamaaannamaa00000000000000class I2C: "" def deinit(): pass def readfrom_into(): pass def scan(): pass def try_lock(): pass def unlock(): pass def writeto(): pass class OneWire: "" def deinit(): pass def read_bit(): pass def reset(): pass def write_bit(): pass class SPI: "" def configure(): pass def deinit(): pass def readinto(): pass def try_lock(): pass def unlock(): pass def write(): pass def write_readinto(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/storage.py0000644000175000017500000000111113611773167025775 0ustar annamaaannamaa00000000000000class VfsFat: "" def chdir(): pass def getcwd(): pass def ilistdir(): pass label = None def mkdir(): pass def mkfs(): pass def mount(): pass def open(): pass def remove(): pass def rename(): pass def rmdir(): pass def stat(): pass def statvfs(): pass def umount(): pass def erase_filesystem(): pass def getmount(): pass def mount(): pass def remount(): pass def umount(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/micropython.py0000644000175000017500000000020713611773167026711 0ustar annamaaannamaa00000000000000def const(): pass def heap_lock(): pass def heap_unlock(): pass def kbd_intr(): pass def opt_level(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/microcontroller.py0000644000175000017500000000057713611773167027565 0ustar annamaaannamaa00000000000000class Pin: "" class Processor: "" frequency = None temperature = None uid = None class RunMode: "" BOOTLOADER = None NORMAL = None SAFE_MODE = None cpu = None def delay_us(): pass def disable_interrupts(): pass def enable_interrupts(): pass nvm = None def on_next_reset(): pass pin = None def reset(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/ure.py0000644000175000017500000000013013611773167025124 0ustar annamaaannamaa00000000000000DEBUG = 4096 def compile(): pass def match(): pass def search(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/neopixel.py0000644000175000017500000000047413611773167026167 0ustar annamaaannamaa00000000000000GRB = None GRBW = None class NeoPixel: "" def _set_item(): pass brightness = None def deinit(): pass def fill(): pass def show(): pass def write(): pass RGB = None RGBW = None digitalio = None math = None def neopixel_write(): pass thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/sys.py0000644000175000017500000000041513611773167025155 0ustar annamaaannamaa00000000000000argv = None byteorder = "little" def exit(): pass implementation = None maxsize = 2147483647 modules = None path = None platform = "Atmel SAMD21" def print_exception(): pass stderr = None stdin = None stdout = None version = "3.4.0" version_info = None thonny-3.2.7/thonny/plugins/circuitpython/api_stubs/math.py0000644000175000017500000000115113611773167025266 0ustar annamaaannamaa00000000000000def acos(): pass def asin(): pass def atan(): pass def atan2(): pass def ceil(): pass def copysign(): pass def cos(): pass def degrees(): pass e = 2.71828 def exp(): pass def fabs(): pass def floor(): pass def fmod(): pass def frexp(): pass def isfinite(): pass def isinf(): pass def isnan(): pass def ldexp(): pass def log(): pass def modf(): pass pi = 3.14159 def pow(): pass def radians(): pass def sin(): pass def sqrt(): pass def tan(): pass def trunc(): pass thonny-3.2.7/thonny/plugins/pgzero_frontend.py0000644000175000017500000000127513611773167022654 0ustar annamaaannamaa00000000000000import os from thonny import get_workbench _OPTION_NAME = "run.pgzero_mode" def toggle_variable(): var = get_workbench().get_variable(_OPTION_NAME) var.set(not var.get()) update_environment() def update_environment(): if get_workbench().in_simple_mode(): os.environ["PGZERO_MODE"] = "auto" else: os.environ["PGZERO_MODE"] = str(get_workbench().get_option(_OPTION_NAME)) def load_plugin(): get_workbench().set_default(_OPTION_NAME, False) get_workbench().add_command( "toggle_pgzero_mode", "run", _("Pygame Zero mode"), toggle_variable, flag_name=_OPTION_NAME, group=40, ) update_environment() thonny-3.2.7/thonny/plugins/pi/0000755000175000017500000000000013611777205017475 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/pi/__init__.py0000644000175000017500000002603113611773167021613 0ustar annamaaannamaa00000000000000import os import re from thonny import get_workbench from thonny.ui_utils import scale DESKTOP_SESSION = os.environ.get("DESKTOP_SESSION", "_") CONFIGURATION_PATH = os.path.join( os.path.expanduser("~"), ".config/lxsession", DESKTOP_SESSION, "desktop.conf" ) GLOBAL_CONFIGURATION_PATH = os.path.join("/etc/xdg/lxsession", DESKTOP_SESSION, "desktop.conf") def pix(): MAIN_BACKGROUND = "#ededed" res_dir = os.path.join(os.path.dirname(__file__), "res") scrollbar_button_settings = {} for direction, element_name in [ ("up", "Vertical.Scrollbar.uparrow"), ("down", "Vertical.Scrollbar.downarrow"), ("left", "Horizontal.Scrollbar.leftarrow"), ("right", "Horizontal.Scrollbar.rightarrow"), ]: # load the image img_name = "scrollbar-button-" + direction for suffix in ["", "-insens"]: get_workbench().get_image( os.path.join(res_dir, img_name + suffix + ".png"), img_name + suffix ) scrollbar_button_settings[element_name] = { "element create": ( "image", img_name, ("!disabled", img_name), ("disabled", img_name + "-insens"), ) } settings = { ".": {"configure": {"background": MAIN_BACKGROUND}}, "Toolbutton": { "configure": {"borderwidth": 1}, "map": { "relief": [("disabled", "flat"), ("hover", "groove"), ("!hover", "flat")], "background": [ ("disabled", MAIN_BACKGROUND), ("!hover", MAIN_BACKGROUND), ("hover", "#ffffff"), ], }, }, "Treeview.Heading": { "configure": { "background": "#f0f0f0", "foreground": "#808080", "relief": "flat", "borderwidth": 1, }, "map": {"foreground": [("active", "black")]}, }, "TNotebook.Tab": { "map": {"background": [("!selected", "#d0d0d0"), ("selected", MAIN_BACKGROUND)]} }, "ButtonNotebook.TNotebook.Tab": { "map": { "background": [("!selected", "#d0d0d0"), ("selected", MAIN_BACKGROUND)], "padding": [ ("selected", [scale(4), scale(2), scale(4), scale(3)]), ("!selected", [scale(4), scale(2), scale(4), scale(3)]), ], } }, "TScrollbar": { "configure": { "gripcount": 0, "borderwidth": 0, "padding": scale(1), "relief": "solid", "background": "#9e9e9e", "darkcolor": "#d6d6d6", "lightcolor": "#d6d6d6", "bordercolor": "#d6d6d6", "troughcolor": "#d6d6d6", "arrowsize": scale(1), "arrowcolor": "gray", }, "map": {"background": [], "darkcolor": [], "lightcolor": []}, }, # Padding allows twaking thumb width "Vertical.TScrollbar": { "layout": [ ( "Vertical.Scrollbar.trough", { "sticky": "ns", "children": [ ("Vertical.Scrollbar.uparrow", {"side": "top", "sticky": ""}), ("Vertical.Scrollbar.downarrow", {"side": "bottom", "sticky": ""}), ( "Vertical.Scrollbar.padding", { "sticky": "nswe", "children": [ ( "Vertical.Scrollbar.thumb", {"expand": 1, "sticky": "nswe"}, ) ], }, ), ], }, ) ] }, "Horizontal.TScrollbar": { "layout": [ ( "Horizontal.Scrollbar.trough", { "sticky": "we", "children": [ ("Horizontal.Scrollbar.leftarrow", {"side": "left", "sticky": ""}), ("Horizontal.Scrollbar.rightarrow", {"side": "right", "sticky": ""}), ( "Horizontal.Scrollbar.padding", { "sticky": "nswe", "children": [ ( "Horizontal.Scrollbar.thumb", {"expand": 1, "sticky": "nswe"}, ) ], }, ), ], }, ) ], "map": { # Make disabled Hor Scrollbar invisible "background": [("disabled", "#d6d6d6")], "troughcolor": [("disabled", "#d6d6d6")], "bordercolor": [("disabled", "#d6d6d6")], "darkcolor": [("disabled", "#d6d6d6")], "lightcolor": [("disabled", "#d6d6d6")], }, }, "TCombobox": {"configure": {"arrowsize": scale(10)}}, "Menubar": { "configure": { "background": MAIN_BACKGROUND, "relief": "flat", "activebackground": "#ffffff", "activeborderwidth": 0, } }, "Menu": { "configure": { "background": "#ffffff", "relief": "flat", "borderwidth": 1, "activeborderwidth": 0, # "activebackground" : bg, # updated below # "activeforeground" : fg, } }, "Tooltip": { "configure": { "background": "#808080", "foreground": "#ffffff", "borderwidth": 0, "padx": 10, "pady": 10, } }, "OPTIONS": {"configure": {"icons_in_menus": False, "shortcuts_in_tooltips": False}}, } settings.update(scrollbar_button_settings) # try to refine settings according to system configuration """Note that fonts are set globally, ie. all themes will later inherit these""" update_fonts() for path in [GLOBAL_CONFIGURATION_PATH, CONFIGURATION_PATH]: if os.path.exists(path): with open(path) as fp: for line in fp: if "sGtk/ColorScheme" in line: if "selected_bg_color" in line: bgr = re.search(r"selected_bg_color:#([0-9a-fA-F]*)", line, re.M).group( 1 ) # @UndefinedVariable color = "#" + bgr[0:2] + bgr[4:6] + bgr[8:10] if is_good_color(color): settings["Menu"]["configure"]["activebackground"] = color if "selected_fg_color" in line: fgr = re.search(r"selected_fg_color:#([0-9a-fA-F]*)", line, re.M).group( 1 ) # @UndefinedVariable color = "#" + fgr[0:2] + fgr[4:6] + fgr[8:10] if is_good_color(color): settings["Menu"]["configure"]["activeforeground"] = color return settings def is_good_color(s): return bool(re.match("^#[0-9a-fA-F]{6}$", s)) def pix_dark(): update_fonts() return {} def update_fonts(): from tkinter import font options = {} for path in [GLOBAL_CONFIGURATION_PATH, CONFIGURATION_PATH]: if os.path.exists(path): with open(path) as fp: for line in fp: if "sGtk/FontName" in line: result = re.search(r"=([^0-9]*) ([0-9]*)", line, re.M) # @UndefinedVariable family = result.group(1) options["size"] = int(result.group(2)) if re.search(r"\bBold\b", family): options["weight"] = "bold" else: options["weight"] = "normal" if re.search(r"\bItalic\b", family): options["slant"] = "italic" else: options["slant"] = "roman" options["family"] = family.replace(" Bold", "").replace(" Italic", "") if options: for name in ["TkDefaultFont", "TkMenuFont", "TkTextFont", "TkHeadingFont"]: font.nametofont(name).configure(**options) def load_plugin(): # set custom images if get_workbench().get_ui_mode() == "simple" and get_workbench().winfo_screenwidth() >= 1280: images = { "run-current-script": "media-playback-start48.png", "stop": "process-stop48.png", "new-file": "document-new48.png", "open-file": "document-open48.png", "save-file": "document-save48.png", "debug-current-script": "debug-run48.png", "step-over": "debug-step-over48.png", "step-into": "debug-step-into48.png", "step-out": "debug-step-out48.png", "run-to-cursor": "debug-run-cursor48.png", "tab-close": "window-close.png", "tab-close-active": "window-close-act.png", "resume": "resume48.png", "zoom": "zoom48.png", "quit": "quit48.png", } else: images = { "run-current-script": "media-playback-start.png", "stop": "process-stop.png", "new-file": "document-new.png", "open-file": "document-open.png", "save-file": "document-save.png", "debug-current-script": "debug-run.png", "step-over": "debug-step-over.png", "step-into": "debug-step-into.png", "step-out": "debug-step-out.png", "run-to-cursor": "debug-run-cursor.png", "tab-close": "window-close.png", "tab-close-active": "window-close-act.png", "resume": "resume.png", "zoom": "zoom.png", "quit": "quit.png", } res_dir = os.path.join(os.path.dirname(__file__), "res") theme_image_map = {} for image in images: theme_image_map[image] = os.path.join(res_dir, images[image]) get_workbench().add_ui_theme("Raspberry Pi", "Enhanced Clam", pix, theme_image_map) get_workbench().add_ui_theme("Raspberry Pi Dark", "Clean Dark", pix_dark, theme_image_map) thonny-3.2.7/thonny/plugins/pi/res/0000755000175000017500000000000013611777205020266 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/pi/res/_disabled_scrollbar-button-left.png0000644000175000017500000000031713611773167027212 0ustar annamaaannamaa00000000000000PNG  IHDR w&IDATx 0EEP#Xx (VjJg*#! :bEk͚9pڵ:֚b#"}G^IH/CZw7 $Tu`[WS]%lup<=H4(wFMW=IENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_resume.png0000644000175000017500000000215513611773167024270 0ustar annamaaannamaa00000000000000PNG  IHDR szz4IDATxW[SF=-y%И0$\J)$}HK7>iRdR2%10 ޵,Y[X3=oӞ [\\X-  6dqLܒٱG2]y)-Lcz,ɧ3,*`aħ'.\QXRy] qģ >ueVRƀ@Y6b]Tw$w bO#n >}l#*_Tt5a\-x*<w _ֶEC O1;vsr`7G3}|6kg=lq-̇]v&z׵; uf,}הǃ$7IԪ#`qLO:ܺciCgV|( c)B_+_C^Ä`VŴض0ƒ|Rqo>T@3->UB-fvGrDYFC3bHNBL?'K`P@ !i8sH ^'8BGO7D͖[6왗0ǟ jpg=C[psX<=̬0]> #K !vg82Eg%v;kEi-~]{B@Ir݆,p!>bT 5ʹUw#J |zPEm@C.v49|Rwp߂JӼ=P).Rpe4Ժ*>T Jkn@(zvi 'd,jUx @6]TNPۭP$}8RlXzvsvsy|t, eM;%JJNSFTjkLgoːq^!dnvBЛS+6UtAp52Wc T(S4Ⱦ:qP֔9 ~,jG T$K8Kb̈́;ۥ܀HVZ6}܂+=?dT`\wI\ ˆXH< XyN폳A^! @ ħCW# J%!v [{݊IENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_debug-run-cursor.png0000644000175000017500000000276513611773167026202 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxݗoT{\l5S础U"!Ed$G >Ї*BRZB==Ks{af܁K#!~ґ^{^֚Q׮]MBQ=$P.SSSSjnzz@u*tg mtͧu\d6Z{͛7D$a驩 @0p pȑJ8ƘV(4ju| .sӗ/_yid2d2="B9}01rNLL_Vֻlm[d2sҥrʇFc+nZT*!̭[>} ^&a;κH`W/}eQ===:ucPQ.Ca#Ν{.ǏGDT'ZfIRa{{jJ\REk-Z1aݻN $P(>-JQgZ18x i4c N~g?~rpp&J)@!"6Y|͵2J4&Q8q]/G?P \X*4ƼEJ)18& >%LH,6xV3XZe{ yvٟF7WUJ<}hE)ED/m [``9B"_njDQZk_HD@AA,(b)Wu5/s|7kmT+vZABXT`P"V0L؊1MZ$(Dkwf嵛\X@:"DiVQ (ba<[uj#@$Z{_;%=ХRiP(;?TJa7ñw]ĩ*n|'Q84`ዥOZLykͭ"]֞)輬/lllAE#;@q\qPJl6Z'm4s|!b_^Μ9󓾾>Sc)wR+z^!"+Z~`E[Syd2i<<qQZʦMmZhbԩ1b;wl6Ek-F>} к8CVcaakK=l?GvϞ={avvvjvv\.O몙9D">+;mLӛ]b[Z딈f}}ߴT,//cɤq }L&;zx%[]]] WJicLtPW^LNNWJq ,--=YZZzrX]P@Jk1u;mSW)Z s=W!=V ]{~v!IENDB`thonny-3.2.7/thonny/plugins/pi/res/document-save48.png0000644000175000017500000000230713611773167023727 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDAThYMOW=M%X :(" e*]8(R%J!JB@%6%ӊE#IQ XB IdEj2B ǘ[Ø|Eͽwμ;g1 m P%b~BZ[[jMVCݻ։:߼_5@֡AEZNV (4g 3J0bJy;ƚe ,gkk \5s Cc~WUeCIxDt>?~?EjlFd*oMyjrl6I3x3v/,+parr_n޼Y"byy+++x5JK@ pa~~;WGDFr6!+*>cB:^J TWWRQC<|eeb1< mmwPP'(l==?ʎ}g\L& Y<˗X\+U >E*R6NNmV4MUG^ Z 5P@QE_V8v>/L4EEvw>E(F{{B.,& Lbbb--_fe~?FGGpRlGAo=t: ՊÕˍrhu,gN bj]077i;woZ4Ml6#[5!}}9z={122WB !@\.\ `X o!#`co0Y1ɥ477 HR}%c'`ss;;;slF>Mb18K=!&b1^yekaaH$D߼hPu[@*:$ *^  FNdVHD>>tC)lطعEJ9MԱlg;%n*Ś[Υ" XP_||yo^QFd꟥G!$o, XeWTrdI4ʶ?̩݊vA%`PwL*XT8t {- NԱlG_tbg)ʖoq2sqAawэ{~i@84ԔNnn{\m9dړU,ܒU{D'`o'`z涧`;F奸׻Ezr8.`kOTuzt:hx1Cd\:u 2Y]'%>"+H /+Xr`V14{Í8ZHx鉙%+,pzglmUzbནIM'%gD8Xq;zY "(^wMHb`7FbP#MADIe* 0jN*F`pBC1nNf)yK 3CS`efe%Z19VU 1r$LskР.ãV| kV χ`]?xZ˪ih2e̾&71{\]!yu= ,fDگ9>gӜzU%rlйmRN"DPnI?kЕXNG$䤟?0;+Ki^ ɐ>Jk(_ۗfB|%WDzAC'z2|sߚ!̀*2MI`׬UR)9WZw#>V myRMJ `CZ /IENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_zoom.png0000644000175000017500000000272013611773167023752 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxWKoVHQ~%5MUˑ_I`6ht1hUl)(1Q hcIHЖHQd‘8f[;sxIݺu &u8i:7;+xFh?!M˲j^]p f =55uքvTZ)8w/<ÌvK9j~>{I3mnW7i4MѶfja WU5!H$˗DcRڶ7 ynau]{iP%غnZ 'eYWb$`X gGq,Iʦia,4CH&DZ asuuuyX;:j/KFY]q+++QQmmFX>]1 0 Q.Yϟ?'6}>^t:rq\$A6]hsLgLY|'GK|+rض] =R p]5FŃi&w-?N˵V5 ðtA3v?9( M4Fd`3 }+n7$IJض9pvn+_ 4"h$) i71%,NP 5~8MjBn ˲jcAR( 69ڽ(Q6rȲ|MUOPV^w)!^['lva坝 7l7\011YX[+EA]ອ " kޛLDZxP(b183o҆aR=VO,8(Ǧ9<1;+}k EQ(0 #4mgv4c$Jgit: Ap 4 n6VAx\R UT(4Qa붵a p;;?t@$ K ++W2EQ( `}z4M;Ѵ 86 p||via7l.Yt]TPuq컄x쨳<]r 88ѷxscy,ʲyna,Z\D|nDQϯ%JaX_ @G*ׄx~$ cw]׿~ eItP*~CHj<(jz8wx 8:jntwoo/xW} F;w99 +QwMIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_process-stop48.png0000644000175000017500000000270413611773167025605 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATxՙoGƿufbġ!RK%zKJo?C՗V*Q-6!!I!qev;3}lOΎow|crmeX+';dpxIT  Yo)C D'4λC,H魶݀02rz"uSi FE^~i. Y)=ݬ Dž/]b$r(Dp%cOe>#7\ [ *5x)jُ(S ,j)|#C!ɴ/P|WC)?so5r_]Bсؾ6q0gxf_ 덯i@>:;OӖ 2vt B*5ya %z49 G˯ +BpKzbXmݏ&K5 U~ S7 ]'.]n; \?"@*q6[u~lLαKЋ#ȁc]B9X 8=ɰ|CYq*\x׀kv oK`2X: 5m(0 m` d) (<X 9:B́=V? Bf Vd̩d R@Lj b`πI]"_x;wLPxT.߮\Gf mX֎;0xM5)HD!EVz:\:NEv@Rs0]Rz%+\ Q;ia"KVrs62ẸY;: ݡM{=y/;e\坸2Z=gyX>@)=:!=z۫YO<1R\ I-?s/h!" V gVʯUKM$}h8S>m4hF`FXa /Z-T#XU/p6dG[m P061Tczk1KE -(3` >N"1C ܐkYnnJZ-~L+HIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_document-save.png0000644000175000017500000000126313611773167025541 0ustar annamaaannamaa00000000000000PNG  IHDR szzzIDATxN@?)TQ:"AB}U ޣ$J@7B=] ]pvsu9wG=17mⷭ!xf0s\jj4̩Ɇ> Dpcks9aPT~ٴȀ뻺g:AP,{R&r{-II)|߿}v$t:M:f~~q999+.^3*2aJHRh6f@A^!qϋ_^^|A5 u!Rrpp0 aRbFRE lD<圞 r9L)ys(T&C!pqq2gg&kkXUU) /70(pZ$~iFՁQU8Mf74}m~$ /ȍ7SIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_debug-run-cursor48.png0000644000175000017500000000276513611773167026356 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxݗoT{\l5S础U"!Ed$G >Ї*BRZB==Ks{af܁K#!~ґ^{^֚Q׮]MBQ=$P.SSSSjnzz@u*tg mtͧu\d6Z{͛7D$a驩 @0p pȑJ8ƘV(4ju| .sӗ/_yid2d2="B9}01rNLL_Vֻlm[d2sҥrʇFc+nZT*!̭[>} ^&a;κH`W/}eQ===:ucPQ.Ca#Ν{.ǏGDT'ZfIRa{{jJ\REk-Z1aݻN $P(>-JQgZ18x i4c N~g?~rpp&J)@!"6Y|͵2J4&Q8q]/G?P \X*4ƼEJ)18& >%LH,6xV3XZe{ yvٟF7WUJ<}hE)ED/m [``9B"_njDQZk_HD@AA,(b)Wu5/s|7kmT+vZABXT`P"V0L؊1MZ$(Dkwf嵛\X@:"DiVQ (ba<[uj#@$Z{_;%=ХRiP(;?TJa7ñw]ĩ*n|'Q84`ዥOZLykͭ"]֞)輬/lllAE#;@q\qPJl6Z'm4s|!b_^Μ9󓾾>Sc)wR+z^!"+Z~`E[Syd2i<<qQZʦMmZhbԩ1b;wl6Ek-F>} к8CVcaakK=l?GvϞ={avvvjvv\.O몙9D">+;mLӛ]b[Z딈f}}ߴT,//cɤq }L&;zx%[]]] WJicLtPW^LNNWJq ,--=YZZzrX]P@Jk1u;mSW)Z s=W!=V ]{~v!IENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_document-open48.png0000644000175000017500000000230513611773167025716 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATxZ]S"G=4 |JPT`W2VvѪ< *V*nʐB]`f&YȲ8 Ӹe}ýow?dX]]{M]{UKTB^ss3Z|5OX̅f>铛ƨ/ Pڮ)D^~yFRTb@v!Z-@唋([^Nonr9dIU^|m'Iu()hbJ~BFQlmmeE= `PuvggCƨۀTj,/\;B_cj^8B~"(T* Yqq~v/ :4퓮?W t4/&?F޽899єe9j ; t]GPD"$bטLӄOj% ֍VUUt$Aכ|!h4ޣh@U5lnn nawt:mivqzz QAu$Id2YAJ%\\\<PU f8??wE4*ʼ,Mxp8hԇi`yϵAuN}-1"7&&0 z=d2#1FFÇ?qu\$qKǽ@ dҺ9ڇBK{u]`nf(Sci4",Զuy}>6)bYa4 !z抏kp\rvֶn#H"`0;FC!jci}`|GT,0*rl;o&dY!?V-p]64J +O,6؟C3|9kZKz陪:7(Q 5@j <A2yT\'竽vt\/>R umϳz0{ / ]i/OCGbÇe '!^&N1Cd!!A1:MC= ҋX^9IV ÃF gN:x^n&_Bcy%}؀po;&/̽P_Co%R3 fH(/+*`+dP mUdP )JCШMIENDB`thonny-3.2.7/thonny/plugins/pi/res/window-close.png0000644000175000017500000000077113611773167023416 0ustar annamaaannamaa00000000000000PNG  IHDR(-SsBITO pHYs B(xtEXtSoftwarewww.inkscape.org<PLTEad_`c`__]_a]aa]^`\`c\`d^bd`ac_`b^`b\`b^bd^bd`ac]bd``b^`d^bd^ac__a]`b^ab_ce`bd`cfabd^cfadfa`d_|~yz|vz}w{}w|~y|}~|~y}z}}ļļƾƾË#4tRNSnovvvwwxxyz}}}}~LqIDATc` s(fyQ$TE\OGTGHTa>6>"\UPWT * g! VT* ! ؤ tE*nIENDB`thonny-3.2.7/thonny/plugins/pi/res/document-new.png0000644000175000017500000000067513611773167023414 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATX헽JQ]XH:MFl&h"6N| J,ShJ!Ht aMI2!Ü^vfg!KI{Ć#:wcv(ZS:0=5<(0d6ʐߖ2`JRi 0˽6L] 2w})3b+Ħg ;ӻA JhT5-ST[0n'!/ ;TF 0=\xdr><@ 5zx(2xh/^tc0@[U?uTtkK2 ]ճ%;ϋ&ΟEGsU5 -SAͼUFZw+l_cIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_quit48.png0000644000175000017500000000331513611773167024125 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATxZo~fvov qpxH- *EU|i q[Wb`s3:3p{{wuGv^gw29`3` 0j6 !?99#NN'И5g(l@ ?MO*GB.sf NۉCI]Hvt >XB\J Cں2{ީ-;cxdrĆ7:ep6'|Xf8g5ː[wl&. to+EN*/HB7s69? |+lcÓCs6Q_WsC1mF0V9g(svn*qn6 Xv@Cn"rp&'sZXE-!5Mb=S&7YmD[$I>ES ]IC&?ːZ9eE>E GAnd3\Tu뗀G?斀< y8  0Aوq:v'rsvh{3f+b/뗀SG5 `frI\x^圵ٽKhbTe#>-'bfgɷrX 8LkyЋӉyr?./*"<8^l-9;~*qn": 8*#ceJhwɯхoสtz#ja]0[\)'Ji!'k8gG bqelZD>!mF9B(z ʈ@/`HS0`-]BCCǠrA h;sMQOI`6}=EKFFw~nh RILtVb*Sxb$ +p Oѯq+`NKo4P|~D` AU5Tr{E 4=R*Jٱ~Z^2ij=۱B 1+kV\h+{4"fgV3ޟÙb""*e1,;o~!Xs9n"Wfr ׄoҲ6GT rDS<#(b:ď*F4I4gՕ Dd";\𤵼Mo  ( ]!DV C}?]7y}JvnR0!e倫sDGiY=/FV 4'/oت BILB8 /w?EAA^1 "s!d&7BnnS+/"׮DY׮c> |I?}?@(ܯ`? !M $4BT}vZ~M }[ߨi7@L׮4Bh;tw1vZ6(|J)|×V;8xlxbG_+ӿAra/Օ' Ƶ kcՎJ+!dO~O'Mo `9ltՊޱ@&GudXS3UCt$ hlSlQJ<\t T1oW Q~Fg![B>v k! ZK_IENDB`thonny-3.2.7/thonny/plugins/pi/res/debug-run48.png0000644000175000017500000000217613611773167023051 0ustar annamaaannamaa00000000000000PNG  IHDR00WEIDAThՙ]L[e-YYb) ;͏+g fdem&~`bQ]57q3f1]l%ܦb^,0Q\KG; tS9ZNjy9nr I l[L$%I:G~77ez z A, Œ0cmc3Ui$STt>o؜%~ ,=d g($h? `*HW`<\ ̊c˚I`2L\[g.[Ofj1׭~ݲekKҴ15+PYk~J<Ԕ3;|6`[E1ߧXjA>SYΆZFcAExV-0P\Hq.bޔ /w[~TfaoC4?tZdhh%cG:ĺLt9Iv&K7cOx^Oc^<M pՇ,n3~ae:_j`Շz س Mɀێ(}ʋ\O4F{ `2e- N툒*JU.'_ު[*ȱnsŚ@ꢕTU6ēR'3f"uQ^rO<ܘ>|QIɌj!^U>ʊ_^i zvYN((oeh2M,T h28+_ł>ԋcoehsAKg#ux݉~aZnAƺ{y)SShb-AVު5Ⱥ{v<@wO@ 8ճidz-[cLiAo +k fz1~\.i{܅T'Nw?QրyS{U?Jϊ.1Ud[ .`gC-V"b|Xjb>y1S3H\W n,7wBضgoIcOϑ/ϊWh{؆t}YKFՏYa:A}{Cn:!bD(تI=uޤirk!N~{>=8ﯰI)7 !Q)` ~G]2a Bt0$(_ K+eȇ=Lpڡ$?]~8}bA!E+O!JtGJ q[ [Z`.GF fvgXP.{pjʄ9_@Vvn!.]{ bV,̦xk㫬n܆ŧIJB2&SV#Oנx ~KVBo~|Vr+1\͝(N-iL'sf%J~ʁϾ1PJya!Lx!i,ODN;&u>I;0D雙_3k EKmTDZ&9J]D{U~f)Psy558 c-XLsУ6B\Fy_ :wF _!%2A t-ڡHНmr'' j2~wUV3qMM_(y4rIENDB`thonny-3.2.7/thonny/plugins/pi/res/scrollbar-button-right-insens.png0000644000175000017500000000546113611773167026711 0ustar annamaaannamaa00000000000000PNG  IHDR w& /iCCPICC profileHǝwTTϽwz0z.0. Qf Ml@DEHb!(`HPb0dFJ|yyǽgs{.$O./ 'z8WGбx0Y驾A@$/7z HeOOҬT_lN:K"N3"$F/JPrb[䥟}Qd[Sl1x{#bG\NoX3I[ql2$ 8xtrp/8 pCfq.Knjm͠{r28?.)ɩL^6g,qm"[Z[Z~Q7%" 3R`̊j[~: w!$E}kyhyRm333: }=#vʉe tqX)I)B>== <8Xȉ9yP:8p΍Lg kk Ѐ$t!0V87`ɀ2A. @JPA#h'@8 .: ``a!2D!UH 2 dA>P ECqB**Z:]B=h~L2  5pN:|ó@ QC !H,G6 H9R ]H/r Aw( Q(OTJCm@*QGQ-(j MF+ 6h/*t:].G7Зw7 Xa<1:L1s3bXyeb~19 vGĩp+5qy^ oó|= ?'Htv`Ba3BDxHxE$Չ"XAP44077&9$An0;T2421t.54ld+s;# V]=iY9FgM֚k&=%Ō:nc1gcbcfX.}lGv{c)LŖN퉛w/p+/<j$.$%&㒣OdxTԂԑ4i3|o~C:&S@L u[Uo3C3OfIgwdO|;W-wsz 17jl8c͉̈́3+{%lKWr[ $ llGmnacOkE&EEY׾2⫅;K,KhtiN=e²{^-_V^Oo§s]?TWީrjVQ=w}`嚢zԶiו8>k׍ E  [ly邟~_Y53rW򯎼^{7so}x>|쇊z>yz;lbKGD pHYs  tIME  .ArIDATӅ1 C;ĐS3qw&Cn?|VʳbS"z 43MUm2 UE6W^umT)1pJ 9֘py!LA_Ctv9R{fPIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_scrollbar-button-down.png0000644000175000017500000000032013611773167027221 0ustar annamaaannamaa00000000000000PNG  IHDR w&IDATxϽ 0Ʃ3@ 8ߚX3IENDB`thonny-3.2.7/thonny/plugins/pi/res/zoom.png0000644000175000017500000000275113611773167021770 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATXVmLSW~[@J a(-BF 3q5j%cm E7cRGELYf 4UES{{cpCi-=s{~sBHDFPD9sm~ajH2+K|j沲Dzz.::.4001x=/l@,Flz6U HKAmj<6p᛻UVL&n]K$bTZVT"iMMl3mj'8aш7m;BdE3YZUUia][[[H"o{"Oą"Iġ˾<|(߿sB$njra`y ?_v0 ǃ//92EGyqzڌ9rI;9BS/ĒyCSL,bcǂEf'#11QSV0`2#r%k|?50P֬Yi@PHKK5?X{RSSAT u#!noIpr? 1@Бxu7v=( b ~$#r5iBBv|zs݃8%%e@% csQ;po2&7!H3.,ADLp&'d IDz^ 麛noN?1x:JҢp̲ ߆Dhh@,Uݔf'@aNwi`edɒ Syۅt$9|ByPRNw)弸5|EGN\.ť%?sӪ`?ƸvIiiin%_(!/ƦS'GGF|q(2ST8OFUkjEF蟮̒u}4MGtε$&>H"sd2|bJ V\F+nӻ\H*SjIQ: {V D*+*]ܾ wvܬlޱv@ =@ ZvTa}yj~=rmU.Z`[V eEg63tWuՃx: w>nPplɓ'4 |dx֬JrBH>{<ƆX=m ݧycN'v8xϞBT=@.;r:j;wec+_tt\N_~k4ʗ{w:իkEN{V[HxApљ3/lJ*ܸq#Oߗ!ϕIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_scrollbar-button-up-insens.png0000644000175000017500000000025713611773167030204 0ustar annamaaannamaa00000000000000PNG  IHDR w&vIDATxK i("^@Oz\2HMK,7,)%Xk@p΁uj9{cvw03T5>3 >jRCۧo­)("?wPIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_debug-run48.png0000644000175000017500000000176413611773167025041 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATx՚]oTv$;eY׷( `Uo' n`\u &t ڔek6eqرU_2۩89~<یeAp=lVUgÏ@JX&NpuQ_T?"7LT۹XMC:.G뫲 u89mNϠI`q$iW` !8OH_Ǩj(2JF1U] $,*-*NR6* -&znbuN݆R*o;24/if )+P.:8o(/$3y~|1cѰw 7Qg8<γ؅Chȭoϔ'fP.8Ot-?TG8 {zT uYԹ6BB/Bc&2NPD?hD[6A:4'PfbUЭsE>q Yoxv/c+gJ٥JPb 4篎]<T5x{.:2R$(e8 ?Cqzl륞`nD m=enR'{F|X_( JBi&wd#"ÿJ![^ےlCNCxl=%Q^I)>E@TH Z!4179݈hHA29"3w!\)xKZ&/$O ~=8Wۚ2ԑa++8PUG*~#o$=iC j ^Gs)dBZo^pB7%   솛Mm}?(3XiFL ~.8T8Yk6~z&j7EzEӭ@41o4Gu[*={"@SӀ'Pi_.YUxPJ"P:+QIENDB`thonny-3.2.7/thonny/plugins/pi/res/window-close-act.png0000644000175000017500000003762113611773167024167 0ustar annamaaannamaa00000000000000PNG  IHDRVΎW pHYs B(x9iTXtXML:com.adobe.xmp Adobe Photoshop CC 2017 (Macintosh) 2014-03-25T09:27:22Z 2017-03-17T15:20:14Z 2017-03-17T15:20:14Z image/png 3 xmp.iid:7e1d57ae-8ad9-4073-972b-a9a4c88137e9 adobe:docid:photoshop:964db76e-4bb3-117a-81fd-ccddd290c121 xmp.did:ec039437-2253-49b5-9430-ebec13b7d1bd created xmp.iid:ec039437-2253-49b5-9430-ebec13b7d1bd 2014-03-25T09:27:22Z Adobe Photoshop CC 2017 (Macintosh) saved xmp.iid:7e1d57ae-8ad9-4073-972b-a9a4c88137e9 2017-03-17T15:20:14Z Adobe Photoshop CC 2017 (Macintosh) / 1 900000/10000 900000/10000 2 65535 18 18 s , cHRMz%u0`:o_F2IDATx"வptoptowyty|wĄĺĺƼȉƽ挏uvqtvpswrޮvytܸ𶶶ܙܙuctGIENDB`thonny-3.2.7/thonny/plugins/pi/res/document-save.png0000644000175000017500000000140213611773167023546 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATX햿Kq?_AMrE*NDk!64vӎK EZRҀjEV&:D/PMĈ3< B uu_L&/ZVi:]^u3pg3`'+v@`mں kv`{{  ~$ppI67F$)(IL!3𩱱AB$I***hjjix&~QX,l6b=IgZF1$@W<;_ZZ f9/D"P,˩)p8@ii)~4M#㴜)",4r13HD8]\E^/%%]9d" 7;&&&xAyy9n(68.+i2666Immm78 ' f w|K!gq:qR-  `0f+΀d``]TUMeYf||jtn(PUPh/M\t (B4%- Y;(JW|iGeX,tuUU/e^ M8ahpہ[JuNպfZ 0# o@@7RZIENDB`thonny-3.2.7/thonny/plugins/pi/res/debug-run-cursor48.png0000644000175000017500000000306513611773167024362 0ustar annamaaannamaa00000000000000PNG  IHDR szzsRGB pHYs B(xtIME  #h@bKGDIDATxVkPeL~ӏѨ%]t+P^ l!,mj`SWEW , ,˲q 2t76; h<3Ϝw{}eΜ9Hl &X ^#<'@q!!$<'q,t:ݯ7n(%yÄ! &%''xddCCC`R53gδ ބlleڴiSNw]VVfy>|Aw&Kv]x1֭GC6[qww2 9F__ Lbʕ+*@IIoWTwn߾wݳ:gkcZ[nS\9m F{{;o܌Z\~555ШNqd(Cpv Z[[0f3bdm5T`0 440oF{AOolO^OL04#qhو7oIrTsu∊ַN0&| qSSj5С0;6f#n/=itkQ AKO SE؊tv=q\ƄN>mܲzPᜓnŠ?d"bQH!hQܦY%KK ==@ k^E!|.NFEaL>!6zGN !\q0oR^0\. HKII0*.=2V$#hQ29OOpR!Jښ(AK_0EYzA_c眎:P'Deuy |=KQRuo NNN&>~ W^Eii)-ӝ(Gx/tT\K+++*3{H'5"nrss{(KRsY27'A1FQ+oa ,((R) &&F)tD?\X&&&ֱBC/vkM+ {J\n_8-ChPyXsz,_A3K]]]`mxd(%54gKo1x?yO8f*QC&p9aB9zS{*$I3sIENDB`thonny-3.2.7/thonny/plugins/pi/res/scrollbar-button-down-insens.png0000644000175000017500000000546213611773167026544 0ustar annamaaannamaa00000000000000PNG  IHDR w& /iCCPICC profileHǝwTTϽwz0z.0. Qf Ml@DEHb!(`HPb0dFJ|yyǽgs{.$O./ 'z8WGбx0Y驾A@$/7z HeOOҬT_lN:K"N3"$F/JPrb[䥟}Qd[Sl1x{#bG\NoX3I[ql2$ 8xtrp/8 pCfq.Knjm͠{r28?.)ɩL^6g,qm"[Z[Z~Q7%" 3R`̊j[~: w!$E}kyhyRm333: }=#vʉe tqX)I)B>== <8Xȉ9yP:8p΍Lg kk Ѐ$t!0V87`ɀ2A. @JPA#h'@8 .: ``a!2D!UH 2 dA>P ECqB**Z:]B=h~L2  5pN:|ó@ QC !H,G6 H9R ]H/r Aw( Q(OTJCm@*QGQ-(j MF+ 6h/*t:].G7Зw7 Xa<1:L1s3bXyeb~19 vGĩp+5qy^ oó|= ?'Htv`Ba3BDxHxE$Չ"XAP44077&9$An0;T2421t.54ld+s;# V]=iY9FgM֚k&=%Ō:nc1gcbcfX.}lGv{c)LŖN퉛w/p+/<j$.$%&㒣OdxTԂԑ4i3|o~C:&S@L u[Uo3C3OfIgwdO|;W-wsz 17jl8c͉̈́3+{%lKWr[ $ llGmnacOkE&EEY׾2⫅;K,KhtiN=e²{^-_V^Oo§s]?TWީrjVQ=w}`嚢zԶiו8>k׍ E  [ly邟~_Y53rW򯎼^{7so}x>|쇊z>yz;lbKGD pHYs  tIME  .ArIDATӍ1 CQ0pLYr0 !fߩR~u]!sFwfI$Zπc{;u]L)׭( k== <8Xȉ9yP:8p΍Lg kk Ѐ$t!0V87`ɀ2A. @JPA#h'@8 .: ``a!2D!UH 2 dA>P ECqB**Z:]B=h~L2  5pN:|ó@ QC !H,G6 H9R ]H/r Aw( Q(OTJCm@*QGQ-(j MF+ 6h/*t:].G7Зw7 Xa<1:L1s3bXyeb~19 vGĩp+5qy^ oó|= ?'Htv`Ba3BDxHxE$Չ"XAP44077&9$An0;T2421t.54ld+s;# V]=iY9FgM֚k&=%Ō:nc1gcbcfX.}lGv{c)LŖN퉛w/p+/<j$.$%&㒣OdxTԂԑ4i3|o~C:&S@L u[Uo3C3OfIgwdO|;W-wsz 17jl8c͉̈́3+{%lKWr[ $ llGmnacOkE&EEY׾2⫅;K,KhtiN=e²{^-_V^Oo§s]?TWީrjVQ=w}`嚢zԶiו8>k׍ E  [ly邟~_Y53rW򯎼^{7so}x>|쇊z>yz;lbKGD pHYs  tIME  .Ar}IDATӍQ9! xߔ> \3SdIvIvٖ|l!+8]]URJ68)PU9# q'p$Qk«~iI@roFyzehLΆhIENDB`thonny-3.2.7/thonny/plugins/pi/res/quit48.png0000644000175000017500000000370413611773167022141 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDAThYklk1!}DJ# ! (-NPT* (Ar0R%DQ55%$'[kz_s#^Njgwg5ks{s/Rd"! @s1F>إP(2^>k IA1KvTuub hLkD)+4޳$q?B^4ֲ `?\ v$-&=XU}s8P(KED1fgے^khxoݓIyH_% .V#/헛7\lK E4vM{BأF IV+=-6e9} ##FΗb{M:9>,K͌i㒐vgR%HRR#V!S Ӝ$Йv3P)EHR3~HP"ƩsJ~d9~M.3Q VbeGY]TD/F0:Iye](YRغƸzҲrx|feI ~xݷ[Shz:>xRgςk膵Vj*I4H 5qN-զ4 ϣVӜ n&lϣaS7p岐V ;}ZCt`~%4 e7syT=h>|@7.o7:3)9=@SCqllS-u':cx PǢ ğl/r<$RnGƗAPBP.ňYy\Suȇgmrl*&|tɚh垢>%9\̽Ci`'v- §3–a_kҜvpZ3AT-1e8_ۃb"r1ͩ8ig18vw݅,2C%P#S|7x0<2P`J83kdF798>ߢ4rmS߽76O>1eE^4Ht'}Bď᫔W>s^AG_WyntmvaT#f">Di$SS9zlxfY?_,,ǯ+~;$8e: #fe ῗ-HTy[U[-q2( _*or|B:_{1A'CJWuw$Ӧ'8vOڅu;zh($5~k-COUå/Q  ՞ޱ*+XVhL)^ſ,MԐ9nWCp-NcH30Ƣ' dg?s.joIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_scrollbar-button-left-insens.png0000644000175000017500000000024013611773167030502 0ustar annamaaannamaa00000000000000PNG  IHDR w&gIDATx SJ, YС:O}*vwR3cw5cRJ|33Z@S *\kBC瘈n9û߁sכ3_])9_IENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_resume48.png0000644000175000017500000000334313611773167024444 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATxՙs3e-_$qJ-]T^ ICDb ,YD`(E={<쮴{VUJ3ݧrի?`Zj FhIL |I)% vPbNJT%0oLxV0{"%# j:F#7wZ)Y3Ƅ[.] ZQ0OIH V8~Z6 d N5$RIoFVgrՁi/7%\nu9H@!+5<1Ԅ1lSZ+rI5zџ&pi{k8S=<{hWkxS BoL''-|GP9O*+RE7r&&o;ڟ/G\>Bd#_É>AB޶qkhHnbN!)'΂޽yBzL׻zg !HzgȔXR=o HT!_9ѕ]:@2V{Z`$ûX=A _z:Z#CC/l iv=<=sϴ+5[TAOlv*瑚|u׈}S ql zb .| ^Kj^h=0#e75>E \5q/> a!^~AV(V0g Q_xUpRd2 P.[M|ZÆ9_S^[i/,*ߦl,p&:EaFgc9r<+Tbjx0U3Lԡ'yNt  AR/*wHAт)W-Ŏ*鎶JO,ӑVK.C/!40kL5)zZfIտ"x@eIENDB`thonny-3.2.7/thonny/plugins/pi/res/media-playback-start.png0000644000175000017500000000247113611773167025001 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATXŗ}hgǿw4yiӦIVgRaZc8?87&1gNܔ 8& 8utu$$]^.w=#/ڦ&U{w9 7q) yi]/8.bԵLLeGטH,EQ8n\~,^`ewz/+@ktS 70] ܷ r\(9g.W}njeg:Et\yɆ xz|8ce!}Çt|C/Logn姉/VmRլ%֕[^+S 5 z\G&>_j~d8́I f=^{;s‰Ӛ<]-O͔`y9~"ff 2䃍@z;M[BR2ƅfs3|Vl!Cd\@ f2W4N+;xQܨnl5,6gַJ}CǤ*.9Vhp:.r`0R*+J>u`o,ތ|E Ys> b5KlMtxs*1 D40y2 jٻ$v>6dҍ`jПww?Nhcn$ʽ^b?6 @)sZe@DbSp52 IuXܧC?&O7ex_^ЦZ D{_Cfag]iӡ,м;0tFqSӸ^YW[XaP7ow 809G51!4|Bkk=ӣZ+j~?865of+iahi3%1^IASv=@9ӱ'_-榕dPt:oܾ}|mOAt:dmmK4>xqVma{wDT>$%!۾qZZ>Çct4MQJ\҄FYmmױ XXX'bc>o=|XnƖ  'O*100· P]]eabbgϞ^^G^^j:ǤIqݴJ;&,ĭMEEn7,KyZ u#Tj app^׮]Cqq1fff݃:(Jp*F:u & w ju.*F#[JD"բ'M/R 0XM{> <`0:o(hm;6ͱy666PPP GvK.acG0qq'ʞBBZrt3]JdMy ]8LT vvvNxq2*z`+cm;Fq]:6_F;GkkIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_debug-step-over48.png0000644000175000017500000000153513611773167026155 0ustar annamaaannamaa00000000000000PNG  IHDR00W$IDATx]oV~kb%[ U۔2CB7|~60!&Z[B ]%89(DqҦ9++?::}=9yS45iya wkl`i]* Gй}EC /krQ( *%~sKtp=h{bݾ 5j8@;9xX9izFmqajC.;bqv-N?/=A !b֐wf@CBɇk;Ǿr*Y%SQk5<& cLkGPl `s)VVjЯv !pvw(>#aq=^DIa} hfkmVckњFz zvp];w\9kApX{ i4 jź*E;}Uog6Ҁ%W=ngSzdZfgܱ9;/Ch>y0WHMdcuUQ*@Z>抋2#Y/b@+RRR+VnTFg/t_YHs1fA)O &hIENDB`thonny-3.2.7/thonny/plugins/pi/res/zoom48.png0000644000175000017500000000500113611773167022133 0ustar annamaaannamaa00000000000000PNG  IHDR00W IDAThY}TTe]fFG$A{_$h"tTji;N1;e$Y{6V-ڦ@hGJlq;! $ýwRg`f` s{vs}s/Kw0;T0Y+N [-Lȡ `L&KtqQV rL& -hhhRyBwU/A9o`:hݺ e˖CRgP^^"o> W%0Saܼyzxowxe'ӧM`͚nذRtp:8tキs0GTз(ӯ񾣣gϖMM`ٺr"88ERRfy_p/`6H88 0 =CR}ͷcbbbDLطo+Z>cYa8䔥6mB`O}}=6o}rףjIG}$Fs~!:B4B'z낪={,)) )%7m"ޜ5==]dݿ୷fDzKpZ,7ܹrl^dPD@*~6|"] Dj}!k"hn}Zϲr:d yE"} B肩?؏&7/]Q?'N|&0 2+Wv:]T=!b8z6!1/e0h %FQ]UU%J3XZnǍ-,w\oLU *0GVO[[:hE,ĕfOˋ n[q"nL櫜A&#~0ŠFmn(2yJ%B+Rz6L`24 aWh9pH څ}]sG@ ໡B3m---U T^t=&..^ `/GJX9Fqqq"KCC=/;kkk[iŊ$/D 3WHrm6jjj. \xUJ򬫭VrE Cfax???ܹrX֢B~㜔TeÆ(-=KQey۰Q?/Xn*jMDv^p;n`O>DT 00 ~kɓ!Aw?3gmj@ f`"X:wl8N'W[,,^ rӓ\zic=} RzƟ3v<6י*ıc^81oy=0tLH\ѣG=n .!d//v\Ǐ !_0{= C=gN{\YXX "zUVͶ]v>WV}EkgTg̞}Knjj]^x晭]]]g"^j?xXP(cl4=- 5]5ynJ &4t~p\\0kG|ee%5LGwhZ$>w۶ա}}}(..BCC}Uf;֭[d7N~xyyyg{WG"~%99۳} ֆÇ^ܸ{K +izlP[[_n+))tmdY~Ԓ}#}}KqÌuu8d0 EocmZZ<11Jރs"}oEWG/qy (|'3V~eoooGV6Sk~5{0t oN}Wdd䴐\eQWW;;p㌆8JZ-J}{,s de=olo1t@= A~(@%׼=Vs""+ ?]^tF/ B.[_SSص59r%7'a 񝱱1f3!TWW&{0jIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_scrollbar-button-down-insens.png0000644000175000017500000000026113611773167030522 0ustar annamaaannamaa00000000000000PNG  IHDR w&xIDATx1! DѿVd!J|Pr="d7d7[ 1"K1)RU̬@Jb1CU}f>+ [kr^'%B8`IENDB`thonny-3.2.7/thonny/plugins/pi/res/scrollbar-button-down.png0000644000175000017500000000545113611773167025245 0ustar annamaaannamaa00000000000000PNG  IHDR w& /iCCPICC profileHǝwTTϽwz0z.0. Qf Ml@DEHb!(`HPb0dFJ|yyǽgs{.$O./ 'z8WGбx0Y驾A@$/7z HeOOҬT_lN:K"N3"$F/JPrb[䥟}Qd[Sl1x{#bG\NoX3I[ql2$ 8xtrp/8 pCfq.Knjm͠{r28?.)ɩL^6g,qm"[Z[Z~Q7%" 3R`̊j[~: w!$E}kyhyRm333: }=#vʉe tqX)I)B>== <8Xȉ9yP:8p΍Lg kk Ѐ$t!0V87`ɀ2A. @JPA#h'@8 .: ``a!2D!UH 2 dA>P ECqB**Z:]B=h~L2  5pN:|ó@ QC !H,G6 H9R ]H/r Aw( Q(OTJCm@*QGQ-(j MF+ 6h/*t:].G7Зw7 Xa<1:L1s3bXyeb~19 vGĩp+5qy^ oó|= ?'Htv`Ba3BDxHxE$Չ"XAP44077&9$An0;T2421t.54ld+s;# V]=iY9FgM֚k&=%Ō:nc1gcbcfX.}lGv{c)LŖN퉛w/p+/<j$.$%&㒣OdxTԂԑ4i3|o~C:&S@L u[Uo3C3OfIgwdO|;W-wsz 17jl8c͉̈́3+{%lKWr[ $ llGmnacOkE&EEY׾2⫅;K,KhtiN=e²{^-_V^Oo§s]?TWީrjVQ=w}`嚢zԶiו8>k׍ E  [ly邟~_Y53rW򯎼^{7so}x>|쇊z>yz;lbKGD pHYs  tIME  .Ar{IDATӍѻ 0 Ѓ,uRQ(`Z2AdO>'b+"$U}EǞ$ygLrk ‰ Wxe> TƘʴ )_l}C=IENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_document-save48.png0000644000175000017500000000207213611773167025714 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATxoOV&&1!хM+Jo uH;>r% hE,$kKǎKԊG{=>ɽ&!LQb0277M֜ ^d~VUxqqAP k°cœp,`QQ(`x0j:%6<&zL/*JOF2r ZJ<_]}K23qWD"w-#ǿ)J%% .,+4 !aV!:IJՆa#3j,JD+_P׹&,,,C,Ic,rc}Bׯ5]ޅ$izQHęcmT)4ͷar ßoUg|||PV s}}MiI;bg00\.$S%L.r||9R9f(C$$ ]-N%x|>2-:oJ4Z`&F74dFaEnJ%}2vmGԔ_:DQfffmBNNNd2$.[ rZeY(J|>g/Eˈ)|S .x?qtgisnIGg]28=<|VV =E==X rPIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_window-close-act.png0000644000175000017500000000117113611773167026144 0ustar annamaaannamaa00000000000000PNG  IHDRVΎW@IDATxn@8ڱ= Uhe]vUi:8@!Ka bDcU"Gitg7!(KfK( }zzU.S.ti !(EQlceYjRmZ'/qCSriڋ :;;TkF0 ðdx3䷷}M$!vCEqeIv_ߍg1u(Fz#]wu:q԰$M6Iu=Sojz}sR\81M-$Iڥv{}ҡZ%΍s$,EMA6,~7Wjv@}1~6шaxUu=D[2X:5?d N/jӦ6lxh{"t4`S=|osSNf+q^{AbmQ9'L|?7`*~R},(RUUi?BQQYu>2,5|+,,Me둬74?yB(ʉi?TUOIENDB`thonny-3.2.7/thonny/plugins/pi/res/resume48.png0000644000175000017500000000367113611773167022462 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDAThZklW{O Ϋ*URR+NKR %- ! 5RZ$@m !1mQPPUIhc.Mff]c~]Q?i=;w9prLj,` S ]"t()W% $V ظXG\ v7cp5E',tFvWYV-Im4fb%_M}w6Y'$[?UŵrTH%uvΈ`{S"[rGi9H\3Mv[8)Ý56'W5-"gLDq]xa_i[xtt,3Y'# 6móB6I\'[\Rp~1^Pxdʏ@LM9OogL<Je $z{'bu[sv=kg+շ#y)^~}#&D$4}| +P~ e)Mǣf49N^8[yDV ΅LI3m9v1{{SBי`p]ٳ e`[vFG?b£),{9wН׻wm3t IzcԬ(nc4-җpοZny<3J`'YͲBc)kCFL^(NLR5$<<6p77z 6?C&0 cD qv\ծW$CUa 75 @}D[Qx9@;IENDB`thonny-3.2.7/thonny/plugins/pi/res/debug-step-out.png0000644000175000017500000000120413611773167023640 0ustar annamaaannamaa00000000000000PNG  IHDR szzKIDATXŖKkSA9z)"XRZ^?BJ@ vaREE; H5X\g>Ɯ\N2'}W9|3 e=y8W~zEoQGoyp*u^KxOD=<d6W"'֢=T )* @XpcvHP?x52Hʺ= p D )aCزO0 ..ԵV6kZKmy[ Qu cñvl@8e*jj/~|t'}>Wp!Z]&4Z~T/6O_ aր2 @P Pyc ߠzC@M~BySkq Ϗ ߈]ـ9Zc \:Rwv;/$^_8wޙs杙b}}Q;j) 5Λ Y\Q,'Cew) [i,f=W: leKH)I'6P .a 1+POJ~ڬč-2e@H֜gOuރ/;WZ먯}jN"YᾦpЬp'nF,?@Mk]t"V$ 3:Uj@(X({,uT=+h!4d@q[6]%`8֑Uڈ<ǿo[ Y%2ȀU SW\t!fYA/ ԝ77<.s K`ys*ڴp~SǢ| NS%N΍-Lp< 'pG fx>Gڣ΃ADS72kp{2 > WRSقlaz* uqv!,F0xUJRޥTp'+QX0 |7/Ԗ{wD>r6@Z҇D( y$+e/VhVDf$$~ n? h+n|[2/Kt -o #QA+&vYp#D[~B'k3߅^hT:1`9VִTڴ7Ȥju·,:\.8IY;9NVWDNqv =uGIENDB`thonny-3.2.7/thonny/plugins/pi/res/scrollbar-button-left.png0000644000175000017500000000542213611773167025226 0ustar annamaaannamaa00000000000000PNG  IHDR w& /iCCPICC profileHǝwTTϽwz0z.0. Qf Ml@DEHb!(`HPb0dFJ|yyǽgs{.$O./ 'z8WGбx0Y驾A@$/7z HeOOҬT_lN:K"N3"$F/JPrb[䥟}Qd[Sl1x{#bG\NoX3I[ql2$ 8xtrp/8 pCfq.Knjm͠{r28?.)ɩL^6g,qm"[Z[Z~Q7%" 3R`̊j[~: w!$E}kyhyRm333: }=#vʉe tqX)I)B>== <8Xȉ9yP:8p΍Lg kk Ѐ$t!0V87`ɀ2A. @JPA#h'@8 .: ``a!2D!UH 2 dA>P ECqB**Z:]B=h~L2  5pN:|ó@ QC !H,G6 H9R ]H/r Aw( Q(OTJCm@*QGQ-(j MF+ 6h/*t:].G7Зw7 Xa<1:L1s3bXyeb~19 vGĩp+5qy^ oó|= ?'Htv`Ba3BDxHxE$Չ"XAP44077&9$An0;T2421t.54ld+s;# V]=iY9FgM֚k&=%Ō:nc1gcbcfX.}lGv{c)LŖN퉛w/p+/<j$.$%&㒣OdxTԂԑ4i3|o~C:&S@L u[Uo3C3OfIgwdO|;W-wsz 17jl8c͉̈́3+{%lKWr[ $ llGmnacOkE&EEY׾2⫅;K,KhtiN=e²{^-_V^Oo§s]?TWީrjVQ=w}`嚢zԶiו8>k׍ E  [ly邟~_Y53rW򯎼^{7so}x>|쇊z>yz;lbKGD pHYs  tIME  .ArdIDATc|1! ߿cW^Ǐp1 =300Gǫbt8E!uL&$pf|9| ~ ӷIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_document-open.png0000644000175000017500000000133313611773167025542 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxVn@=vxX3$7Ĩ +HbX׺_PR|IT@j^ ۘԀ@]ιgyp\.yTҁ٬8::.0ß9'iNAR $ U2|@U,?<JV^Wi>DQNR{Ic $Xe= ͵ ܤ;#@TR" k5d{{{nj\.wЖ g<, D4 |%T u0ȶm8'SU װ,k`Y$(>qXD,)8|F. Ca[mGs58CcI IR8c /"Dꁧ't]c躎[8./;8<<,˫qfi\$0GQl=OөipssL&6R)B!;b.y'R, PJ1clI$IhZ:@hdlm6@F9?9&yp]7P|՘fk0L"nllD> Cu{ZDp@;._ǫBm 48>gg/D8~IENDB`thonny-3.2.7/thonny/plugins/pi/res/scrollbar-button-left-insens.png0000644000175000017500000000545113611773167026525 0ustar annamaaannamaa00000000000000PNG  IHDR w& /iCCPICC profileHǝwTTϽwz0z.0. Qf Ml@DEHb!(`HPb0dFJ|yyǽgs{.$O./ 'z8WGбx0Y驾A@$/7z HeOOҬT_lN:K"N3"$F/JPrb[䥟}Qd[Sl1x{#bG\NoX3I[ql2$ 8xtrp/8 pCfq.Knjm͠{r28?.)ɩL^6g,qm"[Z[Z~Q7%" 3R`̊j[~: w!$E}kyhyRm333: }=#vʉe tqX)I)B>== <8Xȉ9yP:8p΍Lg kk Ѐ$t!0V87`ɀ2A. @JPA#h'@8 .: ``a!2D!UH 2 dA>P ECqB**Z:]B=h~L2  5pN:|ó@ QC !H,G6 H9R ]H/r Aw( Q(OTJCm@*QGQ-(j MF+ 6h/*t:].G7Зw7 Xa<1:L1s3bXyeb~19 vGĩp+5qy^ oó|= ?'Htv`Ba3BDxHxE$Չ"XAP44077&9$An0;T2421t.54ld+s;# V]=iY9FgM֚k&=%Ō:nc1gcbcfX.}lGv{c)LŖN퉛w/p+/<j$.$%&㒣OdxTԂԑ4i3|o~C:&S@L u[Uo3C3OfIgwdO|;W-wsz 17jl8c͉̈́3+{%lKWr[ $ llGmnacOkE&EEY׾2⫅;K,KhtiN=e²{^-_V^Oo§s]?TWީrjVQ=w}`嚢zԶiו8>k׍ E  [ly邟~_Y53rW򯎼^{7so}x>|쇊z>yz;lbKGD pHYs  tIME  .Ar{IDATӍ1 VwU;`)MSdK)=wZC1L)9'{^rtG?r#B01Fb]@GZZ+ι&YE:LNnIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_scrollbar-button-right-insens.png0000644000175000017500000000025513611773167030673 0ustar annamaaannamaa00000000000000PNG  IHDR w&tIDATx̱ % `zrwI)vsN E6{SJ03D`O#c| PJ[kxx59o!nő-ú2IENDB`thonny-3.2.7/thonny/plugins/pi/res/resume.png0000644000175000017500000000235213611773167022301 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATX͗mH[Wk4&{c7GJaM_Oe2?؍8ʠmB6݆BIm8Qٰ/++- `koQc7&9&3楉 =swyιHdXn$8M$,baoa);G\.wxUdYD6ZJxKM!6Wg  g;$OQEq PQ.m7a(YO`*pʥM]dY擞넽[9/i{Zx}rKI˲$T@w\eZ9c fi朷TU5g-3%c\@X N3Wu^pҞU◫1yLɦ?#X{dn+ w[+ŝq!lkL0Ю }lMB$PDGzEC,`ICm۹?@'۹? m a69lyi|M\ZL49l|6@il(-r_/E3ތ8ڴ/'QWx\9m^ed8'!+ɴ#0L'`86#ayg%)VqޓxXs5R< R3rU!6#zkʘ(<JSfP_"xRB{8'FsV[ My56>S^Wi'cXtQp' 50fC7gTT?.ϜJiU $Z :M-|E6r+⣬cD;2fe,ig|CTwg7qLzQ/k8Ȁu6|IKsbΟp |t⼗vQpܳzX,LDCu!*< F>@. _{.aIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_debug-step-into48.png0000644000175000017500000000157613611773167026160 0ustar annamaaannamaa00000000000000PNG  IHDR00WEIDATx]s@ )֏:+I@/zUuv3JVZ,IR>Wnwd7͡E1 k$qƆu"fuwD`gkjkR52 +  ɲRJ8X0mmX KR:xqSgx` PJ'[ \TCx@tk)ХP{"&WA)yc1ds{Œi`/ uMxp&bш;*[pe<@)5 ) z3 NDUoj##CzBfX4.)mTo& >e]jKW!esMcTAZ );u_D1RHK)X9 5^c@`Bn|e. 0pJz`'֎fӧnk ftB ҫ']8Ԁn0h3ZKwwUU.$/R?(I^*z>r&IENDB`thonny-3.2.7/thonny/plugins/pi/res/process-stop48.png0000644000175000017500000000317713611773167023624 0ustar annamaaannamaa00000000000000PNG  IHDR00WFIDATh՚_Eǿ3kzP] A_ Qp@BHMBL| $!JH @(rn9uv=h{] of779I0@ &ěmJPN+W뙣6 IBt~&0kC-`#( I\ts6i1qk#N!\cn@D6LpgZS3pw6~p߇ę8uث(jR-Ͷuפegy$}uq>Y/rJm m{'.٬(_K?qN {=-%UN Hx%|kFtNIl _yk,G $qG-)wQ 3jWQqCf]=S<{ ԆA0YJK(J uvLxQ^89zl4].ԧw@Dq%HSWI'yɲym{ٳʭ&:@Zb$awFMzUpe&ApvɘAV!KHD_9S >?m2QC}`uĊ/(Ԟ(j:W c6jx`7{hQM3W?DfMr|Hx4Հے_7h gi >P]+S$14?U6&P$14P`LWCYb `:j(2DG k14OtR}n(.Bd k}KXP$ayXoD   r-HR1:._ @:o]0nWoځYVdnM=铲KyP?qێSV&i˕Q@_-4U~~4(m~xNm06KM'x_E#WG?^):o"hXEeo I'{^[4+͍r3APJ ?D󵁒$.}ۭqqCy7~m_w/i~=)..X1!B{%mE9&B Y0k(2fCgͅ e5+\-r7a5K 4j 8#kA3e8x9& ;^,f otCej&%qV0rR^?kޑi |wد?rmxDŽ$^ 1ZRjsui%C>mZ:||#6v3سפnĔrgV5p$ӗ҈/}8Poש,c?t{ú .6s7/s \ qīM˲ZqU`uK͛nyxvy:MoyҠn@>e}g|$Ic wQ` !9(QxIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_zoom48.png0000644000175000017500000000445513611773167024135 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATxYkoI=t7`L0Oc#Cb 6+ǎ3j͇LF aJv5+e;N  `f?p7~(#!ѷۆ'O—R"p zPϘXn_ @\{fJ˜ȾJBWWFv$www#@f4cb*c~6vop0je+~?~?B|l Ĕ`0< Bp]nt jVVV^Q_~ PĴ 422:^TL&b1c,K`LTL&Gb'޾}tz*caC~FLlħ8cL27eah(*QZJI y<ss. #p2a5 JƘ:U<>X,}N6 Db Jc|]pc4~BgTyooj<"|; J,c⶞~ ĝr${z^h<_Dp8nA89ۤi,ˉt:|M)1bad2٪H) P|T:8#& f@&qH!p]#(ր8T*A)%jaQJ ~p@<޿y]2&&[Ni7W]wY@G 0&JASBUxNK|>mbt%dYN윬d͛7=Uス]Hx{[NRC[8dz@)/;LJu dR.p3##ZW,7uAc˙L&ؗmmmc~ϱKaAfVů\hxUQN2͛7 SJF.2(%@ 8j5inDbI#F SJtvqRr?b1M uߤ;IJb;8FQlܬ =JWQW0Jcaa! `:zb>pm199Q(OϫZ_y(%X;88, ի6j2ۋ^h.EV*Ҋ"Z~gJ(%w{zz޹`B&R,gLL,--EwvvGѨկ|:}!揷nD"M,KH&פbc0&$?vt A|dYR%fL,^jxJ @0ՔabU🌉jzwS\.Bp:::8qpP@>U峂]7JcXww)/J`GGG0&:0'˒1͸p98Fvn_7JE{9J婞Yw Jl6?'E=}f__._M!{cD]>ܶ(bL+B>^onR`mm kS/}s}}! H&xZ] E)ycf-ɵ׌ߴ@}766֧YVdQdK h1c?8 @&YФo.\O? vIIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_window-close.png0000644000175000017500000000064713611773167025406 0ustar annamaaannamaa00000000000000PNG  IHDRanIDATxՓO@kLhZ*$XSqmu`G8`U%¹A,x{ˋ&r^\׹"e[vcġZ*`s {PQUDsixj!z0&.e0ew̏8NLhRKΒy&sز۳٬O TU)(̿Y̻ش;mB1lSq$骦A$apUຎQ,JV(L&(|Jh*+/ 8)̏GtM}˴[زIyy`u8|(an-߱uݎ1ϫ PtIENDB`thonny-3.2.7/thonny/plugins/pi/res/debug-step-over48.png0000644000175000017500000000170213611773167024163 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATh_hSW?&%hS cn/\X) tA2_P?n:(XPCQk'vɽCJȟIn<{ρ"Gx+4)Bz]JycN54ujcOQRIDt=?}U_REE@p$}##LhE2?ѹ8>~V˿=v2GJ #096ヨ1&dzoi)% k:[NQu He {ir*}ᇷYPP6}XH  SW'^w-͍a߮IoLP?sITGŷfiΛڲ4C^yr]I:r?̦ o&}c`c':s)3E -?sj~8^OʲjJ@/(7~KSJMi=ǎ*CNuRS:hܾGe9)Ij775ҭv%x}M /MG*KFֿݖTS;v7U,]=)5sbi Pye[dĭ&LծJ>&xd`FS!N:<3BNFHbƠj2JnbFLqh[2˘ _tSzR-n VI3D6XڥϷj^!_4>^ÿv3E^IENDB`thonny-3.2.7/thonny/plugins/pi/res/media-playback-start48.png0000644000175000017500000000403013611773167025146 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDAThݚ{pTWǿݻ}]B{&&4d PB ehlPvhG댊C#Ԣu|3R#bř6NQZHC^JC{w<{{#<7Mg=;u1AZBPyF"QJtH/\NJ30v* Z Qp_\w@mVR Eos.4D M"w{#[HԸVgsj!X7_+RS%ɫf%ZTUgJA͹ " + {cH(zfP+MpyohAot!!lH~I~]~z6?UWvt!,AEwJ||`W6-?*3X[0kxSe9~& {OlS#t@L"h})r 3Apoݾ{y*/08@b VWr];\,> w+ew0eTo:bĤ&_-Pg/NVh+߿sf ^cM3ѻ0x:jbT8,ߙ~8SmK b\f_+r֑S(+ ?] PJ$@^9w|T-i&$vXߦ*Gn&T& o.ts"Qmt B۹*pS(u- 7'R`\(" %Yx!'e(I{IE)Q0KCMf/>]h.5^O=O$@)mkEK0`ݥC,~Dj{-hI G3lzF3g IǦ/%DtJ(ǵ6yejDѫo`u^:W${{c7(z5gFSXx&1[|2=;~Y:>{26\vc<Bh|Bƨb(ڨbpdx #ݻ]:sP43\ӻF8w;xpoFQS|:׆s5/cۍrfi ~ԙ\߆m:[ e`6lVGEMo^m+(t?,cC vy>adٖ7Zy&ED^4KI@1sT>=v/,x?vy9)XSaŦJoƜ?hKH毗Qmk: \Pƅ|z}›1~¤`kaeuj0)][ &9? ѲvT|6}6 &K$Q@y~$|R,|'{˥eȥ%444ONZNhk:4 !::uHT np$"Pڨ΂wIENDB`thonny-3.2.7/thonny/plugins/pi/res/document-open.png0000644000175000017500000000144013611773167023553 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATXݗ=HaՊ`S4ܡVHT*tCւJ ;BbX+j.w%&uIQ/_Z#7/ܽLEvky歭ok^Ȳl,//QN\p# |h˙HBX_UUs".qQYlWnk%7Q[[J+*'sq_`](aD"J 44OTF0oLMMfϴ ɲ/V`{{"&&xP(i3<}TVVܼ(ʹ\SgcfƝ759p8|>|NqLJgf`g;sshooG$&q8hX[ YedΟ~q4OP|KB"3lH‹z4vhhIX]]rZ[[O766k?q҉C[pttD,&%-i; 4 ©르rN'$lT_1;T\ ujnf53FF\)#FjKh4,,|0tww]܀ 83*-ffLLkXJccㅊ{<0Nx$ JIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_debug-step-out48.png0000644000175000017500000000156213611773167026011 0ustar annamaaannamaa00000000000000PNG  IHDR00W9IDATx]sTyyi]ZRm0`G:^MzXa)vSXi) }$/kwMMvv9ydqlYTko|T~S^uA%u霽ښWmAQS4GTѝyU>ꎠap8UC٥t[{$hHV|8O ]N+o6Pn>1pih)"^ĎmQGQzyowc | FK#YRtŕ|b7ʓ}( x~'n:5P4=1@H4lv\E>0t K .TXz )&뛯GQuÊ[2Zv?hWħ&=m暳y?gJ>Lw?$r.^J;uj,ʻ^vSf :+ZG][?h3pf:[HOۋi"J;$hk/cﳢ:}iNs6#IBfZ\<ÇQjRbxxu ~p0[~*S1O<4%+62jTB3yǧyQJu.d k7(KUfas?`@AU RJhmRDcgN1]A)ͺ@E"E. DFIENDB`thonny-3.2.7/thonny/plugins/pi/res/debug-step-over.png0000644000175000017500000000117513611773167024013 0ustar annamaaannamaa00000000000000PNG  IHDR szzDIDATXŖKkQ3s" ZB*X SJDQ bT{ F,EPp%DP\Q$ B5󹨎d29ߙaK8lP9*Uzm5U|9ōgnsT_%UIGdU^ܾ{,% H 'HO bGz8F86"eDxMHʖ5 IغHJXFó ]٬=ezW\ɼ@rT(J(8(=:zk35Rذ ͟UpۂmΆ ax0CAo҄O;) C ;/vC%vCE&Ʋއ6Uz 4 P9wu:zC*!g#yғaWD mP ~ [Ff? ƀڛ|]<{2c㣁A?,!wr|׽H_Q{ɪ\(=T( au7\h$kʼfXp~Lu5IENDB`thonny-3.2.7/thonny/plugins/pi/res/debug-step-into48.png0000644000175000017500000000172413611773167024165 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATh[HQ^m]uT,P)J$B! (2"SAV!/iCYf"-.uݙYOVzvqVt|3;sV8lNBNJiP5" ~I!;xv;01;nh[fy~cM S=;NZGo {)-LyI0_paR c?y-U5@)I{9dN|( uتpabBc!S- ]^$PFFkݽ^cv _P`E32dmE?NQ|B5zob*86|:fꊁ[܍'00^dH`/`A>A4 it GPhLu&O{͆Y +&(P L4`K빎/Fxb[+J Gprz== <8Xȉ9yP:8p΍Lg kk Ѐ$t!0V87`ɀ2A. @JPA#h'@8 .: ``a!2D!UH 2 dA>P ECqB**Z:]B=h~L2  5pN:|ó@ QC !H,G6 H9R ]H/r Aw( Q(OTJCm@*QGQ-(j MF+ 6h/*t:].G7Зw7 Xa<1:L1s3bXyeb~19 vGĩp+5qy^ oó|= ?'Htv`Ba3BDxHxE$Չ"XAP44077&9$An0;T2421t.54ld+s;# V]=iY9FgM֚k&=%Ō:nc1gcbcfX.}lGv{c)LŖN퉛w/p+/<j$.$%&㒣OdxTԂԑ4i3|o~C:&S@L u[Uo3C3OfIgwdO|;W-wsz 17jl8c͉̈́3+{%lKWr[ $ llGmnacOkE&EEY׾2⫅;K,KhtiN=e²{^-_V^Oo§s]?TWީrjVQ=w}`嚢zԶiו8>k׍ E  [ly邟~_Y53rW򯎼^{7so}x>|쇊z>yz;lbKGD pHYs  tIME  .ArIDATӕ10CMs\ e8 d͒ U "~^<ǝDI U>RH~ho18`l>&X=[IJnMzY7#NU᜻\JE'GMtMIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_media-playback-start48.png0000644000175000017500000000341613611773167027143 0ustar annamaaannamaa00000000000000PNG  IHDR00WIDATxZ[of ER4IKX:QVnk0$]ISEXhR'@dɶȺ4Ek˽E),/R }33]raf3 @ht 239ӱJP܄@BPV<,Z"zp8gOm\$wɜB,-ղXd/i!K8g1y`&4f/Puexo_gU9Bg*%sio>o¿?3˿ShҍbIlBqVm1Wp;2&٬B}"es9gsɓ#qPOl8gsY[YL/x!!5ح^":MY}jˆ^z >c}ۢSܺ"ot#5Yl dS`2v[3Yb.-s_za>ۀ8!ﶥzs6%T\g>Nmdq]F;_:o@lS #8g׽H40keq;V-{~=Ĉ4t̸ވ8 )>ڀC-.-n =tb #LuX}Rn+ۉlag&9E5p&s<=J&~.i`A8C)s[Ă9H0كm lbH6I)PϤTjj"b2Ɵ|v *ig_sΨaRNULַ&PO]TଝŸr;>_3M\Vy &5p-u]EڌDeASգʰDNϣ zhu}ӣGUy}! Uׁ'e+׹AhAը!]^º[lCyTe"eyٴ*_S@y Q`Yo IP:z/&!dԅH6hͩ\8E곾uwR(huKߚ)Ekj|"pwܩZȶh{Ke&Z$%<qyB0%zd= Df*qw07H'J~CMç׫a9anв}c¯QW6sܞ5پaU@|HBukSY+yWpjZtaB/k|<(7&8\l%QnV!rۺ!dT{t*(p Ex?mCՎRYSq)Dأb@{BWu}/WOb ᆈ}[rОrV8ݫd'B%7y b),7ZH~|k ¿u6g`* q ]MscUo6:DO9skuJ8THD1Jy0%]wSy BH;q_Ŭ3*aBMh@3@Ⱦh/P B5ecأBHvw*IIENDB`thonny-3.2.7/thonny/plugins/pi/res/debug-step-into.png0000644000175000017500000000122313611773167024003 0ustar annamaaannamaa00000000000000PNG  IHDR szzZIDATXŕ_kPƟCvMPǦX1b{a0v!ā Cey ~~^L Ţb]M?]$&i*N-zsL-켷5ׇu]=ᾇoopPCʂ/@ n1ՍD?q?PpO'G}SeMVn XWߵ\;X}Ao ¶/|v/DZVi#)Rӧ y̶plH"=KqvZ)xdxCJ[ tiUM%?|\`*G}"e`M%|Aw&Kv]x1֭GC6[qww2 9F__ Lbʕ+*@IIoWTwn߾wݳ:gkcZ[nS\9m F{{;o܌Z\~555ШNqd(Cpv Z[[0f3bdm5T`0 440oF{AOolO^OL04#qhو7oIrTsu∊ַN0&| qSSj5С0;6f#n/=itkQ AKO SE؊tv=q\ƄN>mܲzPᜓnŠ?d"bQH!hQܦY%KK ==@ k^E!|.NFEaL>!6zGN !\q0oR^0\. HKII0*.=2V$#hQ29OOpR!Jښ(AK_0EYzA_c眎:P'Deuy |=KQRuo NNN&>~ W^Eii)-ӝ(Gx/tT\K+++*3{H'5"nrss{(KRsY27'A1FQ+oa ,((R) &&F)tD?\X&&&ֱBC/vkM+ {J\n_8-ChPyXsz,_A3K]]]`mxd(%54gKo1x?yO8f*QC&p9aB9zS{*$I3sIENDB`thonny-3.2.7/thonny/plugins/pi/res/_disabled_debug-step-over.png0000644000175000017500000000110113611773167025766 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxŖAOA;֊VxR1=^YH$<6mNy;_{3oUV2Tquu yO#0Q2Qo~զz/u߽yԅ) "rih3@E}B:g2[Ġb/wu~ƀ/k?yO7Ęsz0 -׶oR.] yB}g//CAJqD%MOXcvk89Lg[TV /0s&Y9/_ S== <8Xȉ9yP:8p΍Lg kk Ѐ$t!0V87`ɀ2A. @JPA#h'@8 .: ``a!2D!UH 2 dA>P ECqB**Z:]B=h~L2  5pN:|ó@ QC !H,G6 H9R ]H/r Aw( Q(OTJCm@*QGQ-(j MF+ 6h/*t:].G7Зw7 Xa<1:L1s3bXyeb~19 vGĩp+5qy^ oó|= ?'Htv`Ba3BDxHxE$Չ"XAP44077&9$An0;T2421t.54ld+s;# V]=iY9FgM֚k&=%Ō:nc1gcbcfX.}lGv{c)LŖN퉛w/p+/<j$.$%&㒣OdxTԂԑ4i3|o~C:&S@L u[Uo3C3OfIgwdO|;W-wsz 17jl8c͉̈́3+{%lKWr[ $ llGmnacOkE&EEY׾2⫅;K,KhtiN=e²{^-_V^Oo§s]?TWީrjVQ=w}`嚢zԶiו8>k׍ E  [ly邟~_Y53rW򯎼^{7so}x>|쇊z>yz;lbKGD pHYs  tIME  .Ar|IDATӭ1 0 E!C QtЫAB"b_') "U0.w0"rVMz+ds, @Qfq̟!  1 !`k IENDB`thonny-3.2.7/thonny/plugins/pi/res/debug-run.png0000644000175000017500000000135213611773167022670 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATXŖKSa?g55K)4 ?"‹* ѴB/0{~ SYᒖs;9}mn;n꜇M{ѼA3\0 aN_yl@J$*,0bQ挚#" 8a)+c "1T޼1oжBhz |Ԑ*[\2USк{ @p:e@ z&/ډi6/:LBzZK9qOIs`_|#URBXswdM1+meˋ1tM=gh]ϮoARjh1 - (T. <.5MuEe(|TXvHuq\RRl/*La6IENDB`thonny-3.2.7/thonny/plugins/pi/res/process-stop.png0000644000175000017500000000216313611773167023442 0ustar annamaaannamaa00000000000000PNG  IHDR szz:IDATX͗OhUǿggg'f$i.mmыKPԂZJA ŋx l+/Dm"B(`;3;ndfvfw<i֤lvqo4ZɤEoЕR>ll&?w9ra0ͪMt2'c#D[Ei0.8gE]hZ_3݉D*Xt6ik*gth'{g>}r \'f8W ""X Я=Ǥ/ xL:qpZr,6@rr?-u]~Y>omg9&b;(>Os7 Z,&_6.XLDȳL.X 7  B'FDY>:`AK?[5F4O*,GArtsX.EG_lK 8hw7D-CU5A+X^#A)}"-n% UUu۽0Ҿ"0JCl 5C#D|~[+p <ꢫdd@l߄x6 i*!M]m l3A"0Ñ[y8rz)͊t؞AkR4uh* sJ%i8r0˒Ɋ@&EV,kJ)t]/^-TE@Q426έEƇy-33:l8ũ?,1(Vd8RLx{>l&@#]U9Q'٬j+0ݻ]nO-QGHVQX4;DVuk-_Ʃ~[{]9lo,K;7I_ƛ1{ \uޫaR۾AOx\^ĕEO9WIXsrgٗ~Y ԉhVQW2tg4`_v-ut$">(|'Zq-#iar#{LC wL82 0S ]$?IENDB`thonny-3.2.7/thonny/plugins/microbit/0000755000175000017500000000000013611777205020675 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/microbit/__init__.py0000644000175000017500000002052313611773167023013 0ustar annamaaannamaa00000000000000import sys import os.path from thonny.plugins.micropython import ( MicroPythonProxy, MicroPythonConfigPage, add_micropython_backend, ) from thonny import get_workbench, ui_utils from thonny.ui_utils import FileCopyDialog, CommonDialog, ems_to_pixels from thonny.misc_utils import find_volume_by_name import shutil from time import sleep from tkinter import ttk, messagebox import threading from urllib.request import urlopen import json LATEST_RELEASE_URL = "https://api.github.com/repos/bbcmicrobit/micropython/releases/latest" class MicrobitProxy(MicroPythonProxy): def _start_background_process(self, clean=None): # NB! Sometimes disconnecting and reconnecting (on macOS?) # too quickly causes anomalies # https://github.com/pyserial/pyserial/issues/176 # In my Sierra, Calliope and micro:bit seemed to soft-reboot # when reconnected too quickly. if clean and sys.platform == "darwin": sleep(1.0) super()._start_background_process(clean) def supports_remote_directories(self): return False @property def consider_unknown_devices(self): return False @property def known_usb_vids_pids(self): """Copied from https://github.com/mu-editor/mu/blob/master/mu/modes/adafruit.py""" return {(0x0D28, 0x0204)} # Adafruit CRICKit M0 class MicrobitConfigPage(MicroPythonConfigPage): def _get_usb_driver_url(self): return "https://microbit-micropython.readthedocs.io/en/latest/devguide/repl.html" def _get_flashing_frame(self): frame = super()._get_flashing_frame() self._flashing_label.configure( text=_("Make sure MicroPython has been installed to your micro:bit.") + "\n(" + _("Don't forget that main.py only works without embedded main script.") + ")" ) return frame def _has_flashing_dialog(self): return True def _open_flashing_dialog(self): mount_path = find_volume_by_name( "MICROBIT", not_found_msg=_("Could not find disk '%s'.") + "\n" + _("Make sure you have micro:bit plugged in!") + "\n\n" + _("Do you want to continue and locate the disk yourself?"), ) if mount_path is None: return dlg = FlashingDialog(get_workbench(), mount_path) ui_utils.show_dialog(dlg) class FlashingDialog(CommonDialog): def __init__(self, master, target_dir): self._release_info = None self._hex_url = None self._hex_size = None self._target_dir = target_dir self._bytes_copied = 0 self._state = "starting" super().__init__(master) main_frame = ttk.Frame(self) # To get styled background main_frame.grid(row=0, column=0, sticky="nsew") self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) main_frame.columnconfigure(1, weight=1) self.title(_("Install latest MicroPython to BBC micro:bit")) target_caption_label = ttk.Label(main_frame, text=_("micro:bit location:")) target_caption_label.grid(row=0, column=0, padx=15, pady=(15, 0), sticky="w") target_label = ttk.Label(main_frame, text=self._target_dir) target_label.grid(row=0, column=1, padx=15, pady=(15, 0), sticky="w", columnspan=2) version_caption_label = ttk.Label(main_frame, text=_("Version to be installed:")) version_caption_label.grid(row=1, column=0, sticky="w", padx=15, pady=(0, 15)) self._version_label = ttk.Label(main_frame, text=_("please wait") + " ...") self._version_label.grid(row=1, column=1, columnspan=2, padx=15, pady=(0, 15), sticky="w") self._state_label = ttk.Label( main_frame, text=_("NB! All files on micro:bit will be deleted!") ) self._state_label.grid(row=2, column=0, columnspan=3, sticky="w", padx=15, pady=(0, 15)) self._progress_bar = ttk.Progressbar(main_frame, length=ems_to_pixels(30)) self._progress_bar.grid(row=3, column=0, columnspan=3, sticky="nsew", padx=15, pady=0) self._install_button = ttk.Button( main_frame, text=_("Install"), command=self._start_installing ) self._install_button.grid(row=4, column=0, columnspan=2, sticky="ne", padx=0, pady=15) self._close_button = ttk.Button(main_frame, text=_("Cancel"), command=self._close) self._close_button.grid(row=4, column=2, sticky="ne", padx=15, pady=15) self._progress_bar.focus_set() main_frame.columnconfigure(1, weight=1) self.bind("", self._close, True) # escape-close only if process has completed self.protocol("WM_DELETE_WINDOW", self._close) self._start_downloading_release_info() self._update_state() def _locate_microbit(self): pass def _start_downloading_release_info(self): def work(): with urlopen(LATEST_RELEASE_URL) as fp: self._release_info = json.loads(fp.read().decode("UTF-8")) threading.Thread(target=work, daemon=True).start() def _process_release_info(self): version_str = ( self._release_info["tag_name"] + " (" + self._release_info["published_at"][:10] + ")" ) self._version_label.configure(text=version_str) # self._install_button.configure(text=_("Install") + " " + version_str) candidates = [ asset for asset in self._release_info["assets"] if asset["name"].endswith(".hex") and "micropython" in asset["name"].lower() and 400000 < asset["size"] < 800000 ] if len(candidates) == 0: return self._close_with_error( "Could not find the right hex file from the release info (%s)" % LATEST_RELEASE_URL ) elif len(candidates) > 1: return self._close_with_error( "Found several possible hex files from the release info (%s)" % LATEST_RELEASE_URL ) else: self._hex_url = candidates[0]["browser_download_url"] self._hex_size = candidates[0]["size"] def _close_with_error(self, text): messagebox.showerror("Error", text) self._close() def _update_state(self): if self._state in ["closing", "closed"]: return if self._state == "starting" and self._release_info is not None: self._process_release_info() self._state = "ready" if self._state == "ready": self._install_button.state(["!disabled"]) else: self._install_button.state(["disabled"]) if self._state == "installing": self._progress_bar.configure(value=self._bytes_copied) self._old_bytes_copied = self._bytes_copied self._state_label.configure(text=_("Installing ...")) if self._state == "done": self._progress_bar.configure(value=0) self._state_label.configure(text=_("Done!") + " " + _("You can now close this dialog.")) self._close_button.configure(text=_("Close")) if self._state != "done": self.after(200, self._update_state) def _start_installing(self): self._progress_bar.configure(maximum=self._hex_size) def work(): self._copy_progess = 0 target = os.path.join(self._target_dir, "micropython.hex") with urlopen(self._hex_url, timeout=5) as fsrc: with open(target, "wb") as fdst: while True: buf = fsrc.read(8 * 1024) if not buf: break fdst.write(buf) fdst.flush() os.fsync(fdst) self._bytes_copied += len(buf) self._state = "done" self._state = "installing" threading.Thread(target=work, daemon=True).start() def _close(self): if self._state == "installing" and not messagebox.askyesno( "Really cancel?", "Are you sure you want to cancel?" ): return self._state = "closing" self.destroy() self._state = "closed" def load_plugin(): add_micropython_backend( "microbit", MicrobitProxy, "MicroPython (BBC micro:bit)", MicrobitConfigPage ) thonny-3.2.7/thonny/plugins/microbit/api_stubs/0000755000175000017500000000000013611777205022666 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/plugins/microbit/api_stubs/os.py0000644000175000017500000000014013611773167023657 0ustar annamaaannamaa00000000000000def listdir(): pass def remove(): pass def size(): pass def uname(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/random.py0000644000175000017500000000026513611773167024526 0ustar annamaaannamaa00000000000000def choice(): pass def getrandbits(): pass def randint(): pass def random(): pass def randrange(): pass def seed(): pass def uniform(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/love.py0000644000175000017500000000003113611773167024202 0ustar annamaaannamaa00000000000000def badaboom(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/ustruct.py0000644000175000017500000000020313611773167024747 0ustar annamaaannamaa00000000000000def calcsize(): pass def pack(): pass def pack_into(): pass def unpack(): pass def unpack_from(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/time.py0000644000175000017500000000027313611773167024203 0ustar annamaaannamaa00000000000000def sleep(): pass def sleep_ms(): pass def sleep_us(): pass def ticks_add(): pass def ticks_diff(): pass def ticks_ms(): pass def ticks_us(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/speech.py0000644000175000017500000000014313611773167024510 0ustar annamaaannamaa00000000000000def pronounce(): pass def say(): pass def sing(): pass def translate(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/microbit.py0000644000175000017500000000100313611773167025045 0ustar annamaaannamaa00000000000000class Image: "" accelerometer = None button_a = None button_b = None compass = None display = None i2c = None def panic(): pass pin0 = None pin1 = None pin10 = None pin11 = None pin12 = None pin13 = None pin14 = None pin15 = None pin16 = None pin19 = None pin2 = None pin20 = None pin3 = None pin4 = None pin5 = None pin6 = None pin7 = None pin8 = None pin9 = None def reset(): pass def running_time(): pass def sleep(): pass spi = None def temperature(): pass uart = None thonny-3.2.7/thonny/plugins/microbit/api_stubs/utime.py0000644000175000017500000000027313611773167024370 0ustar annamaaannamaa00000000000000def sleep(): pass def sleep_ms(): pass def sleep_us(): pass def ticks_add(): pass def ticks_diff(): pass def ticks_ms(): pass def ticks_us(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/gc.py0000644000175000017500000000027213611773167023635 0ustar annamaaannamaa00000000000000def collect(): pass def disable(): pass def enable(): pass def isenabled(): pass def mem_alloc(): pass def mem_free(): pass def threshold(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/builtins.py0000644000175000017500000001304113611773167025073 0ustar annamaaannamaa00000000000000class ArithmeticError: "" class AssertionError: "" class AttributeError: "" class BaseException: "" class EOFError: "" Ellipsis = None class Exception: "" class GeneratorExit: "" class ImportError: "" class IndentationError: "" class IndexError: "" class KeyError: "" class KeyboardInterrupt: "" class LookupError: "" class MemoryError: "" class NameError: "" class NotImplementedError: "" class OSError: "" class OverflowError: "" class RuntimeError: "" class StopIteration: "" class SyntaxError: "" class SystemExit: "" class TypeError: "" class UnicodeError: "" class ValueError: "" class ZeroDivisionError: "" def abs(): pass def all(): pass def any(): pass def bin(): pass class bool: "" class bytearray: "" def append(): pass def extend(): pass class bytes: "" def count(): pass def endswith(): pass def find(): pass def format(): pass def index(): pass def isalpha(): pass def isdigit(): pass def islower(): pass def isspace(): pass def isupper(): pass def join(): pass def lower(): pass def lstrip(): pass def replace(): pass def rfind(): pass def rindex(): pass def rsplit(): pass def rstrip(): pass def split(): pass def startswith(): pass def strip(): pass def upper(): pass def callable(): pass def chr(): pass class classmethod: "" class dict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass def dir(): pass def divmod(): pass class enumerate: "" def eval(): pass def exec(): pass class filter: "" class float: "" class frozenset: "" def add(): pass def clear(): pass def copy(): pass def difference(): pass def difference_update(): pass def discard(): pass def intersection(): pass def intersection_update(): pass def isdisjoint(): pass def issubset(): pass def issuperset(): pass def pop(): pass def remove(): pass def symmetric_difference(): pass def symmetric_difference_update(): pass def union(): pass def update(): pass def getattr(): pass def globals(): pass def hasattr(): pass def hash(): pass def help(): pass def hex(): pass def id(): pass def input(): pass class int: "" def from_bytes(): pass def to_bytes(): pass def isinstance(): pass def issubclass(): pass def iter(): pass def len(): pass class list: "" def append(): pass def clear(): pass def copy(): pass def count(): pass def extend(): pass def index(): pass def insert(): pass def pop(): pass def remove(): pass def reverse(): pass def sort(): pass def locals(): pass class map: "" def max(): pass def min(): pass def next(): pass class object: "" def oct(): pass def open(): pass def ord(): pass def pow(): pass def print(): pass class range: "" def repr(): pass class reversed: "" def round(): pass class set: "" def add(): pass def clear(): pass def copy(): pass def difference(): pass def difference_update(): pass def discard(): pass def intersection(): pass def intersection_update(): pass def isdisjoint(): pass def issubset(): pass def issuperset(): pass def pop(): pass def remove(): pass def symmetric_difference(): pass def symmetric_difference_update(): pass def union(): pass def update(): pass def setattr(): pass class slice: "" def sorted(): pass class staticmethod: "" class str: "" def count(): pass def endswith(): pass def find(): pass def format(): pass def index(): pass def isalpha(): pass def isdigit(): pass def islower(): pass def isspace(): pass def isupper(): pass def join(): pass def lower(): pass def lstrip(): pass def replace(): pass def rfind(): pass def rindex(): pass def rsplit(): pass def rstrip(): pass def split(): pass def startswith(): pass def strip(): pass def upper(): pass def sum(): pass class super: "" class tuple: "" def count(): pass def index(): pass class type: "" class zip: "" thonny-3.2.7/thonny/plugins/microbit/api_stubs/this.py0000644000175000017500000000003013611773167024203 0ustar annamaaannamaa00000000000000def authors(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/radio.py0000644000175000017500000000047513611773167024347 0ustar annamaaannamaa00000000000000RATE_1MBIT = 0 RATE_250KBIT = 2 RATE_2MBIT = 1 def config(): pass def off(): pass def on(): pass def receive(): pass def receive_bytes(): pass def receive_bytes_into(): pass def receive_full(): pass def reset(): pass def send(): pass def send_bytes(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/antigravity.py0000644000175000017500000000002113611773167025575 0ustar annamaaannamaa00000000000000# Pseudo-package thonny-3.2.7/thonny/plugins/microbit/api_stubs/machine.py0000644000175000017500000000031413611773167024645 0ustar annamaaannamaa00000000000000def disable_irq(): pass def enable_irq(): pass def freq(): pass mem16 = None mem32 = None mem8 = None def reset(): pass def time_pulse_us(): pass def unique_id(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/music.py0000644000175000017500000000072213611773167024364 0ustar annamaaannamaa00000000000000BADDY = None BA_DING = None BIRTHDAY = None BLUES = None CHASE = None DADADADUM = None ENTERTAINER = None FUNERAL = None FUNK = None JUMP_DOWN = None JUMP_UP = None NYAN = None ODE = None POWER_DOWN = None POWER_UP = None PRELUDE = None PUNCHLINE = None PYTHON = None RINGTONE = None WAWAWAWAA = None WEDDING = None def get_tempo(): pass def pitch(): pass def play(): pass def reset(): pass def set_tempo(): pass def stop(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/collections.py0000644000175000017500000000062213611773167025561 0ustar annamaaannamaa00000000000000class OrderedDict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass def namedtuple(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/array.py0000644000175000017500000000012413611773167024356 0ustar annamaaannamaa00000000000000class array: "" def append(): pass def extend(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/ucollections.py0000644000175000017500000000062213611773167025746 0ustar annamaaannamaa00000000000000class OrderedDict: "" def clear(): pass def copy(): pass def fromkeys(): pass def get(): pass def items(): pass def keys(): pass def pop(): pass def popitem(): pass def setdefault(): pass def update(): pass def values(): pass def namedtuple(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/struct.py0000644000175000017500000000020313611773167024562 0ustar annamaaannamaa00000000000000def calcsize(): pass def pack(): pass def pack_into(): pass def unpack(): pass def unpack_from(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/micropython.py0000644000175000017500000000033213611773167025614 0ustar annamaaannamaa00000000000000def const(): pass def heap_lock(): pass def heap_unlock(): pass def kbd_intr(): pass def mem_info(): pass def opt_level(): pass def qstr_info(): pass def stack_use(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/audio.py0000644000175000017500000000020613611773167024342 0ustar annamaaannamaa00000000000000class AudioFrame: "" def copyfrom(): pass def is_playing(): pass def play(): pass def stop(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/neopixel.py0000644000175000017500000000012413611773167025063 0ustar annamaaannamaa00000000000000class NeoPixel: "" def clear(): pass def show(): pass thonny-3.2.7/thonny/plugins/microbit/api_stubs/sys.py0000644000175000017500000000024413611773167024061 0ustar annamaaannamaa00000000000000byteorder = "little" def exit(): pass implementation = None platform = "microbit" def print_exception(): pass version = "3.4.0" version_info = None thonny-3.2.7/thonny/plugins/microbit/api_stubs/math.py0000644000175000017500000000115113611773167024172 0ustar annamaaannamaa00000000000000def acos(): pass def asin(): pass def atan(): pass def atan2(): pass def ceil(): pass def copysign(): pass def cos(): pass def degrees(): pass e = 2.71828 def exp(): pass def fabs(): pass def floor(): pass def fmod(): pass def frexp(): pass def isfinite(): pass def isinf(): pass def isnan(): pass def ldexp(): pass def log(): pass def modf(): pass pi = 3.14159 def pow(): pass def radians(): pass def sin(): pass def sqrt(): pass def tan(): pass def trunc(): pass thonny-3.2.7/thonny/plugins/base_ui_themes.py0000644000175000017500000005373313611773167022431 0ustar annamaaannamaa00000000000000from typing import Callable, Dict, Union # @UnusedImport from thonny import get_workbench from thonny.misc_utils import running_on_linux, running_on_windows, running_on_mac_os from thonny.workbench import BasicUiThemeSettings, CompoundUiThemeSettings def scale(value) -> float: # dimensions in this module were designed with a 1.67 scale return get_workbench().scale(value / 1.67) def _treeview_settings() -> BasicUiThemeSettings: light_blue = "#ADD8E6" light_grey = "#D3D3D3" if running_on_linux() or running_on_mac_os(): bg_sel_focus = light_blue fg_sel_focus = "black" fg_sel_notfocus = "black" else: bg_sel_focus = "SystemHighlight" fg_sel_focus = "SystemHighlightText" fg_sel_notfocus = "SystemWindowText" return { "Treeview": { "configure": {"font": "TreeviewFont"}, "map": { "background": [ ("selected", "focus", bg_sel_focus), ("selected", "!focus", light_grey), ], "foreground": [ ("selected", "focus", fg_sel_focus), ("selected", "!focus", fg_sel_notfocus), ], }, "layout": [ # get rid of borders ("Treeview.treearea", {"sticky": "nswe"}) ], }, "treearea": {"configure": {"borderwidth": 0}}, } def _menubutton_settings() -> BasicUiThemeSettings: return { "TMenubutton": { "configure": {"padding": scale(14)}, "layout": [ ("Menubutton.dropdown", {"side": "right", "sticky": "ns"}), ( "Menubutton.button", { "children": [ # ('Menubutton.padding', {'children': [ ("Menubutton.label", {"sticky": ""}) # ], 'expand': '1', 'sticky': 'we'}) ], "expand": "1", "sticky": "nswe", }, ), ], } } def _paned_window_settings() -> BasicUiThemeSettings: return {"Sash": {"configure": {"sashthickness": scale(10)}}} def _menu_settings() -> BasicUiThemeSettings: return {"Menubar": {"configure": {"activeborderwidth": 0, "relief": "flat"}}} def _text_settings() -> BasicUiThemeSettings: return { "Text": { "configure": { "background": "SystemWindow" if running_on_windows() else "white", "foreground": "SystemWindowText" if running_on_windows() else "black", } }, "Syntax.Text": {"map": {"background": [("readonly", "Yellow")]}}, "Gutter": {"configure": {"background": "#e0e0e0", "foreground": "#999999"}}, } def _label_settings() -> BasicUiThemeSettings: return {"Url.TLabel": {"configure": {"foreground": "DarkBlue"}}} def _button_notebook_settings() -> BasicUiThemeSettings: # Adapted from https://github.com/python/cpython/blob/2.7/Demo/tkinter/ttk/notebook_closebtn.py return { "closebutton": { "element create": ( "image", "img_close", ("active", "pressed", "!disabled", "img_close_active"), ("active", "!disabled", "img_close_active"), {"padding": scale(2), "sticky": ""}, ) }, "ButtonNotebook.TNotebook.Tab": { "layout": [ ( "Notebook.tab", { "sticky": "nswe", "children": [ ( "Notebook.padding", { "side": "top", "sticky": "nswe", "children": [ ( "Notebook.focus", { "side": "left", "sticky": "nswe", "children": [ ( "Notebook.label", {"side": "left", "sticky": ""}, ) ], }, ), ("Notebook.closebutton", {"side": "right", "sticky": ""}), ], }, ) ], }, ) ] }, } def clam() -> BasicUiThemeSettings: # Transcribed from https://github.com/tcltk/tk/blob/master/library/ttk/clamTheme.tcl defaultfg = "#000000" disabledfg = "#999999" frame = "#dcdad5" window = "#ffffff" dark = "#cfcdc8" darker = "#bab5ab" darkest = "#9e9a91" lighter = "#eeebe7" selectbg = "#4a6984" selectfg = "#ffffff" altindicator = "#5895bc" disabledaltindicator = "#a0a0a0" return { ".": { "configure": { "background": frame, "foreground": defaultfg, "bordercolor": darkest, "darkcolor": dark, "lightcolor": lighter, "troughcolor": darker, "selectbackground": selectbg, "selectforeground": selectfg, "selectborderwidth": 0, "font": "TkDefaultFont", }, "map": { "background": [("disabled", frame), ("active", lighter)], "foreground": [("disabled", disabledfg)], "selectbackground": [("!focus", darkest)], "selectforeground": [("!focus", "white")], }, }, "TButton": { "configure": { "anchor": "center", "width": scale(11), "padding": scale(5), "relief": "raised", }, "map": { "background": [("disabled", frame), ("pressed", darker), ("active", lighter)], "lightcolor": [("pressed", darker)], "darkcolor": [("pressed", darker)], "bordercolor": [("alternate", "#000000")], }, }, "Toolbutton": { "configure": {"anchor": "center", "padding": scale(2), "relief": "flat"}, "map": { "relief": [ ("disabled", "flat"), ("selected", "sunken"), ("pressed", "sunken"), ("active", "raised"), ], "background": [("disabled", frame), ("pressed", darker), ("active", lighter)], "lightcolor": [("pressed", darker)], "darkcolor": [("pressed", darker)], }, }, "TCheckbutton": { "configure": { "indicatorbackground": "#ffffff", "indicatormargin": [scale(1), scale(1), scale(6), scale(1)], "padding": scale(2), }, "map": { "indicatorbackground": [ ("pressed", frame), ("!disabled", "alternate", altindicator), ("disabled", "alternate", disabledaltindicator), ("disabled", frame), ] }, }, # TRadiobutton has same style as TCheckbutton "TRadiobutton": { "configure": { "indicatorbackground": "#ffffff", "indicatormargin": [scale(1), scale(1), scale(6), scale(1)], "padding": scale(2), }, "map": { "indicatorbackground": [ ("pressed", frame), ("!disabled", "alternate", altindicator), ("disabled", "alternate", disabledaltindicator), ("disabled", frame), ] }, }, "TMenubutton": {"configure": {"width": scale(11), "padding": scale(5), "relief": "raised"}}, "TEntry": { "configure": {"padding": scale(1), "insertwidth": scale(1)}, "map": { "background": [("readonly", frame)], "bordercolor": [("focus", selectbg)], "lightcolor": [("focus", "#6f9dc6")], "darkcolor": [("focus", "#6f9dc6")], }, }, "TCombobox": { "configure": { "padding": [scale(4), scale(2), scale(2), scale(2)], "insertwidth": scale(1), }, "map": { "background": [("active", lighter), ("pressed", lighter)], "fieldbackground": [("readonly", "focus", selectbg), ("readonly", frame)], "foreground": [("readonly", "focus", selectfg)], "arrowcolor": [("disabled", disabledfg)], }, }, "ComboboxPopdownFrame": {"configure": {"relief": "solid", "borderwidth": scale(1)}}, "TSpinbox": { "configure": {"arrowsize": scale(10), "padding": [scale(2), 0, scale(10), 0]}, "map": {"background": [("readonly", frame)], "arrowcolor": [("disabled", disabledfg)]}, }, "TNotebook.Tab": { "configure": {"padding": [scale(6), scale(2), scale(6), scale(2)]}, "map": { "padding": [("selected", [scale(6), scale(4), scale(6), scale(4)])], "background": [("selected", frame), ("", darker)], "lightcolor": [("selected", lighter), ("", dark)], }, }, "Treeview": { "configure": {"background": window}, "map": { "background": [ ("disabled", frame), ("!disabled", "!selected", window), ("selected", selectbg), ], "foreground": [ ("disabled", disabledfg), ("!disabled", "!selected", defaultfg), ("selected", selectfg), ], }, }, # Treeview heading "Heading": { "configure": { "font": "TkHeadingFont", "relief": "raised", "padding": [scale(3), scale(3), scale(3), scale(3)], } }, "TLabelframe": {"configure": {"labeloutside": True, "labelmargins": [0, 0, 0, scale(4)]}}, "TProgressbar": {"configure": {"background": frame}}, "Sash": {"configure": {"sashthickness": scale(6), "gripcount": 10}}, } def xpnative() -> BasicUiThemeSettings: # Transcribed from https://github.com/tcltk/tk/blob/master/library/ttk/xpTheme.tcl return { ".": { "configure": { "background": "SystemButtonFace", "foreground": "SystemWindowText", "selectbackground": "SystemHighlight", "selectforeground": "SystemHighlightText", "font": "TkDefaultFont", }, "map": {"foreground": [("disabled", "SystemGrayText")]}, }, "TButton": { "configure": {"anchor": "center", "width": scale(11), "padding": [scale(1), scale(1)]} }, "Toolbutton": {"configure": {"padding": [scale(4), scale(4)]}}, "TCheckbutton": {"configure": {"padding": scale(2)}}, # TRadiobutton has same style as TCheckbutton "TRadiobutton": {"configure": {"padding": scale(2)}}, "TMenubutton": {"configure": {"padding": [scale(8), scale(4)]}}, "TEntry": { "configure": {"padding": [scale(2), scale(2), scale(2), scale(4)]}, "map": { "selectbackground": [("!focus", "SystemWindow")], "selectforeground": [("!focus", "SystemWindowText")], }, }, "TCombobox": { "configure": {"padding": scale(2)}, "map": { "selectbackground": [("!focus", "SystemWindow")], "selectforeground": [("!focus", "SystemWindowText")], "foreground": [ ("disabled", "SystemGrayText"), ("readonly", "focus", "SystemHighlightText"), ], "focusfill": [("readonly", "focus", "SystemHighlight")], }, }, "ComboboxPopdownFrame": {"configure": {"relief": "solid", "borderwidth": scale(1)}}, "TSpinbox": { "configure": {"padding": [scale(2), 0, scale(14), 0]}, "map": { "selectbackground": [("!focus", "SystemWindow")], "selectforeground": [("!focus", "SystemWindowText")], }, }, "TNotebook": {"configure": {"tabmargins": [scale(2), scale(2), scale(2), 0]}}, "TNotebook.Tab": { "map": {"expand": [("selected", [scale(2), scale(2), scale(2), scale(2)])]} }, "Treeview": { "configure": {"background": "SystemWindow"}, "map": { "background": [ ("disabled", "SystemButtonFace"), ("!disabled", "!selected", "SystemWindow"), ("selected", "SystemHighlight"), ], "foreground": [ ("disabled", "SystemGrayText"), ("!disabled", "!selected", "SystemWindowText"), ("selected", "SystemHighlightText"), ], }, }, "Heading": {"configure": {"font": "TkHeadingFont", "relief": "raised"}}, # Treeview heading "TLabelframe.Label": {"configure": {"foreground": "#0046d5"}}, } def aqua() -> BasicUiThemeSettings: # https://github.com/tcltk/tk/blob/master/library/ttk/aquaTheme.tcl return { ".": { "configure": { "font": "TkDefaultFont", "background": "systemWindowBody", "foreground": "systemModelessDialogActiveText", "selectbackground": "systemHighlight", "selectforeground": "systemModelessDialogActiveText", "selectborderwidth": 0, "insertwidth": 1, "stipple": "", }, "map": { "foreground": [ ("disabled", "systemModelessDialogInactiveText"), ("background", "systemModelessDialogInactiveText"), ], "selectbackground": [ ("background", "systemHighlightSecondary"), ("!focus", "systemHighlightSecondary"), ], "selectforeground": [ ("background", "systemModelessDialogInactiveText"), ("!focus", "systemDialogActiveText"), ], }, }, "TButton": {"configure": {"anchor": "center", "width": "6"}}, "Toolbutton": {"configure": {"padding": 4}}, "TNotebook": { "configure": {"tabmargins": [10, 0], "tabposition": "n", "padding": [18, 8, 18, 17]} }, "TNotebook.Tab": {"configure": {"padding": [12, 3, 12, 2]}}, "TCombobox": {"configure": {"postoffset": [5, -2, -10, 0]}}, "Heading": {"configure": {"font": "TkHeadingFont"}}, "Treeview": { "configure": {"rowheight": 18, "background": "white"}, "map": { "background": [ ("disabled", "systemDialogBackgroundInactive"), ("!disabled", "!selected", "systemWindowBody"), ("selected", "background", "systemHighlightSecondary"), ("selected", "systemHighlight"), ], "foreground": [ ("disabled", "systemModelessDialogInactiveText"), ("!disabled", "!selected", "black"), ("selected", "systemModelessDialogActiveText"), ], }, }, "TProgressbar": {"configure": {"period": 100, "maxphase": 255}}, "Labelframe": {"configure": {"labeloutside": True, "labelmargins": [14, 0, 14, 4]}}, } def windows() -> CompoundUiThemeSettings: return [ xpnative(), _treeview_settings(), _menubutton_settings(), _paned_window_settings(), _menu_settings(), _text_settings(), _label_settings(), _button_notebook_settings(), { "TNotebook": { "configure": { # With tabmargins I can get a gray line below tab, which separates # tab content from label "tabmargins": [scale(2), scale(2), scale(2), scale(2)] } }, "Tab": {"configure": {"padding": [scale(3), scale(1), scale(3), 0]}}, "ButtonNotebook.TNotebook.Tab": { "configure": {"padding": (scale(4), scale(1), scale(1), 0)} }, "TCombobox": { "map": { "selectbackground": [ ("readonly", "!focus", "SystemWindow"), ("readonly", "focus", "SystemHighlight"), ], "selectforeground": [ ("readonly", "!focus", "SystemWindowText"), ("readonly", "focus", "SystemHighlightText"), ], } }, "Listbox": { "configure": { "background": "SystemWindow", "foreground": "SystemWindowText", "disabledforeground": "SystemGrayText", "highlightbackground": "SystemActiveBorder", "highlightcolor": "SystemActiveBorder", "highlightthickness": scale(1), } }, "ViewBody.TFrame": { "configure": { "background": "SystemButtonFace" # to create the fine line below toolbar } }, "ViewToolbar.TFrame": {"configure": {"background": "SystemWindow"}}, "ViewToolbar.Toolbutton": {"configure": {"background": "SystemWindow"}}, "ViewTab.TLabel": { "configure": {"background": "SystemWindow", "padding": [scale(5), 0]} }, "ViewToolbar.TLabel": { "configure": {"background": "SystemWindow", "padding": [scale(5), 0]} }, "ViewToolbar.Link.TLabel": { "configure": {"background": "SystemWindow", "padding": [scale(5), 0]} }, "Active.ViewTab.TLabel": { "configure": { # "font" : "BoldTkDefaultFont", "relief": "sunken", "borderwidth": scale(1), } }, "Inactive.ViewTab.TLabel": {"configure": {"font": "UnderlineTkDefaultFont"}}, }, ] def enhanced_clam() -> CompoundUiThemeSettings: return [ clam(), _treeview_settings(), _menubutton_settings(), _paned_window_settings(), _menu_settings(), _text_settings(), _label_settings(), _button_notebook_settings(), { "ButtonNotebook.Tab": { "configure": {"padding": (scale(6), scale(4), scale(2), scale(3))} }, "TScrollbar": { "configure": { "gripcount": 0, "arrowsize": scale(14), # "arrowcolor" : "DarkGray" # "width" : 99 # no effect } }, "TCombobox": { "configure": {"arrowsize": scale(14)}, "map": { "selectbackground": [("readonly", "!focus", "#dcdad5")], "selectforeground": [("readonly", "!focus", "#000000")], }, }, "TCheckbutton": {"configure": {"indicatorsize": scale(12)}}, "TRadiobutton": {"configure": {"indicatorsize": scale(12)}}, "Listbox": { "configure": { "background": "white", "foreground": "black", "disabledforeground": "#999999", "highlightbackground": "#4a6984", "highlightcolor": "#4a6984", "highlightthickness": scale(1), } }, }, ] def enhanced_aqua() -> CompoundUiThemeSettings: return [ _treeview_settings(), _menubutton_settings(), # _paned_window_settings(), _menu_settings(), { "TPanedWindow": {"configure": {"background": "systemDialogBackgroundActive"}}, "TFrame": {"configure": {"background": "systemDialogBackgroundActive"}}, "Tab": {"map": {"foreground": [("selected", "white")]}}, }, ] def load_plugin() -> None: from tkinter import ttk original_themes = ttk.Style().theme_names() # load all base themes for name in original_themes: settings = {} # type: Union[Dict, Callable[[], Dict]] if name == "clam": settings = clam elif name == "xpnative": settings = xpnative elif name == "aqua": settings = aqua get_workbench().add_ui_theme(name, None, settings) get_workbench().add_ui_theme( "Enhanced Clam", "clam", enhanced_clam, {"tab-close": "tab-close-clam", "tab-close-active": "tab-close-active-clam"}, ) if "xpnative" in original_themes: get_workbench().add_ui_theme("Windows", "xpnative", windows) if "aqua" in original_themes: get_workbench().add_ui_theme("Kind of Aqua", "aqua", enhanced_aqua) thonny-3.2.7/thonny/token_utils.py0000644000175000017500000000325213611773167020323 0ustar annamaaannamaa00000000000000import builtins import keyword def matches_any(name, alternates): "Return a named group pattern matching list of alternates." return "(?P<%s>" % name + "|".join(alternates) + ")" KEYWORD = r"\b" + matches_any("keyword", keyword.kwlist) + r"\b" _builtinlist = [ str(name) for name in dir(builtins) if not name.startswith("_") and name not in keyword.kwlist ] # TODO: move builtin handling to global-local BUILTIN = r"([^.'\"\\#]\b|^)" + matches_any("builtin", _builtinlist) + r"\b" NUMBER = matches_any("number", [r"\b(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?"]) # TODO: would it make regex too slow? VARIABLE = matches_any("VARIABLE", [...]) COMMENT = matches_any("comment", [r"#[^\n]*"]) MAGIC_COMMAND = matches_any("magic", [r"^%[^\n]*"]) # used only in shell STRINGPREFIX = r"(\br|u|ur|R|U|UR|Ur|uR|b|B|br|Br|bR|BR|rb|rB|Rb|RB|f|F|fr|Fr|fR|FR|rf|rF|Rf|RF)?" SQSTRING_OPEN = STRINGPREFIX + r"'[^'\\\n]*(\\.[^'\\\n]*)*\n?" SQSTRING_CLOSED = STRINGPREFIX + r"'[^'\\\n]*(\\.[^'\\\n]*)*'" DQSTRING_OPEN = STRINGPREFIX + r'"[^"\\\n]*(\\.[^"\\\n]*)*\n?' DQSTRING_CLOSED = STRINGPREFIX + r'"[^"\\\n]*(\\.[^"\\\n]*)*"' SQ3STRING = STRINGPREFIX + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?" DQ3STRING = STRINGPREFIX + r'"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?' SQ3DELIMITER = STRINGPREFIX + "'''" DQ3DELIMITER = STRINGPREFIX + '"""' COMMENT_WITH_Q3DELIMITER = matches_any("q3comment", [r"#[^\n]*('''|\"\"\")[^\n]*"]) STRING_OPEN = matches_any("open_string", [SQSTRING_OPEN, DQSTRING_OPEN]) STRING_CLOSED = matches_any("string", [SQSTRING_CLOSED, DQSTRING_CLOSED]) STRING3_DELIMITER = matches_any("DELIMITER3", [SQ3DELIMITER, DQ3DELIMITER]) STRING3 = matches_any("string3", [DQ3STRING, SQ3STRING]) thonny-3.2.7/thonny/shell.py0000644000175000017500000021312413611773167017073 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- from _tkinter import TclError import logging import os.path import re from tkinter import ttk import traceback from thonny import get_runner, get_workbench, memory, roughparse, ui_utils, running from thonny.codeview import PythonText, get_syntax_options_for_tag from thonny.common import InlineCommand, ToplevelCommand, ToplevelResponse from thonny.misc_utils import construct_cmd_line, parse_cmd_line, running_on_mac_os, shorten_repr from thonny.tktextext import index2line, TextFrame, TweakableText from thonny.ui_utils import ( EnhancedTextWithLogging, scrollbar_style, select_sequence, TextMenu, create_tooltip, show_dialog, lookup_style_option, CommonDialog, tr_btn, ) import tkinter as tk import webbrowser from thonny.running import EDITOR_CONTENT_TOKEN _CLEAR_SHELL_DEFAULT_SEQ = select_sequence("", "") # NB! Don't add parens without refactoring split procedure! OUTPUT_SPLIT_REGEX = re.compile(r"(\x1B\[[0-?]*[ -/]*[@-~]|[\a\b\r])") NUMBER_SPLIT_REGEX = re.compile(r"((? 1 and self.text.winfo_width() > 5: get_workbench().set_option("view.shell_sash_position", self.sash_coord(0)[0]) class ShellMenu(TextMenu): def __init__(self, target, view): self.view = view TextMenu.__init__(self, target) def add_extra_items(self): self.add_separator() self.add_command(label=_("Clear"), command=self.text._clear_shell) def toggle_from_menu(): # I don't like that Tk menu toggles checbutton variable # automatically before calling the handler. # So I revert the toggle before calling the actual handler. # This way the handler doesn't have to worry whether it # needs to toggle the variable or not, and it can choose to # decline the toggle. self.view.plotter_visibility_var.set(not self.view.plotter_visibility_var.get()) self.view.toggle_plotter() self.add_checkbutton( label=_("Show Plotter"), command=toggle_from_menu, variable=self.view.plotter_visibility_var, ) def selection_is_read_only(self): return not self.text.selection_is_writable() class BaseShellText(EnhancedTextWithLogging, PythonText): """Passive version of ShellText. Used also for preview""" def __init__(self, master, view=None, cnf={}, **kw): self.view = view kw["tabstyle"] = "wordprocessor" super().__init__(master, cnf, **kw) self._command_history = ( [] ) # actually not really history, because each command occurs only once self._command_history_current_index = None # logs of IO events for current toplevel block # (enables undoing and redoing the events) self._applied_io_events = [] self._queued_io_events = [] self._images = set() self._ansi_foreground = None self._ansi_background = None self._ansi_inverse = False self._ansi_intensity = None self._ansi_italic = False self._ansi_underline = False self._ansi_conceal = False self._ansi_strikethrough = False self._io_cursor_offset = 0 self._squeeze_buttons = set() self.update_tty_mode() self.bind("", self._arrow_up, True) self.bind("", self._arrow_down, True) self.bind("", self._text_key_press, True) self.bind("", self._text_key_release, True) prompt_font = tk.font.nametofont("BoldEditorFont") x_padding = 4 io_vert_spacing = 10 io_indent = 16 + x_padding self.io_indent = io_indent code_indent = prompt_font.measure(">>> ") + x_padding self.tag_configure("command", lmargin1=code_indent, lmargin2=code_indent) self.tag_configure( "io", lmargin1=io_indent, lmargin2=io_indent, rmargin=io_indent, font="IOFont" ) self.update_margin_color() self.tag_configure("after_io_or_value", spacing1=io_vert_spacing) self.tag_configure("before_io", spacing3=io_vert_spacing) self.tag_configure("prompt", lmargin1=x_padding, lmargin2=x_padding) self.tag_configure("value", lmargin1=x_padding, lmargin2=x_padding) self.tag_configure("restart_line", wrap="none", lmargin1=x_padding, lmargin2=x_padding) self.tag_configure("welcome", lmargin1=x_padding, lmargin2=x_padding) # Underline on the font looks better than underline on the tag, # therefore Shell doesn't use configured "hyperlink" style directly hyperlink_opts = get_syntax_options_for_tag("hyperlink").copy() if hyperlink_opts.get("underline"): hyperlink_opts["font"] = "UnderlineIOFont" del hyperlink_opts["underline"] self.tag_configure("io_hyperlink", **hyperlink_opts) # create 3 marks: input_start shows the place where user entered but not-yet-submitted # input starts, output_end shows the end of last output, # output_insert shows where next incoming program output should be inserted self.mark_set("input_start", "end-1c") self.mark_gravity("input_start", tk.LEFT) self.mark_set("output_end", "end-1c") self.mark_gravity("output_end", tk.LEFT) self.mark_set("output_insert", "end-1c") self.mark_gravity("output_insert", tk.RIGHT) self.active_object_tags = set() self.update_tabs() self.tag_raise("io_hyperlink") self.tag_raise("underline") self.tag_raise("strikethrough") self.tag_raise("intense_io") self.tag_raise("italic_io") self.tag_raise("intense_italic_io") self.tag_raise("sel") def submit_command(self, cmd_line, tags): # assert get_runner().is_waiting_toplevel_command() self.delete("input_start", "end") self.insert("input_start", cmd_line, tags) self.see("end") self.mark_set("insert", "end") self._try_submit_input() def _handle_input_request(self, msg): self._ensure_visible() self.focus_set() self.mark_set("insert", "end") self.tag_remove("sel", "1.0", tk.END) self._try_submit_input() # try to use leftovers from previous request self.see("end") def _handle_program_output(self, msg): # Discard but not too often, as toplevel response will discard anyway if int(float(self.index("end"))) > get_workbench().get_option("shell.max_lines") + 100: self._discard_old_content() self._ensure_visible() self._append_to_io_queue(msg.data, msg.stream_name) if not self._applied_io_events: # this is first line of io, add padding below command line self.tag_add("before_io", "output_insert -1 line linestart") self._update_visible_io(None) def _handle_toplevel_response(self, msg: ToplevelResponse) -> None: if msg.get("error"): self._insert_text_directly(msg["error"] + "\n", ("toplevel", "stderr")) self._ensure_visible() if "user_exception" in msg: self._show_user_exception(msg["user_exception"]) self._ensure_visible() welcome_text = msg.get("welcome_text") if welcome_text and welcome_text: preceding = self.get("output_insert -1 c", "output_insert") if preceding.strip() and not preceding.endswith("\n"): self._insert_text_directly("\n") self._insert_text_directly(welcome_text, ("welcome",)) if "value_info" in msg: num_stripped_question_marks = getattr(msg, "num_stripped_question_marks", 0) if num_stripped_question_marks > 0: # show the value in object inspector get_workbench().event_generate("ObjectSelect", object_id=msg["value_info"].id) else: # show the value in shell value_repr = shorten_repr(msg["value_info"].repr, 10000) if value_repr != "None": if get_workbench().in_heap_mode(): value_repr = memory.format_object_id(msg["value_info"].id) object_tag = "object_" + str(msg["value_info"].id) self._insert_text_directly(value_repr + "\n", ("toplevel", "value", object_tag)) if running_on_mac_os(): sequence = "" else: sequence = "" self.tag_bind( object_tag, sequence, lambda _: get_workbench().event_generate( "ObjectSelect", object_id=msg["value_info"].id ), ) self.active_object_tags.add(object_tag) self.mark_set("output_end", self.index("end-1c")) self._discard_old_content() self._update_visible_io(None) self._reset_ansi_attributes() self._io_cursor_offset = 0 self._insert_prompt() self._try_submit_input() # Trying to submit leftover code (eg. second magic command) self.see("end") # import os # import psutil # process = psutil.Process(os.getpid()) # print("MEM", process.memory_info().rss // (1024*1024)) def _handle_fancy_debugger_progress(self, msg): if msg.in_present or msg.io_symbol_count is None: self._update_visible_io(None) else: self._update_visible_io(msg.io_symbol_count) def _get_squeeze_threshold(self): return get_workbench().get_option("shell.squeeze_threshold") def _append_to_io_queue(self, data, stream_name): if self.tty_mode: # Make sure ANSI CSI codes are stored as separate events # TODO: try to complete previously submitted incomplete code parts = re.split(OUTPUT_SPLIT_REGEX, data) for part in parts: if part: # split may produce empty string in the beginning or start # split the data so that very long lines separated for block in re.split("(.{%d,})" % (self._get_squeeze_threshold() + 1), part): if block: self._queued_io_events.append((block, stream_name)) else: self._queued_io_events.append((data, stream_name)) def _update_visible_io(self, target_num_visible_chars): current_num_visible_chars = sum(map(lambda x: len(x[0]), self._applied_io_events)) if ( target_num_visible_chars is not None and target_num_visible_chars < current_num_visible_chars ): # hard to undo complex renderings (squeezed texts and ANSI codes) # easier to clean everything and start again self._queued_io_events = self._applied_io_events + self._queued_io_events self._applied_io_events = [] self.direct_delete("command_io_start", "output_end") current_num_visible_chars = 0 self._reset_ansi_attributes() while self._queued_io_events and current_num_visible_chars != target_num_visible_chars: data, stream_name = self._queued_io_events.pop(0) if target_num_visible_chars is not None: leftover_count = current_num_visible_chars + len(data) - target_num_visible_chars if leftover_count > 0: # add suffix to the queue self._queued_io_events.insert(0, (data[-leftover_count:], stream_name)) data = data[:-leftover_count] self._apply_io_event(data, stream_name) current_num_visible_chars += len(data) self.mark_set("output_end", self.index("end-1c")) self.see("end") def _apply_io_event(self, data, stream_name, extra_tags=set()): if not data: return original_data = data if self.tty_mode and re.match(OUTPUT_SPLIT_REGEX, data): if data == "\a": get_workbench().bell() elif data == "\b": self._change_io_cursor_offset(-1) elif data == "\r": self._change_io_cursor_offset("line") elif data.endswith("D") or data.endswith("C"): self._change_io_cursor_offset_csi(data) elif stream_name == "stdout": # According to https://github.com/tartley/colorama/blob/master/demos/demo04.py # codes sent to stderr shouldn't affect later output in stdout # It makes sense, but Ubuntu terminal does not confirm it. # For now I'm just trimming stderr color codes self._update_ansi_attributes(data) else: tags = extra_tags | {"io", stream_name} if stream_name == "stdout" and self.tty_mode: tags |= self._get_ansi_tags() non_url_length = len(data) for url_match in SIMPLE_URL_SPLIT_REGEX.finditer(data): non_url_length -= url_match.end() - url_match.start() if non_url_length > self._get_squeeze_threshold() and "\n" not in data: self._io_cursor_offset = 0 # ignore the effect of preceding \r and \b button_text = data[:40] + " …" btn = tk.Label( self, text=button_text, # width=len(button_text), cursor="arrow", borderwidth=2, relief="raised", font="IOFont", ) btn.bind("<1>", lambda e: self._show_squeezed_text(btn), True) btn.contained_text = data btn.tags = tags self._squeeze_buttons.add(btn) create_tooltip(btn, "%d characters squeezed. " % len(data) + "Click for details.") # TODO: refactor # (currently copied from insert_text_directly) self.mark_gravity("input_start", tk.RIGHT) self.mark_gravity("output_insert", tk.RIGHT) self.window_create("output_insert", window=btn) for tag_name in tags: self.tag_add(tag_name, "output_insert -1 chars") data = "" elif self._io_cursor_offset < 0: overwrite_len = min(len(data), -self._io_cursor_offset) if 0 <= data.find("\n") < overwrite_len: overwrite_len = data.find("\n") overwrite_data = data[:overwrite_len] self.direct_insert( "output_insert -%d chars" % -self._io_cursor_offset, overwrite_data, tuple(tags) ) del_start = self.index("output_insert -%d chars" % -self._io_cursor_offset) del_end = self.index( "output_insert -%d chars" % (-self._io_cursor_offset - overwrite_len) ) self.direct_delete(del_start, del_end) # compute leftover data to be printed normally data = data[overwrite_len:] if "\n" in data: # cursor offset doesn't apply on new line self._io_cursor_offset = 0 else: # offset becomes closer to 0 self._io_cursor_offset + overwrite_len elif self._io_cursor_offset > 0: # insert spaces before actual data # NB! Print without formatting tags self._insert_text_directly(" " * self._io_cursor_offset, ("io", stream_name)) self._io_cursor_offset = 0 if data: # if any data is still left, then this should be output normally self._insert_text_directly(data, tuple(tags)) self._applied_io_events.append((original_data, stream_name)) def _show_squeezed_text(self, button): dlg = SqueezedTextDialog(self, button) show_dialog(dlg) def _change_io_cursor_offset_csi(self, marker): ints = re.findall(INT_REGEX, marker) if len(ints) != 1: logging.warn("bad CSI cursor positioning: %s", marker) # do nothing return try: delta = int(ints[0]) except ValueError: logging.warn("bad CSI cursor positioning: %s", marker) return if marker.endswith("D"): delta = -delta self._change_io_cursor_offset(delta) def _change_io_cursor_offset(self, delta): line = self.get("output_insert linestart", "output_insert") if delta == "line": self._io_cursor_offset = -len(line) else: self._io_cursor_offset += delta if self._io_cursor_offset < -len(line): # cap self._io_cursor_offset = -len(line) def _reset_ansi_attributes(self): self._ansi_foreground = None self._ansi_background = None self._ansi_inverse = False self._ansi_intensity = None self._ansi_italic = False self._ansi_underline = False self._ansi_conceal = False self._ansi_strikethrough = False def _update_ansi_attributes(self, marker): if not marker.endswith("m"): # ignore return codes = re.findall(INT_REGEX, marker) if not codes: self._reset_ansi_attributes() while codes: code = codes.pop(0) if code == "0": self._reset_ansi_attributes() elif code in ["1", "2"]: self._ansi_intensity = code elif code == "3": self._ansi_italic = True elif code == "4": self._ansi_underline = True elif code == "7": self._ansi_inverse = True elif code == "8": self._ansi_conceal = True elif code == "9": self._ansi_strikethrough = True elif code == "22": self._ansi_intensity = None elif code == "23": self._ansi_italic = False elif code == "24": self._ansi_underline = False elif code == "27": self._ansi_inverse = False elif code == "28": self._ansi_conceal = False elif code == "29": self._ansi_strikethrough = False if code in [ "30", "31", "32", "33", "34", "35", "36", "37", "90", "91", "92", "93", "94", "95", "96", "97", ]: self._ansi_foreground = code elif code == "39": self._ansi_foreground = None elif code in [ "40", "41", "42", "43", "44", "45", "46", "47", "100", "101", "102", "103", "104", "105", "106", "107", ]: self._ansi_background = code elif code == "49": self._ansi_background = None elif code in ["38", "48"]: # multipart code, ignore for now, # but make sure all arguments are ignored if not codes: # nothing follows, ie. invalid code break mode = codes.pop(0) if mode == "5": # 256-color code, just ignore for now if not codes: break codes = codes[1:] elif mode == "2": # 24-bit code, ignore if len(codes) < 3: # invalid code break codes = codes[3:] else: # ignore other codes pass def _get_ansi_tags(self): result = set() if self._ansi_foreground: fg = ANSI_COLOR_NAMES[self._ansi_foreground[-1]] if self._ansi_intensity == "1" or self._ansi_foreground[0] == "9": fg = "bright_" + fg elif self._ansi_intensity == "2": fg = "dim_" + fg else: fg = "fore" if self._ansi_intensity == "1": fg = "bright_" + fg elif self._ansi_intensity == "2": fg = "dim_" + fg if self._ansi_background: bg = ANSI_COLOR_NAMES[self._ansi_background[-1]] if self._ansi_background.startswith("10"): bg = "bright_" + bg else: bg = "back" if self._ansi_inverse: result.add(fg + "_bg") result.add(bg + "_fg") else: if fg != "fore": result.add(fg + "_fg") if bg != "back": result.add(bg + "_bg") if self._ansi_intensity == "1" and self._ansi_italic: result.add("intense_italic_io") elif self._ansi_intensity == "1": result.add("intense_io") elif self._ansi_italic: result.add("italic_io") if self._ansi_underline: result.add("underline") if self._ansi_strikethrough: result.add("strikethrough") return result def _insert_prompt(self): # if previous output didn't put a newline, then do it now if not self.index("output_insert").endswith(".0"): self._insert_text_directly("\n", ("io",)) prompt_tags = ("toplevel", "prompt") # if previous line has value or io then add little space prev_line = self.index("output_insert - 1 lines") prev_line_tags = self.tag_names(prev_line) if "io" in prev_line_tags or "value" in prev_line_tags: prompt_tags += ("after_io_or_value",) self._insert_text_directly(">>> ", prompt_tags) self.edit_reset() def _ensure_visible(self): if self.winfo_ismapped(): return focused_view = get_workbench().focus_get() get_workbench().show_view("ShellView") if focused_view is not None: focused_view.focus() def update_tabs(self): tab_chars = 8 tab_pixels = tk.font.nametofont("IOFont").measure("n" * tab_chars) offset = self.io_indent tabs = [offset] for _ in range(20): offset += tab_pixels tabs.append(offset) self.tag_configure("io", tabs=tabs, tabstyle="wordprocessor") def restart(self): self._insert_text_directly( # "\n============================== RESTART ==============================\n", "\n" + "─" * 200 + "\n", # "\n" + "═"*200 + "\n", ("magic", "restart_line"), ) def intercept_insert(self, index, txt, tags=()): # pylint: disable=arguments-differ if self._editing_allowed() and self._in_current_input_range(index): # self._print_marks("before insert") # I want all marks to stay in place self.mark_gravity("input_start", tk.LEFT) self.mark_gravity("output_insert", tk.LEFT) if get_runner().is_waiting_toplevel_command(): tags = tags + ("toplevel", "command") else: tags = tags + ("io", "stdin") EnhancedTextWithLogging.intercept_insert(self, index, txt, tags) if not get_runner().is_waiting_toplevel_command(): if not self._applied_io_events: # tag preceding command line differently self.tag_add("before_io", "input_start -1 lines linestart") self._try_submit_input() self.see("insert") else: get_workbench().bell() def intercept_delete(self, index1, index2=None, **kw): if index1 == "sel.first" and index2 == "sel.last" and not self.has_selection(): return if ( self._editing_allowed() and self._in_current_input_range(index1) and (index2 is None or self._in_current_input_range(index2)) ): self.direct_delete(index1, index2, **kw) else: get_workbench().bell() def selection_is_writable(self): try: if not self.has_selection(): return self._in_current_input_range(self.index("insert")) else: return self._in_current_input_range( self.index("sel.first") ) and self._in_current_input_range(self.index("sel.last")) except TclError: return True def perform_return(self, event): if get_runner().is_running(): # if we are fixing the middle of the input string and pressing ENTER # then we expect the whole line to be submitted not linebreak to be inserted # (at least that's how IDLE works) self.mark_set("insert", "end") # move cursor to the end # Do the return without auto indent EnhancedTextWithLogging.perform_return(self, event) self._try_submit_input() elif get_runner().is_waiting_toplevel_command(): # Same with editin middle of command, but only if it's a single line command whole_input = self.get("input_start", "end-1c") # asking the whole input if "\n" not in whole_input and self._code_is_ready_for_submission(whole_input): self.mark_set("insert", "end") # move cursor to the end # Do the return without auto indent EnhancedTextWithLogging.perform_return(self, event) else: # Don't want auto indent when code is ready for submission source = self.get("input_start", "insert") tail = self.get("insert", "end") if self._code_is_ready_for_submission(source + "\n", tail): # No auto-indent EnhancedTextWithLogging.perform_return(self, event) else: # Allow auto-indent PythonText.perform_return(self, event) self._try_submit_input() return "break" def on_secondary_click(self, event=None): super().on_secondary_click(event) if self.view: self.view.menu.tk_popup(event.x_root, event.y_root) def _in_current_input_range(self, index): try: return self.compare(index, ">=", "input_start") except Exception: return False def _insert_text_directly(self, txt, tags=()): def _insert(txt, tags): if txt != "": self.direct_insert("output_insert", txt, tags) def _insert_and_highlight_urls(txt, tags): parts = SIMPLE_URL_SPLIT_REGEX.split(txt) for i, part in enumerate(parts): if i % 2 == 0: _insert(part, tags) else: if part.startswith("data:image/"): token = ";base64," data = part[part.index(token) + len(token) :] try: img = tk.PhotoImage(data=data) self._images.add(img) # to avoit it being gc-d""" self.image_create("output_insert", image=img) for tag in tags: self.tag_add(tag, "output_insert -1 chars") except TclError: _insert(part, tags + ("io_hyperlink",)) else: _insert(part, tags + ("io_hyperlink",)) # I want the insertion to go before marks # self._print_marks("before output") self.mark_gravity("input_start", tk.RIGHT) self.mark_gravity("output_insert", tk.RIGHT) tags = tuple(tags) # Make stacktrace clickable if "stderr" in tags or "error" in tags: # show lines pointing to source lines as hyperlinks for line in txt.splitlines(True): parts = re.split(r"(File .* line \d+.*)$", line, maxsplit=1) if len(parts) == 3 and " 0: assert tail.strip() == "" self.delete("insert", "end-1c") # leftover text will be kept in widget, waiting for next request. start_index = self.index("input_start") end_index = self.index("input_start+{0}c".format(len(submittable_text))) # apply correct tags (if it's leftover then it doesn't have them yet) if get_runner().is_running(): self.tag_add("io", start_index, end_index) self.tag_add("stdin", start_index, end_index) else: self.tag_add("toplevel", start_index, end_index) self.tag_add("command", start_index, end_index) # update start mark for next input range self.mark_set("input_start", end_index) # Move output_insert mark after the requested_text # Leftover input, if any, will stay after output_insert, # so that any output that will come in before # next input request will go before leftover text self.mark_set("output_insert", end_index) # remove tags from leftover text for tag in ("io", "stdin", "toplevel", "command"): # don't remove magic, because otherwise I can't know it's auto self.tag_remove(tag, end_index, "end") self._submit_input(submittable_text) def _editing_allowed(self): return get_runner() is not None def _extract_submittable_input(self, input_text, tail): if get_runner().is_waiting_toplevel_command(): if input_text.endswith("\n"): if input_text.strip().startswith("%") or input_text.strip().startswith("!"): # if several magic command are submitted, then take only first return input_text[: input_text.index("\n") + 1] elif self._code_is_ready_for_submission(input_text, tail): return input_text else: return None else: return None elif get_runner().is_running(): i = 0 while True: if i >= len(input_text): return None elif input_text[i] == "\n": return input_text[: i + 1] else: i += 1 return None def _code_is_ready_for_submission(self, source, tail=""): # Ready to submit if ends with empty line # or is complete single-line code if tail.strip() != "": return False # First check if it has unclosed parens, unclosed string or ending with : or \ parser = roughparse.RoughParser(self.indent_width, self.tabwidth) parser.set_str(source.rstrip() + "\n") if parser.get_continuation_type() != roughparse.C_NONE or parser.is_block_opener(): return False # Multiline compound statements need to end with empty line to be considered # complete. lines = source.splitlines() # strip starting empty and comment lines while len(lines) > 0 and (lines[0].strip().startswith("#") or lines[0].strip() == ""): lines.pop(0) compound_keywords = ["if", "while", "for", "with", "try", "def", "class", "async", "await"] if len(lines) > 0: first_word = lines[0].strip().split()[0] if first_word in compound_keywords and not source.replace(" ", "").replace( "\t", "" ).endswith("\n\n"): # last line is not empty return False return True def _submit_input(self, text_to_be_submitted): logging.debug( "SHELL: submitting %r in state %s", text_to_be_submitted, get_runner().get_state() ) if get_runner().is_waiting_toplevel_command(): # register in history and count if text_to_be_submitted in self._command_history: self._command_history.remove(text_to_be_submitted) self._command_history.append(text_to_be_submitted) # meaning command selection is not in process self._command_history_current_index = None self.update_tty_mode() cmd_line = text_to_be_submitted.strip() try: if cmd_line.startswith("%"): parts = cmd_line.split(" ", maxsplit=1) if len(parts) == 2: args_str = parts[1].strip() else: args_str = "" argv = parse_cmd_line(cmd_line[1:]) command_name = argv[0] cmd_args = argv[1:] if len(cmd_args) >= 2 and cmd_args[0] == "-c": # move source argument to source attribute source = cmd_args[1] cmd_args = [cmd_args[0]] + cmd_args[2:] if source == EDITOR_CONTENT_TOKEN: source = ( get_workbench().get_editor_notebook().get_current_editor_content() ) else: source = None get_workbench().event_generate("MagicCommand", cmd_line=text_to_be_submitted) get_runner().send_command( ToplevelCommand( command_name, args=cmd_args, args_str=args_str, cmd_line=cmd_line, tty_mode=self.tty_mode, source=source, ) ) elif cmd_line.startswith("!"): argv = parse_cmd_line(cmd_line[1:]) get_workbench().event_generate("SystemCommand", cmd_line=text_to_be_submitted) get_runner().send_command( ToplevelCommand( "execute_system_command", argv=argv, cmd_line=cmd_line, tty_mode=self.tty_mode, ) ) else: get_runner().send_command( ToplevelCommand( "execute_source", source=text_to_be_submitted, tty_mode=self.tty_mode ) ) # remember the place where the output of this command started self.mark_set("command_io_start", "output_insert") self.mark_gravity("command_io_start", "left") # discard old io events self._applied_io_events = [] self._queued_io_events = [] except Exception: get_workbench().report_exception() self._insert_prompt() get_workbench().event_generate("ShellCommand", command_text=text_to_be_submitted) else: assert get_runner().is_running() get_runner().send_program_input(text_to_be_submitted) get_workbench().event_generate("ShellInput", input_text=text_to_be_submitted) self._applied_io_events.append((text_to_be_submitted, "stdin")) def _arrow_up(self, event): if not get_runner().is_waiting_toplevel_command(): return None if not self._in_current_input_range("insert"): return None insert_line = index2line(self.index("insert")) input_start_line = index2line(self.index("input_start")) if insert_line != input_start_line: # we're in the middle of a multiline command return None if len(self._command_history) == 0 or self._command_history_current_index == 0: # can't take previous command return "break" if self._command_history_current_index is None: self._command_history_current_index = len(self._command_history) - 1 else: self._command_history_current_index -= 1 cmd = self._command_history[self._command_history_current_index] if cmd[-1] == "\n": cmd = cmd[:-1] # remove the submission linebreak self._propose_command(cmd) return "break" def _arrow_down(self, event): if not get_runner().is_waiting_toplevel_command(): return None if not self._in_current_input_range("insert"): return None insert_line = index2line(self.index("insert")) last_line = index2line(self.index("end-1c")) if insert_line != last_line: # we're in the middle of a multiline command return None if ( len(self._command_history) == 0 or self._command_history_current_index is None or self._command_history_current_index >= len(self._command_history) - 1 ): # can't take next command self._command_history_current_index = len(self._command_history) self._propose_command("") return "break" if self._command_history_current_index is None: self._command_history_current_index = len(self._command_history) - 1 else: self._command_history_current_index += 1 self._propose_command( self._command_history[self._command_history_current_index].strip("\n") ) return "break" def _propose_command(self, cmd_line): self.delete("input_start", "end") self.intercept_insert("input_start", cmd_line) self.see("insert") def _text_key_press(self, event): # Ctrl should underline values # TODO: this underline may confuse, when user is just copying on pasting # try to add this underline only when mouse is over the value # TODO: take theme into account """ if event.keysym in ("Control_L", "Control_R", "Command"): # TODO: check in Mac self.tag_configure("value", foreground="DarkBlue", underline=1) """ def _text_key_release(self, event): # Remove value underlining # TODO: take theme into account """ if event.keysym in ("Control_L", "Control_R", "Command"): # TODO: check in Mac self.tag_configure("value", foreground="DarkBlue", underline=0) """ def _clear_shell(self): end_index = self.index("output_end") self._clear_content(end_index) def compute_smart_home_destination_index(self): """Is used by EnhancedText""" if self._in_current_input_range("insert"): # on input line, go to just after prompt return "input_start" else: return super().compute_smart_home_destination_index() def _hyperlink_enter(self, event): self.config(cursor="hand2") def _hyperlink_leave(self, event): self.config(cursor="") def _handle_hyperlink(self, event): try: line = self.get("insert linestart", "insert lineend") # Python stacktrace matches = list(re.finditer(r'File "(?P[^"]+)", line (?P\d+)', line)) if not matches: # Friendly traceback matches = list( re.finditer( r"\b(?P\d+)\b.+'(?P[^\']+\.pyw?)'", line, flags=re.IGNORECASE ) ) if len(matches) == 1: filename = os.path.expanduser(matches[0].group("file")) lineno = int(matches[0].group("line")) if os.path.exists(filename) and os.path.isfile(filename): # TODO: better use events instead direct referencing get_workbench().get_editor_notebook().show_file( filename, lineno, set_focus=False ) else: r = self.tag_prevrange("io_hyperlink", "@%d,%d" % (event.x, event.y)) if r and len(r) == 2: url = self.get(r[0], r[1]) if SIMPLE_URL_SPLIT_REGEX.match(url): webbrowser.open(url) except Exception: traceback.print_exc() def _show_user_exception(self, user_exception): fr_tr = user_exception.get("friendly_traceback", None) if fr_tr is not None: self._format_friendly_traceback(fr_tr) return for line, frame_id, *_ in user_exception["items"]: tags = ("io", "stderr") if frame_id is not None: frame_tag = "frame_%d" % frame_id def handle_frame_click(event, frame_id=frame_id): get_runner().send_command(InlineCommand("get_frame_info", frame_id=frame_id)) return "break" # TODO: put first line with frame tag and rest without tags += (frame_tag,) self.tag_bind(frame_tag, "", handle_frame_click, True) self._insert_text_directly(line, tags) def _format_friendly_traceback(self, s): tags = ("io", "stderr") lines = s.splitlines(True) for line in lines: self._insert_text_directly(line, tags) def _discard_old_content(self): max_lines = max(get_workbench().get_option("shell.max_lines"), 0) proposed_cut = self.index("end -%d lines linestart" % max_lines) if proposed_cut == "1.0": return # would this keep current block intact? next_prompt = self.tag_nextrange("prompt", proposed_cut, "end") if not next_prompt: pass # TODO: disable stepping back self._clear_content(proposed_cut) def _clear_content(self, cut_idx): proposed_cut_float = float(cut_idx) for btn in list(self._squeeze_buttons): btn_pos = float(self.index(btn)) if btn_pos < proposed_cut_float: self._squeeze_buttons.remove(btn) # looks like the widgets are not fully GC-d. # At least avoid leaking big chunks of texts btn.contained_text = None btn.destroy() self.direct_delete("0.1", cut_idx) def _invalidate_current_data(self): """ Grayes out input & output displayed so far """ end_index = self.index("output_end") self.tag_add("inactive", "1.0", end_index) self.tag_remove("value", "1.0", end_index) while len(self.active_object_tags) > 0: self.tag_remove(self.active_object_tags.pop(), "1.0", "end") def get_lines_above_viewport_bottom(self, tag_name, n): end_index = self.index("@%d,%d lineend" % (self.winfo_height(), self.winfo_height())) start_index = self.index(end_index + " -50 lines") result = "" while True: r = self.tag_nextrange(tag_name, start_index, end_index) if not r: break result += self.get(r[0], r[1]) start_index = r[1] return result def update_tty_mode(self): self.tty_mode = get_workbench().get_option("shell.tty_mode") def set_syntax_options(self, syntax_options): super().set_syntax_options(syntax_options) self.update_margin_color() def update_margin_color(self): if ui_utils.get_tk_version_info() >= (8, 6, 6): self.tag_configure("io", lmargincolor=get_syntax_options_for_tag("TEXT")["background"]) class ShellText(BaseShellText): def __init__(self, master, view, cnf={}, **kw): super().__init__(master, view, cnf=cnf, **kw) self.bindtags(self.bindtags() + ("ShellText",)) self.tag_bind("io_hyperlink", "", self._handle_hyperlink) self.tag_bind("io_hyperlink", "", self._hyperlink_enter) self.tag_bind("io_hyperlink", "", self._hyperlink_leave) get_workbench().bind("InputRequest", self._handle_input_request, True) get_workbench().bind("ProgramOutput", self._handle_program_output, True) get_workbench().bind("ToplevelResponse", self._handle_toplevel_response, True) get_workbench().bind("DebuggerResponse", self._handle_fancy_debugger_progress, True) class SqueezedTextDialog(CommonDialog): def __init__(self, master, button): super().__init__(master) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.button = button self.content = button.contained_text self.shell_text = master padding = 20 mainframe = ttk.Frame(self) mainframe.grid(row=0, column=0, sticky="nsew") mainframe.columnconfigure(0, weight=1) mainframe.rowconfigure(2, weight=1) explanation_label = ttk.Label( mainframe, text=_( "For performance reasons, Shell avoids showing " + "very long lines in full (see Tools => Options => Shell).\n" + "Here you can interact with the original text fragment." ), ) explanation_label.grid(row=0, column=0, sticky="nsew", padx=padding, pady=padding) self._wrap_var = tk.BooleanVar(False) self.wrap_checkbox = ttk.Checkbutton( mainframe, text=_("Wrap text (may be slow)"), variable=self._wrap_var, onvalue=True, offvalue=False, command=self._on_wrap_changed, ) self.wrap_checkbox.grid(row=1, padx=padding, pady=(0, padding // 2), sticky="w") self.text_frame = TextFrame( mainframe, text_class=TweakableText, height=10, width=80, relief="sunken", borderwidth=1, wrap="none", ) self.text_frame.grid(row=2, column=0, padx=padding, sticky="nsew") self.text_frame.text.insert("1.0", button.contained_text) self.text_frame.text.set_read_only(True) button_frame = ttk.Frame(mainframe) button_frame.grid(row=3, column=0, padx=padding, pady=padding, sticky="nswe") button_frame.columnconfigure(2, weight=1) copy_caption = tr_btn("Copy to clipboard") copy_button = ttk.Button( button_frame, text=copy_caption, width=len(copy_caption), command=self._on_copy ) copy_button.grid(row=0, column=1, sticky="w", padx=(0, padding)) expand_caption = tr_btn("Expand in Shell") expand_button = ttk.Button( button_frame, text=expand_caption, width=len(expand_caption), command=self._on_expand ) expand_button.grid(row=0, column=2, sticky="e", padx=padding) close_button = ttk.Button(button_frame, text=tr_btn("Close"), command=self._on_close) close_button.grid(row=0, column=3, sticky="e") self.bind("", self._on_close, True) self.protocol("WM_DELETE_WINDOW", self._on_close) self.title(_("Squeezed text (%d characters)") % len(self.content)) def _on_wrap_changed(self): if self._wrap_var.get(): self.text_frame.text.configure(wrap="word") else: self.text_frame.text.configure(wrap="none") def _on_expand(self): index = self.shell_text.index(self.button) self.shell_text.direct_delete(index, index + " +1 chars") self.shell_text.direct_insert(index, self.content, tuple(self.button.tags)) self.destroy() # looks like the widgets are not fully GC-d. # At least avoid leaking big chunks of texts self.button.contained_text = None self.button.destroy() def _on_copy(self): self.clipboard_clear() self.clipboard_append(self.content) def _on_close(self, event=None): self.destroy() class PlotterCanvas(tk.Canvas): def __init__(self, master, text): self.master = master self.background = get_syntax_options_for_tag("TEXT")["background"] self.foreground = get_syntax_options_for_tag("TEXT")["foreground"] super().__init__( master, background=self.background, borderwidth=0, height=10000, # size of the virtual drawing area width=10000, highlightthickness=0, ) self.text = text self.x_scale = None self.x_scale = None self.range_start = -1 self.range_end = 2 self.range_block_size = 0 self.value_range = 2 self.last_legend = None self.font = tk.font.nametofont("TkDefaultFont") self.linespace = self.font.metrics("linespace") self.y_padding = self.linespace self.x_padding_left = -1 # makes sharper cut for partly hidden line self.x_padding_right = self.linespace self.fresh_range = True self.colors = [ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf", ] self.range_block_sizes = [ 0.1, 0.25, 0.5, 1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, ] self.bind("", self.on_resize, True) self.bind("", self.reset_range, True) self.create_close_button() get_workbench().bind("SyntaxThemeChanged", self.reload_theme_options, True) def create_close_button(self): self.close_img = get_workbench().get_image("tab-close") self.close_active_img = get_workbench().get_image("tab-close-active") self.close_rect = self.create_rectangle( self.winfo_width() - self.close_img.width() - self.linespace, self.linespace / 2, self.winfo_width(), self.linespace / 2 + self.close_img.height(), fill=self.background, width=0, tags=("close",), ) self.close_button = self.create_image( self.winfo_width() - self.linespace / 2, self.linespace / 2, anchor="ne", image=self.close_img, activeimage=self.close_active_img, tags=("close",), ) self.tag_bind("close", "<1>", self.on_close) def update_close_button(self): self.coords( self.close_rect, self.winfo_width() - self.close_img.width() - self.linespace / 1.5, self.linespace / 2, self.winfo_width() - self.linespace / 2, self.linespace / 2 + self.close_img.height(), ) self.coords(self.close_button, self.winfo_width() - self.linespace / 2, self.linespace / 2) def on_close(self, event): self.master.toggle_plotter() def reset_range(self, event=None): self.fresh_range = True def get_num_steps(self): return 30 def update_plot(self, force_clean=False): data_lines = [] bottom_index = self.text.index( "@%d,%d" % (self.text.winfo_width(), self.text.winfo_height()) ) bottom_lineno = int(float(bottom_index)) for i in range(bottom_lineno - self.get_num_steps(), bottom_lineno + 1): line_start_index = "%d.0" % i if i < 1 or "stdout" not in self.text.tag_names(line_start_index): data_lines.append(([], [])) else: content = self.text.get(line_start_index, line_start_index + " lineend") data_lines.append(self.extract_pattern_and_numbers(content)) # data_lines need to be transposed segments_by_color = [] for i in range(100): segments = list(self.extract_series_segments(data_lines, i)) if segments: segments_by_color.append(segments) else: break self.delete("segment") self.update_range(segments_by_color, force_clean) segment_count = self.draw_segments(segments_by_color) self.update_legend(data_lines, force_clean) self.delete("info") if segment_count == 0: info_text = ( _("Plotter visualizes series of\n" + "numbers printed to the Shell.") + "\n\n" + _("See Help for details.") ) self.create_text_with_background( self.winfo_width() / 2, self.winfo_height() / 2, text=info_text, anchor="center", justify="center", tags=("info",), ) # self.delete("guide", "tick", "legend") # self.range_start = 0 # self.range_end = 0 self.tag_raise("info") self.fresh_range = False def update_legend(self, data_lines, force_clean=False): legend = None i = len(data_lines) - 2 # one before last while i >= 0: legend = data_lines[i][0] if legend and legend == data_lines[i + 1][0]: # found last legend, which covers at least 2 consecutive points break i -= 1 if self.last_legend == legend and not force_clean: # just make sure it remains topmost self.tag_raise("legend") return self.delete("legend") if legend is None: return # add horizontal padding # legend[0] = " " + legend[0] # legend[-1] = legend[-1] + " " marker = "●" # "●" "•" marker_width = self.font.measure(marker) full_text_width = self.font.measure(marker.join(legend)) y = self.winfo_height() - self.linespace // 2 x = self.winfo_width() - full_text_width - self.linespace self.create_rectangle( x - self.linespace // 4, y - self.linespace, x + full_text_width + self.linespace // 4, y, fill=self.background, width=0, tags=("legend",), ) for i, part in enumerate(legend): if i > 0: self.create_text( x, y, text=marker, anchor="sw", fill=self.colors[i - 1 % len(self.colors)], tags=("legend",), ) x += marker_width self.create_text(x, y, text=part, anchor="sw", tags=("legend",), fill=self.foreground) x += self.font.measure(part) self.last_legend = legend def draw_segments(self, segments_by_color): count = 0 for color, segments in enumerate(segments_by_color): for pos, nums in segments: self.draw_segment(color, pos, nums) count += 1 # raise certain elements above segments self.tag_raise("tick") self.tag_raise("close") return count def draw_segment(self, color, pos, nums): x = self.x_padding_left + pos * self.x_scale args = [] for num in nums: y = self.y_padding + (self.range_end - num) * self.y_scale args.extend([x, y]) x += self.x_scale self.create_line( *args, width=2, fill=self.colors[color % len(self.colors)], tags=("segment",), # arrow may be confusing # and doesn't play nice with distinguising between # scrollback view and fresh_range view # arrow="last", # arrowshape=(3,5,3) ) # self.current_segment_ids.append(line_id) def update_range(self, segments_by_color, clean): if not segments_by_color: return range_start = 9999999999 range_end = -9999999999 # if new block is using 3/4 of the width, # then don't consider old block's values anymore interest_position = 0 for start_pos, nums in reversed(segments_by_color[0]): if start_pos < self.get_num_steps() / 10: interest_position = start_pos break assert isinstance(interest_position, int) for segments in segments_by_color: for start_pos, nums in segments: if start_pos >= interest_position: range_start = min(range_start, *nums) range_end = max(range_end, *nums) if interest_position == 0 and not self.fresh_range: # meaning we still care about old line's values range_start = min(range_start, self.range_start) range_end = max(range_end, self.range_end) if range_end == range_start: range_end += 1 if ( not clean and not self.fresh_range and self.x_scale is not None and range_end == self.range_end and range_start == self.range_start ): # don't recompute as nothing was changed return value_range = range_end - range_start range_block_size = value_range // 4 # prefer round blocks for size in self.range_block_sizes: if size * 4 >= value_range: range_block_size = size break # extend to range block boundary if range_end % range_block_size != 0: range_end -= range_end % -range_block_size if range_start % range_block_size != 0: range_start -= range_start % range_block_size # not sure about these assertions when using floats # assert range_start % range_block_size == 0 # assert range_end % range_block_size == 0, "range_end: %s, bs: %s" % (range_end, range_block_size) # remember self.range_start = range_start self.range_end = range_end self.value_range = range_end - range_start self.range_block_size = range_block_size available_height = self.winfo_height() - 2 * self.y_padding available_width = self.winfo_width() - self.x_padding_left - self.x_padding_right num_steps = self.get_num_steps() self.x_scale = available_width / (num_steps - 1) self.y_scale = available_height / self.value_range self.update_guides_and_ticks() def update_guides_and_ticks(self): self.delete("guide", "tick") value = self.range_start while value <= self.range_end: y = self.y_padding + (self.range_end - value) * self.y_scale # guide self.create_line( 0, y, self.winfo_width(), y, tags=("guide",), dash=(2, 2), fill="#aaaaaa" ) # tick if value == int(value): value = int(value) caption = " " + str(value) + " " self.create_text_with_background( self.linespace // 2, y, caption, anchor="w", tags=("tick",) ) value += self.range_block_size def extract_pattern_and_numbers(self, line): parts = NUMBER_SPLIT_REGEX.split(line) if len(parts) < 2: return ([], []) assert len(parts) % 2 == 1 pattern = [] numbers = [] for i in range(0, len(parts), 2): pattern.append(parts[i]) for i in range(1, len(parts), 2): numbers.append(float(parts[i])) return (pattern, numbers) def extract_series_segments(self, data_lines, series_nr): """Yields numbers which form connected multilines on graph Each segment is pair of starting position and numbers""" segment = (0, []) prev_pattern = None for i, (pattern, nums) in enumerate(data_lines): if len(nums) <= series_nr or pattern != prev_pattern: # break the segment if len(segment[1]) > 1: yield segment segment = (i, []) if len(nums) > series_nr: segment[1].append(nums[series_nr]) prev_pattern = pattern if len(segment[1]) > 1: yield segment def create_text_with_background( self, x, y, text, anchor="w", justify="left", background=None, tags=() ): if background is None: background = self.background width = 0 lines = text.splitlines() for line in lines: width = max(width, self.font.measure(line)) height = len(lines) * self.linespace rect_x = x rect_y = y if anchor == "center": rect_x = x - width / 2 rect_y = y - height / 2 elif anchor == "w": rect_y = y - height / 2 else: "TODO:" self.create_rectangle( rect_x, rect_y, rect_x + width, rect_y + height, fill=background, width=0, tags=tags ) self.create_text( x, y, anchor=anchor, text=text, tags=tags, fill=self.foreground, justify=justify ) def reload_theme_options(self, event): self.background = get_syntax_options_for_tag("TEXT")["background"] self.foreground = get_syntax_options_for_tag("TEXT")["foreground"] self.configure(background=self.background) self.itemconfig(self.close_rect, fill=self.background) self.update_plot(True) def on_resize(self, event): if self.winfo_width() > 10: get_workbench().set_option("view.plotter_width", self.winfo_width()) self.update_plot(True) self.update_close_button() self.master.resize_plotter() thonny-3.2.7/thonny/test/0000755000175000017500000000000013611777205016363 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/test/__init__.py0000644000175000017500000000002113611773167020470 0ustar annamaaannamaa00000000000000# package marker thonny-3.2.7/thonny/test/plugins/0000755000175000017500000000000013611777205020044 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/test/plugins/__init__.py0000644000175000017500000000002113611773167022151 0ustar annamaaannamaa00000000000000# package marker thonny-3.2.7/thonny/test/plugins/test_name_highlighter.py0000644000175000017500000000642613611776473024771 0ustar annamaaannamaa00000000000000import tkinter from typing import Sequence, Set # @UnusedImport from thonny.plugins.highlight_names import VariablesHighlighter import sys import warnings TEST_STR1 = """def foo(): foo() pass def boo(narg): foo = 2 # line 5 boo = foo + 4 print(narg + 2) for i in range(5): boo() narg = 2 # line 10 def bar(): x + x def blarg(): x = 2 """ # tuple of tuples, where an inner tuple corresponds to a group of insert positions # that should produce the same output (corresponding expected output is in the # expected_indices tuple at the same index) # # consider TEST_STR1: # # The first group is four indices, where we would expect the two locations of the name "foo" # to be returned. Those expected two locations are specified at index 0 of tuple expected_indices. # # Second tuple is a group of one index, where we would expect output with the locations for "boo" # And if the insert location is at "pass", we would expect an empty set for output CURSOR_POSITIONS1 = ( ("1.4", "1.5", "1.7", "2.5"), ("4.6",), ("3.4",), ("5.7", "6.12"), ("4.10", "7.11"), ("10.2",), ("12.5", "12.9"), ("14.5",), ) EXPECTED_INDICES1 = [ {("1.4", "1.7"), ("2.4", "2.7")}, {("4.4", "4.7"), ("9.4", "9.7")}, set(), {("5.4", "5.7"), ("6.10", "6.13")}, {("4.8", "4.12"), ("7.10", "7.14")}, {("10.0", "10.4")}, {("12.4", "12.5"), ("12.8", "12.9")}, {("14.4", "14.5")}, ] # type: Sequence[Set[Sequence[str]]] TEST_STR2 = """import too def foo(): foo = too + 4 x = foo + bow # 5 class TestClass: def foo(self): pass def add3(self): self.foo() # 10 foo() """ CURSOR_POSITIONS2 = (("1.8", "3.10"), ("2.4", "2.5", "11.10"), ("3.5", "4.9")) EXPECTED_INDICES2 = ( {("1.7", "1.10"), ("3.10", "3.13")}, {("2.4", "2.7"), ("11.8", "11.11")}, {("3.4", "3.7"), ("4.8", "4.11")}, ) TEST_GROUPS = ( (CURSOR_POSITIONS1, EXPECTED_INDICES1, TEST_STR1), (CURSOR_POSITIONS2, EXPECTED_INDICES2, TEST_STR2), ) def test_all(): if sys.version_info >= (3, 8): warnings.warn("Skipping name matcher tests in Python 3.8") return import jedi if ( jedi.__version__.startswith("0.13.") or jedi.__version__.startswith("0.14.") or jedi.__version__.startswith("0.15.") or jedi.__version__.startswith("0.16.") ): warnings.warn("Skipping name matcher tests for Jedi " + jedi.__version__) return for i, test in enumerate(TEST_GROUPS): print("Running test group %d: " % (i + 1)) _assert_returns_correct_indices(test[0], test[1], test[2]) def _assert_returns_correct_indices(insert_pos_groups, expected_indices, input_str): text_widget = tkinter.Text() text_widget.insert("end", input_str) nh = VariablesHighlighter(text_widget) for i, group in enumerate(insert_pos_groups): for insert_pos in group: text_widget.mark_set("insert", insert_pos) actual = nh.get_positions() expected = expected_indices[i] assert actual == expected, ( "\nInsert position: %s" "\nExpected: %s" "\nGot: %s" % (insert_pos, expected, actual) ) print("\rPassed %d of %d" % (i + 1, len(insert_pos_groups)), end="") print() thonny-3.2.7/thonny/test/plugins/test_locals_marker.py0000644000175000017500000000112713611773167024277 0ustar annamaaannamaa00000000000000import tkinter from thonny.plugins.locals_marker import LocalsHighlighter TEST_STR1 = """num_cars = 3 def foo(): print(num_cars + num_cars) def too(): num_cars = 4 print(num_cars + num_cars) def joo(): global num_cars num_cars = 2 """ def test_regular_closed(): expected_local = {("5.4", "5.12"), ("6.10", "6.18"), ("6.21", "6.29")} text_widget = tkinter.Text() text_widget.insert("end", TEST_STR1) highlighter = LocalsHighlighter(text_widget) actual_local = highlighter.get_positions() assert actual_local == expected_local print("Passed.") thonny-3.2.7/thonny/test/test_common.py0000644000175000017500000000222513611773167021270 0ustar annamaaannamaa00000000000000import os from thonny.common import path_startswith def test_path_startswith(): assert path_startswith("/kala/pala", "/kala") assert path_startswith("/kala/pala", "/kala/") assert not path_startswith("/kala/pala", "/pala") assert not path_startswith("/kalapala/pala", "/kala") if os.name == "nt": assert path_startswith("/kala/pala", "/KALA") else: assert not path_startswith("/kala/pala", "/KALA") if os.name == "nt": assert path_startswith("C:\\foo\\bar", "C:\\foo") assert path_startswith("C:\\foo", "C:\\") assert path_startswith("C:/foo", "C:\\") assert path_startswith("C:\\foo", "C:/") assert path_startswith("C:\\foo\\dir\\file", "C:\\foo") assert path_startswith("C:/foo\\dir\\file", "c:\\FOO") assert path_startswith("c:\\FOO\\dir\\file", "C:/foo") assert path_startswith("C:\\FOO\\dir\\dir2\\..\\ee", "C:/foo/dir/ee") assert path_startswith("c:\\foo\\bar.txt/kala\\pala", "C:\\foo\\bar.txt/kala") assert path_startswith("c:\\foo\\bar.txt/kala\\pala", "C:\\") assert not path_startswith("C:\\kalapala\\pala", "C:\\kala") thonny-3.2.7/thonny/terminal.py0000644000175000017500000001570413611773167017603 0ustar annamaaannamaa00000000000000import os.path import platform import shlex import shutil import subprocess def run_in_terminal(cmd, cwd, env_overrides={}, keep_open=True, title=None): from thonny.running import get_environment_with_overrides env = get_environment_with_overrides(env_overrides) if not cwd or not os.path.exists(cwd): cwd = os.getcwd() if platform.system() == "Windows": _run_in_terminal_in_windows(cmd, cwd, env, keep_open, title) elif platform.system() == "Linux": _run_in_terminal_in_linux(cmd, cwd, env, keep_open) elif platform.system() == "Darwin": _run_in_terminal_in_macos(cmd, cwd, env_overrides, keep_open) else: raise RuntimeError("Can't launch terminal in " + platform.system()) def open_system_shell(cwd, env_overrides={}): from thonny.running import get_environment_with_overrides env = get_environment_with_overrides(env_overrides) if platform.system() == "Darwin": _run_in_terminal_in_macos([], cwd, env_overrides, True) elif platform.system() == "Windows": cmd = "start cmd" subprocess.Popen(cmd, cwd=cwd, env=env, shell=True) elif platform.system() == "Linux": cmd = _get_linux_terminal_command() subprocess.Popen(cmd, cwd=cwd, env=env, shell=True) else: raise RuntimeError("Can't launch terminal in " + platform.system()) def _add_to_path(directory, path): # Always prepending to path may seem better, but this could mess up other things. # If the directory contains only one Python distribution executables, then # it probably won't be in path yet and therefore will be prepended. if ( directory in path.split(os.pathsep) or platform.system() == "Windows" and directory.lower() in path.lower().split(os.pathsep) ): return path else: return directory + os.pathsep + path def _run_in_terminal_in_windows(cmd, cwd, env, keep_open, title=None): if keep_open: # Yes, the /K argument has weird quoting. Can't explain this, but it works quoted_args = " ".join(map(lambda s: s if s == "&" else '"' + s + '"', cmd)) cmd_line = """start {title} /D "{cwd}" /W cmd /K "{quoted_args}" """.format( cwd=cwd, quoted_args=quoted_args, title='"' + title + '"' if title else "" ) subprocess.Popen(cmd_line, cwd=cwd, env=env, shell=True) else: subprocess.Popen(cmd, creationflags=subprocess.CREATE_NEW_CONSOLE, cwd=cwd, env=env) def _run_in_terminal_in_linux(cmd, cwd, env, keep_open): def _shellquote(s): return subprocess.list2cmdline([s]) term_cmd = _get_linux_terminal_command() if isinstance(cmd, list): cmd = " ".join(map(_shellquote, cmd)) if keep_open: # http://stackoverflow.com/a/4466566/261181 core_cmd = "{cmd}; exec bash -i".format(cmd=cmd) in_term_cmd = "bash -c {core_cmd}".format(core_cmd=_shellquote(core_cmd)) else: in_term_cmd = cmd if term_cmd == "lxterminal": # https://www.raspberrypi.org/forums/viewtopic.php?t=221490 whole_cmd = "{term_cmd} --command={in_term_cmd}".format( term_cmd=term_cmd, in_term_cmd=_shellquote(in_term_cmd) ) else: whole_cmd = "{term_cmd} -e {in_term_cmd}".format( term_cmd=term_cmd, in_term_cmd=_shellquote(in_term_cmd) ) subprocess.Popen(whole_cmd, cwd=cwd, env=env, shell=True) def _run_in_terminal_in_macos(cmd, cwd, env_overrides, keep_open): _shellquote = shlex.quote cmds = "clear; cd " + _shellquote(cwd) # osascript "tell application" won't change Terminal's env # (at least when Terminal is already active) # At the moment I just explicitly set some important variables for key in env_overrides: if env_overrides[key] is None: cmds += "; unset " + key else: cmds += "; export {key}={value}".format(key=key, value=_shellquote(env_overrides[key])) if cmd: if isinstance(cmd, list): cmd = " ".join(map(_shellquote, cmd)) cmds += "; " + cmd if not keep_open: cmds += "; exit" # The script will be sent to Terminal with 'do script' command, which takes a string. # We'll prepare an AppleScript string literal for this # (http://stackoverflow.com/questions/10667800/using-quotes-in-a-applescript-string): cmd_as_apple_script_string_literal = '"' + cmds.replace("\\", "\\\\").replace('"', '\\"') + '"' # When Terminal is not open, then do script opens two windows. # do script ... in window 1 would solve this, but if Terminal is already # open, this could run the script in existing terminal (in undesirable env on situation) # That's why I need to prepare two variations of the 'do script' command doScriptCmd1 = """ do script %s """ % cmd_as_apple_script_string_literal doScriptCmd2 = """ do script %s in window 1 """ % cmd_as_apple_script_string_literal # The whole AppleScript will be executed with osascript by giving script # lines as arguments. The lines containing our script need to be shell-quoted: quotedCmd1 = subprocess.list2cmdline([doScriptCmd1]) quotedCmd2 = subprocess.list2cmdline([doScriptCmd2]) # Now we can finally assemble the osascript command line cmd_line = ( "osascript" + """ -e 'if application "Terminal" is running then ' """ + """ -e ' tell application "Terminal" ' """ + """ -e """ + quotedCmd1 + """ -e ' activate ' """ + """ -e ' end tell ' """ + """ -e 'else ' """ + """ -e ' tell application "Terminal" ' """ + """ -e """ + quotedCmd2 + """ -e ' activate ' """ + """ -e ' end tell ' """ + """ -e 'end if ' """ ) subprocess.Popen(cmd_line, cwd=cwd, shell=True) def _get_linux_terminal_command(): xte = shutil.which("x-terminal-emulator") if xte: if os.path.realpath(xte).endswith("/lxterminal") and shutil.which("lxterminal"): # need to know exact program, because it needs special treatment return "lxterminal" else: return "x-terminal-emulator" # Older konsole didn't pass on the environment elif shutil.which("konsole"): if ( shutil.which("gnome-terminal") and "gnome" in os.environ.get("DESKTOP_SESSION", "").lower() ): return "gnome-terminal" else: return "konsole" elif shutil.which("gnome-terminal"): return "gnome-terminal" elif shutil.which("xfce4-terminal"): return "xfce4-terminal" elif shutil.which("lxterminal"): return "lxterminal" elif shutil.which("xterm"): return "xterm" else: raise RuntimeError("Don't know how to open terminal emulator") thonny-3.2.7/thonny/res/0000755000175000017500000000000013611777205016175 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/res/nav-backward.png0000644000175000017500000000053313611773167021247 0ustar annamaaannamaa00000000000000PNG  IHDRa"IDATxc``w͞fO{[Y;Oռ6>{fG=P}f,sk%t^*ng@[k>Z+~y})jonmRl%+AϚ|?]}S/~+/߮-u _WGk > Lj9|xϯK?õk]"΄KîpFdί_| s<^8&a ' l%ڎ<{^<*?A|i[qJ I;[ѡBު$|4:H +nEIwo&`lLAlZ^Ft{gs;ÃZ_OlOgqT q?y\Hf`3D8.NddN l>t-"HX6'xdq[,xj LLf7iѲA1k" L@3H47FX 4| u 𼌥k,Q8}lLtdz|Y~BߟIENDB`thonny-3.2.7/thonny/res/_disabled_information_2x.png0000644000175000017500000000302313611773167023630 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxŖ[o3go\RbY˺uEZ裟ۗ@-ZjMڑlYwZ)^~f C$ 0س؝̜;3''D3P)Tvm _&\Na)08I狽o7>x ˿`׳O Xh"Js D ;o~<3(׳ÔE1yVfRkYa*h988|9m=ǛM7>* 3>*؀鋵'ĴT0J> 4 LK2_^&\SVܪ VL:in1Q2P.Fʀ%bX Ôe4U +3Q~LfdP6->^SP*a"@B;D@ PQPjEL wl" $^W MDޓ] (45L %(P"ŹR;.$EHE4܊ jl;d%⋱TݳRKtj¯8 J3etܶ̾ i3Qx1 Sa ߝ梲=6v: lh(-JBѴKReI'Y9GEgjW+kbl?;xmYsS-yi7i"IϩV`:R-_5Z9Ң8ƙM lgo8ofYW7Ÿ^5E/Owo#25HEH5\k6/@䈪Q Qe~@NoVf* Bj!w:{q_kOV T?ix no_vmcu\ LgVZ-E }?;VA^5WV_6e<I Ic4/h_owT߳;!Ir(\,HMun  rj;X[ٹY*$E,:dCrS0U& y(K8:j݅ @D`yg 4Qt:}LMMa^1`n{ q#I^NY@y=@CPw<>=MVu.@P([I`8I uldxaduuΎ9::0aP;L;U|ٜ('''G`T6*kme%U8+P-AW(ٍ G6Wﯕ|&,(IENDB`thonny-3.2.7/thonny/res/quit.png0000644000175000017500000000106113611773167017666 0ustar annamaaannamaa00000000000000PNG  IHDRasBIT|d pHYs  IDAT8AoQދ3D-[ uA ҍ;\huAg]M*: (0PHLmMwܓqc EJ) ^=#yW}խZ`/" j|c޳3+!e# -{{ h`>P:|V*frbam}{;;l{v߮ôPt)V\.gl$8p7(&[2~3߇+:ma% t+N70\VHsu\i_Q4;lS BI苬.q&6j>mq1Kt"`6S C>Zpȝ(Z EZ~r9Tҽ0sYGQB}IIu,AC\d%b.c{i:kkwn ;3'MIENDB`thonny-3.2.7/thonny/res/_disabled_zoom.png0000644000175000017500000000072513611773167021664 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATx?@҈>{EkEDK?k`j)7PSX kH,3gY1L~5Mc4ty n kRG(}U?<B(~OSvfMT ^I+t(JxvԹl)%m3 0 ۶ЂǃB\&$Q B8pPRʂ$I~OBuL<Ϥi|>Wir:0M)ʫ5u @, \0d%aHǘIedYFRZ1QJnzi!<j" CUjU B,²,>%:l6{Ri#V>yIENDB`thonny-3.2.7/thonny/res/_disabled_save-file_alt.png0000644000175000017500000000100613611773167023404 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxMnAc Xq~E"܄: b*F A#,۸gzXv`!zS^jN^z_|<8mJ o.130 )ߕՒ}; )NF"_gks.,i5I7o'}h!$M /gF˷9Kc0@\05@׾~^t6(zQwJR.oaGnaDQzY%OK@jo <0C`ۖ_˚و,Bcd㗑F08.&/ 6`ٚޙ(=)m[BaݚwòB`  Ap?-|18^\kej-qPUifF1:f5Yh}p|F~ PW9Ect8CdoY#IENDB`thonny-3.2.7/thonny/res/_disabled_stop_alt.png0000644000175000017500000000046113611773167022522 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxӱJAv/gZF|BXYH"6"HLvnҜ 1?J4sQp3?ȑ ,>zi]L&u_Ջ@5TVHLo2L7w3s z9`·܂jT#}$WD 7 #P>#L!E)SA@>.<A~ď@Laq˩DDIENDB`thonny-3.2.7/thonny/res/_disabled_tab-close-active-clam.gif0000644000175000017500000000154213611773167024713 0ustar annamaaannamaa00000000000000GIF87a ```, GHX ! 3Ǐ =ɓ˗/ 8sg@;thonny-3.2.7/thonny/res/boxminus.png0000644000175000017500000000042013611773167020546 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2bKGD pHYs.#.#x?vtIME 0/tEXtCommentCreated with GIMPWxIDAT(cd]ܾ~ }Z n. &N81Taĉ((#C\n E\x @VL }W16yꅁuM֭cF(GU[IENDB`thonny-3.2.7/thonny/res/_disabled_generic-file.gif0000644000175000017500000000171013611773167023205 0ustar annamaaannamaa00000000000000GIF87aƧ,@H`XȰ!" @"1(Ǐ  @R(@@@I&r OѣX*ӧjUj ٳX+۷p @Wx 0 a+^ `@HLYr;thonny-3.2.7/thonny/res/step-out.png0000644000175000017500000000057313611773167020473 0ustar annamaaannamaa00000000000000PNG  IHDRaBIDATxc`R`mG{~ &2@}DS@]j[oN[C-E>??_2Q^6J-jA_}˓t|T']׀u<SkӽwkP#YH0 VI|5!|?T B3,-β++,*Y^(iBt-Jd_UP4߯tߢt>L|^W'_\$Z[Ԃiť3˕R;p@nPIENDB`thonny-3.2.7/thonny/res/_disabled_step-out.png0000644000175000017500000000062413611773167022456 0ustar annamaaannamaa00000000000000PNG  IHDRa[IDATxœJBQ̃=FIPfB@M|ޡJ B Jp`{G88ړo}kl<9T_D8IC $ԁ:߶5K**{7r<:)wdwt0VS1f/yr󣟱 Zg!dZ>LZ0z r[Ir`LI`w׆?X qX&IENDB`thonny-3.2.7/thonny/res/nav-forward_2x.png0000644000175000017500000000120413611773167021542 0ustar annamaaannamaa00000000000000PNG  IHDR szzKIDATxOQpU7x)Cc&gʢp 뗫it]R02@5Xs\^m:l};l yw/VꈕP!5u6;j(qϱM 4NiU!>g6o!} 4%Dl8דZ&bMvBLY!=DMlk4 2դW !0wu|O\]px9B3 \lW ~6U3li 'g]' Һ4NALa4Z.rɴ๓V= ^٪8x#:G 9:NW݂l3FJ_HLXgA'{ݳak=CF7ٌҼ` Ftȇ#qb\j^[!bA }!nZo^)?F~;Wټ ]u| otA35;@c-k~V {~c5پ=^55ס0}yU]"թQ.ҔIENDB`thonny-3.2.7/thonny/res/terminal_2x.png0000644000175000017500000000272013611773167021133 0ustar annamaaannamaa00000000000000PNG  IHDR szzsBIT|dIDATX]E?3sv/KقH*mIȊZ5jW`b|a !"?^@ ?\kBD(Bn-l*w3gf_s=wƔ_=s3y3sOvF&JFDO^B}iqם |ͺ߼uڑU$|"^CQklKя^epxhX{,IF.Zv|s??ܘxK.9:o@tBkcL/3\a=AXhnHT$ZLLI@ /mO"BWz?v.|=Fk @n!R(?F5l4yXh q"1whm/Zq.ID:H Lq1"Y(욃>`9Kz& $f`+ ̤WU+q$bL@ i`)`XvR=f/8h4kU:KԗN1͛0hdfXBLiԫTiz>U1g-sxv0d |[oa6[/235E>ѐ6+1}ɥ9RE(j ZZ\} @DPIĘsāMח8,3CV_B00OsEG1`9WL6i!M= K81^_m;3k5 ;װyQJt,JkDDxDDeer~,} ^Uk-N1 O _z!c7lcbE#14t%ʻ}lp+HĹ 1`M y&܋{S1]W~%,@X6۴'~]1_+ثP|lYg-^X0Z#6WvHcAkݓֲHҮ Eh!HjWmW[sՆN?`=AJv DRPZ{~ wB_ĝy=_gNr4#ۯd &FYi=|0~ULM.5^K9$IZkyUɴ6]ļ44$IrOc.k.k/k?e=f6lDj9rCoHoOqNtMvRvD}L{SwQxTxUxSyTyUyTyVyWyTzR{VzWzXzOZzZzX{LZ{N[{Z{U}Z|\|Z|[|[~[~]URW_Zhccorsty€ʆϊьЕŘəȘ͝ʝ͞ˡ̞ΠϣͣΦϧΩѭּ޹پ!Created with GIMP! ,S_^WUQLB`vyrmgbM<.]wztplfVOaZw \|XYw|[keDTw +3@IR{qd Kw%&/761Hc Gзun Ew'#$,=>Ni yoFlE2,@Asѐ}i((ȝ8tAF%j(q%K ;thonny-3.2.7/thonny/res/run-current-script.png0000644000175000017500000000115413611773167022475 0ustar annamaaannamaa00000000000000PNG  IHDRa3IDATxc`6(p-$QnYlCJNR Ŋm%, t,;g\_w8ߒvKpjqX}0қ7ߟ| ɩ7|+pxݗ Qk&w?캷GŻVRnxmU׏-Ax0p[@kv/Jp*n{< [6GW^\:.$XKm~z=+6WG?<odycτzD$ Jlzwk*Q4Nmb/Nku_ߞ,!@; ((#a{i vaD7XvBItg>XUwD0k(MwtFIENDB`thonny-3.2.7/thonny/res/_disabled_new-file_Linux.png0000644000175000017500000000057013611773167023563 0ustar annamaaannamaa00000000000000PNG  IHDRa?IDATxNA;ÊQLjEi&P6 &F ~eg,%N2=i4wZ*B5Zk7ZZoQ@70RIENDB`thonny-3.2.7/thonny/res/_disabled_new-file_Linux_2x.png0000644000175000017500000000154413611773167024176 0ustar annamaaannamaa00000000000000PNG  IHDR szz+IDATxŗnHj.AbA.9m>$\P2W y, VbẃA b/U%RnnnE} 'F-V:vǸFƘw" sUݻo=/}1gQ{ WWWa[UڝV`#L@g@^_71vZ$ ,(O@pz 2}`~Y""ρrX!}}ƬRsW slķA,`;19 >*iDd}yz$4{oˌFlo4,.*9")0~ h@3qY)ib]R(:t8.R VOl?;pPAǠ5fv [=pqqsn<=g'Șls{nD`GPS Һ+.^%}v@PB&1ovEtp 4gR% H漃p7+OJoUPA~TAؔnM m:o uhNM*%QPxsG\^^IL!R|yWИNm?63jhk Д~'Vc{ .@ "a^Ӟ0do.)gp6KD1f. bv07 ^9)R۪lgU&o~9\R"?K?IENDB`thonny-3.2.7/thonny/res/run-to-cursor.png0000644000175000017500000000037413611773167021451 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxc`'[dD͍X6`S AT,64Htn~ |sVH8 yGzZÀU}9~oUbWU\e\}=]f}Kp`Yחz({Dā@\R(/!+(NHe&d % IENDB`thonny-3.2.7/thonny/res/_disabled_step-out_2x.png0000644000175000017500000000132613611773167023067 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxMOQ;Sv.)`UIX?ʵ@6&$$*m {\L[J 0L2s<=gf2־f?B%|9%PJ-=mO6埉qy?9ZhJ (0; {ƻ8gⷯou';yz).1 @r"ZӀњ$ۮ9<H pɩig С<# RS.DS"rU'Zs;/YI uY'0 K TDCm +QP b@ 0:a sbka??O(k@mmΤ7ɬ|,tUj$Hkv}}ˇ+ 431T{05AJ}|3}B*e2YgnyD@@\@Rdҫ~$dheK7DP2;N&NۥNt9PN?8}%&bZ0ʵSR*e=RcS,L]%xW@RVDYMABDZA`;|*5 (XbّM¢fۗd-usƀAD)m+*:/4M誃7 ~҄`.IENDB`thonny-3.2.7/thonny/res/_disabled_nav-backward.png0000644000175000017500000000065413611773167023241 0ustar annamaaannamaa00000000000000PNG  IHDRasIDATxSMKA~ffw"`ZPd5Bj?ԏ{CYR dA%))" vfw:T(ma/ezy^о^)U' :~/p8Ѥ#^:rIUe4_0)"ŒH<#|1.UDwbۭ&ڞzw aw+NQzt"j^) a[]!T@6*N'9U,Pk?EA*Lś)֯zĽ0וA[د ?\;.)ytIENDB`thonny-3.2.7/thonny/res/stop_2x_alt.png0000644000175000017500000000100513611773167021140 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxIKBaAAi &I- +APD B 6-֮v]|qvO|.nMs9Vbr,#YhJ4Vcx1$K/h&/+%} @"fP8EDZ(O}0ގ"&P'B mE'PA@VjKcZ(O}7a@PWWBy_[S/pOSC JBy }= ":PZwwByhuxSgI`VvIc-#AaoJ2/$F]|n/TnI^h*fm3h~.Oyw`;IENDB`thonny-3.2.7/thonny/res/_disabled_tab-close-active-clam-dark.gif0000644000175000017500000000154213611773167025632 0ustar annamaaannamaa00000000000000GIF87a ```, GHX ! 3Ǐ =ɓ˗/ 8sg@;thonny-3.2.7/thonny/res/nav-forward.png0000644000175000017500000000053013611773167021132 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxc``oý-ow6je:/.E=Yl/,hH%CU}?:,d? R-{~viuhl(:m3oSlb%*/ T-?#__cؗU6p/_]}UtNחj&Vfg)j"A3, yUej9oeXFf68yIENDB`thonny-3.2.7/thonny/res/_disabled_nav-backward_2x.png0000644000175000017500000000136413611773167023651 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxKOa 3! n b [B_`1^\L 47XB܏RPJ lx4_'}LG:^ 5rtJ7C8<*]^] tJB!Seٌ9f gS2% =jLwpB Ҭ ,ifd*3I"P2axnuEed;0?tTр.{I0PyScFG~&tRė@< >@ºO3m{1G @:Yd84?46:Kza&u3)Uӹ50(5ֵ?ePRoIENDB`thonny-3.2.7/thonny/res/zoom.png0000644000175000017500000000072413611773167017675 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATx^?AaƯsLJ> h0Ȩ̊d0`S(jc${zN2~u:yx~ ~OXk`Od2eYr|ŽaԸzN s=QV"z6E`0@:]/ TUv;vWZ"064@:1/ bQiBzT9kĀR1z1q:$HМ.T*qEٔn74#N m4nJ%t]4vh&f3 4|d2.&3PB@xT^AOSw_.n/ +|>uph @uF d.l6 X J./3B8x'3jcya#IENDB`thonny-3.2.7/thonny/res/_disabled_tab-close-clam.gif0000644000175000017500000000154213611773167023442 0ustar annamaaannamaa00000000000000GIF87a Ʊ, GHX ! @3Ǐ =ɓ˗/ @8sg@;thonny-3.2.7/thonny/res/_disabled_run-to-cursor_2x.png0000644000175000017500000000114413611773167024044 0ustar annamaaannamaa00000000000000PNG  IHDR szz+IDATxokPƟ6i [3EBn2E(7+?2lej]ǨnfiY5ٮk`ہ\dIV ۏrgܶw] 9$ (ξn9H.dz*WP=}hٱDB\aOrh? ~J"B2~x`zB [&$̹hV^z:((&yڭ )p Є"c@(\!jǕha^`kaFFcCՍ0t"&ꢶO `/VNzE Dr,a%U\sV/KZK'▦٬޿j7ׇ&윂Z@ݻ hVJ+A+kx| p[OaP fe|JVD|x4Ck_{}+z$opZ1@.g?NnFߎB\̥lIENDB`thonny-3.2.7/thonny/res/boxplus.png0000644000175000017500000000044013611773167020400 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2bKGD pHYs.#.#x?vtIME 2 BtEXtCommentCreated with GIMPWIDAT(cd]ܾ~ }Z n. &N81Taĉ(p@!`A|!l7+u8l7M }@ oh!- 4[o:Xn689`Q5*|IENDB`thonny-3.2.7/thonny/res/_disabled_step-over.png0000644000175000017500000000102213611773167022613 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxkQ{f21(Z$AQt"+?ͭC5ElU`[l]Ւ¦VK qwbaEo ='O6vrԉtʽڋ*@! :cg/%F.L. vKr}?p>12zM?T$#pO)KRjlko.{tb4#~*s( xt~=_ ?" oWf,NdM2lw#c V}]`25S*  ۩[#X TWUM8< 60T_Y[[[MZ!fZ֗W̯9P}"p1-D$dDH$~#eWrCD$@Q7m%㚦lZT8HD \nX @I5~,Xb 9[r2v YWW3 m:cKev[1 Dkj-Uώ9IIENDB`thonny-3.2.7/thonny/res/_disabled_quit_2x.png0000644000175000017500000000141413611773167022267 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxŗ]N@E86M[5E$rl$w@Zւ0!@HBcD|Ώg1o)M : afKyW8|k#Z0W/l=^] miLX ʹ[x4-#vvt<-q@J7];Q6 ӗ@E1wZi /ur;(%Ns53oNW!ҔQ`2J1J~ H ʂ=T}N-@c-F1Kyw}j"8FRBwxA (!.20000,reXð.,Oqeu2ĕ&߾}g`````w8.O@dAuM֭cF"(ZfaGIENDB`thonny-3.2.7/thonny/res/harddisk.png0000644000175000017500000000151713611773167020503 0ustar annamaaannamaa00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<tEXtTitleHard DriveO2tEXtAuthorJakub Steiner/#tEXtSourcehttp://tango.freedesktop.org}aIDAT8nQs!lg!$q@MH hR]J.R QЧHEXHo B4bfhDV>|p!\֎%iJ2H$'Wqm*?%$"Zp8Cӡ鰿{pM4Yu }9hbbk-I 1~ppt4.jJ.Û.bZK.wn(rYx1.s47BR G0/gff-T*Q.qz|0 ֞ @4=vwwi4c(WR$I2:cz8}!e{R!Fz$ mi8xRC0֪`6rJ$0f5R cui6!֢qEX[[3 X__'2!N˲,Z&M>{S.K88FIENDB`thonny-3.2.7/thonny/res/stop_alt.png0000644000175000017500000000051213611773167020531 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxc`^Dp"<_'ϟjWcÊ_nXa?X 8_{Lm> ' vZ[}T[5NNkK|XY NNcS^6 5sG 8K/pS߫2oL98@upPD9S6qÒ/ dž-{@Y6IENDB`thonny-3.2.7/thonny/res/_disabled_arrow-down.gif0000644000175000017500000000152713611773167022761 0ustar annamaaannamaa00000000000000GIF87aċ,< X@"E2Ǐ ɓ˖;thonny-3.2.7/thonny/res/PrintLnkTarget.vbs0000644000175000017500000000041613611773167021625 0ustar annamaaannamaa00000000000000' used for getting path of network location from shortcut set WshShell = WScript.CreateObject("WScript.Shell") set Lnk = WshShell.Createshortcut(WScript.Arguments(0)) WScript.Echo Lnk.TargetPath ' usage cscript /Nologo PrintTarget.vbs .\shortcutname\target.lnk thonny-3.2.7/thonny/res/_disabled_stop_2x_alt.png0000644000175000017500000000073113611773167023133 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATx헻JAY؊":>B^QX+("^\vEfV81He!?ߜvV,G2S9;Z'3_0VIENDB`thonny-3.2.7/thonny/res/folder.gif0000644000175000017500000000060213611773167020140 0ustar annamaaannamaa00000000000000GIF89a5GWƮtˮgȯu̳xζz׾sÄ{|Ȉ|}~~̀΁΁ρς҃҄ԅӃՅև׆ׇوڈ܉܊ۈߋߋ!Created with GIMP! ?,_A,Hd P#;hLv;Mh+˥d0k4I]RJ"` T'&# z|~x $5I!rz{? |r ZHzTTHA;thonny-3.2.7/thonny/res/save-file_2x_alt.png0000644000175000017500000000217713611773167022041 0ustar annamaaannamaa00000000000000PNG  IHDR szz pHYs  ~1IDATXKU}=:Nb2$Al@@D[!dJ! W*w![>6YĕyFB橓L}qNU"}B:&&VY~{/ "Ɗ `iwpI ?x衅F*3`Bn&=~=3o~wƩ_]119$3ZMgyT&jmݜ{g(aU9jQ-` EUpu*(Z]w۰ɢqN )*1fk@qMմ xрן@IAЉ8-(u4ӻv)^<^pS7@Y~hiLf)nɀxE$p$q{<޻ gsE)~D x*][!RL4$Z/AWLc:`|iπR3?$+h 6/YD=CWEwȄhq$pnD%bp>DmֱdOҡ=a}]<T|K="  ,~x_N3}'^y UED(ʒ̩s\;6"O:#i?WZCc$\G2눻9 6/ɭe2)lIw`ʚq:=j_it,5zCB kTSV;R%YcIf9yV1Nq*&f".DڴQ%vq UfL9-H'9Yۚ4ϨEǘQ@DQ%"h+KzbC[9cKK:diNQՔu *xD8+*XYQ.>2b3K҉:̀ Kɐ<U&c[ J]9-IgH=q YjEfC*;LKnݺe_m, r h)Z X@_jؗt>|6'ȤJe<E-nwzKXV |œPm"I~ 쇤F'jޝv#Kͺ՚/%SvA%Oin7X[_,k% lX+r)KXRFk[ l*̴9;1{)6jS/5):\ Di :$8`(6\pKFwF9b%FY(/#kT9*/>fRKlGcrTǵźyd%ًxf{Pa "p7O:gI~=sǹ.[ESVo E%k 9#PL#nſg{xL8Ob{6$uj!Y +mivϜx؜=&`DA_٫x Z ߚDsi-U<:RMx2  B[vv8ED:X<\T߬GV7rFl\nf8ʙ ߀+alNM;#~17f棈wW"th|}@|5Т:>z%)Z?= 7OC;D:4Ll4 FڸIjӠb( +&¡ƜePwP;QJ%Is9=gvr6"f+';@çj@r9ByH0x l>VH=} b?r?FHуp N.I'$4A%ϳ!W<*]}|8SHl-Q8` g Nu|/D*n\hķ}%:JP>lhuP4fyҐܡ.^s>oC# /׭R-;2 9ƚLz.4$` '%ٟk9(㓟!N z0b*Gj$O^nH#+R%rT"QgHȓof`7P D!+,GZπ@>U?[GnBy} I(oɂl N.~ < dumΰL{g&Mtũ\BY`f$^lM_>hX=,.GguTTY%;%`]vN(zo aI$G.U'9yԕ1I2򦿔gԐnS@,38TWp6a XX>i5"3W 3a<Ңt{O2\?Rʾ,촜W{TȔzX7).H9_/ M[Q-IENDB`thonny-3.2.7/thonny/res/step-out_2x.png0000644000175000017500000000143613611773167021103 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxKSq"un* @HP’zU _0 ͇f4LJaZ>M]df$!9ӻosun(|=wwcٳKӧ M "o,s~5z(>Mr f0գey64)@1 c&\ZLt(#KB +A5$F[SƉz/MHSQ*MĊuM"/Lt*̝Jcya; ֟ݥh/P.24ԎnHs:]ﱁ|^8cxVz.ͅZsj} _ľ!_@Kʀc9!P#֬0VzkBՏI#p|0i[_'X`ܔ->'wœKrnjί@9kꍱ?(g|p9"n}6QÉy˯=곃O7@bfv8[QV0πB(g,n BB-;w  Cd4եxl>rf^Zπm |#(''g58UŸ#ϭמV@Ӄr<Pn"& 1:5|uj ,÷_v76BΘNiش6D9"!7Bٲ_ɹ?|p:3k՚칳 kO㤋7{(iM:41rAA2"D(/PWٜ9sd }ntscړ$HD0N6'KdrFVXxC(NlKslMun? l\U,l)@A9D9#1f2N,3s2U:^Δ}ݧ;߄Z E.É9Ĕd 3RW]cDŠ UV4u(E5S6LsBsal`A O|WT W7]|?Z71e'^Z!͈,8#sA*_Yӝw ""1ֽXESTw -Ze6ld&dh Gz%%̚U˛ZX&<.W67z\#b5D*ϕtN-V쉹9\1qY6b27h@h3 mTr_={jl i]koY昮,'BH%#-Mn\% Cx/Yр}bW^͟o՗u|H6u6 FJ  k_8t=ӆ7ėXXT-gIbL2];ڞ5Qڮ\&yv)sR\e ՆS}ᱯ]{.~rt'VJpb=N}>XJnm{۳cU%/L 8vn5+E:Uuzq;nX籇lAOZ4F#\# [;oС;6ڲنxO.J A>7/xMKY@z?]+= d YvՓ3 z@G"C])8qcSp]{;00ch\G….B[ugrwwӚaL\6ALCX蹏05y\RbPg29|Y q@EpzdNNf;;{essw?6mze;8rdj喝׃jPK Btz㞱Q?Ϗ?~yuT_s%^E Dhooo}g2bM`B`l [՜^PJqˍoMJ/X_!2|:WƘi0 +֢{OUUEbpN]4;Y5(*5MLE(,ၳ3Cryy9Crsl`|}rBS78CDHd¡6VK}~!e})r;PU ?^t&_EIENDB`thonny-3.2.7/thonny/res/python-file.gif0000644000175000017500000000116213611773167021125 0ustar annamaaannamaa00000000000000GIF89ao2l3l6p6q7r9u:v;w;x=y>{?}@}E}@~DDHMbUZ^fcÒltw͌ˠźϼMNPژRSY\TUWaX`Z\_]o`abdr}r!Created with GIMP! ,VJKORVWWXYZ`KGHD\PIK  ^``dTKMNV[bddgX& fCSiY e>Bƃ]QfgcF79l_ UE?<83.@`# f=:51+/Lnaa72jڬAC [Z$$'ܤ Q[6lpqFC3g>tDC0a;thonny-3.2.7/thonny/res/save-file_Linux.png0000644000175000017500000000161713611773167021745 0ustar annamaaannamaa00000000000000PNG  IHDRabKGDC pHYs  tIME 7*ؿtEXtCommentMenu-sized icon ========== (c) 2003 Jakub 'jimmac' Steiner, http://jimmac.musichall.cz created with the GIMP, http://www.gimp.orggGIDAT8˝MHTaL1͑QlQQ4&E.B(,V-*ETR( "((j["DETjܛN al6<=_'?[ظ3 T[&Ÿ?ͻϝ 4wt퍭Uk:#km'-Q7˺; <}۝;ƨf(ce#+s >b$y,%_FDDdsZzD/Hϫ/.wY%<r$qDxXBAA(W'n۱wp=/x|vl_PPP#wҘX̌M4єXi^"2"0e1.XͻǪ Q_ͭ{h\Î,4M9H*|!mkص)i8(m41MCRO-hm aPYYޚ <۶qy!<]s?D30DQ,@.x]:R,Fs4_;3L"bmIENDB`thonny-3.2.7/thonny/res/terminal.png0000644000175000017500000000123413611773167020521 0ustar annamaaannamaa00000000000000PNG  IHDRabKGD pHYs  tIME %F)IDAT8}KTQ?w|3*dA W\E6jA`6JEb-%¢4P#+}_gF-s?{稡81Tbl9qgzǏMzN3uOޱ^,_7O[̦N?M$m=)/!"xqxIyAὣB?BDyYὔ@my uZ465$x%@lח 7 8vD3 y9K!Im&J%x!ë7/Gam~A@m @)]/yVˏP po'' ))W;E:KW/(x7>S:9.JqJBR((n Qo>B]#p67mll4(!aFEkb'Z5hYY)hi 䗾_6d֕Q6 e5FX;$"עMIENDB`thonny-3.2.7/thonny/res/_disabled_nav-forward.png0000644000175000017500000000064413611773167023126 0ustar annamaaannamaa00000000000000PNG  IHDRakIDATxOKA;ft:t)H7$cLOw{bdwOQhV=Oc`#NTδ_}|_ync!p;^]__g>L X P>?N|wNxVdP+b&/^vi Js%i|+KxcNNc/\]](|7ߞy(zy5x3]@T*2rppй`jkkkqsF5xbxꔕ`r99g}~ "ch4>\YVfW05WptrF6#2·ËXOqd3P*HRfmZt"V\qt#bKde\&E1.{[(D$)b+++J)SV8("8dq>R-'=j,.zZ9sYqJ)1j5GHKKKk-J)s8bEnh1]P+=Bq0Z.`M9PJa%JQT'''JFAEIʀidMULz^DEl6sLf-c9Ǭ|O^2_hgs^9{goZKX$F.PJ4M= :>'/TJfR|Y{6 t 5Tʇ(Z#"u-"0R[jc \(8b&R 94{JeSJ%2 ZF:ۈJT8Fvρي-y櫔J25oqcADd2$7wݮw]/bx9G׻sһ0LAׯ_vz CqR51oaHEy& |(( L& Xk}k{]W'm2{J§llV׵}[ϳ-.O1r|巵 0R.R*0P, ƘϞ=R*g>`< >@x .eY X`4HCL!,ODlIENDB`thonny-3.2.7/thonny/res/_disabled_help.png0000644000175000017500000000135113611773167021624 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxmnZW5kA($qҴ4F"~XMe+JhNmJ199mzqcY5?k~u||wxTu] dV˥bu 8<#Foh׉+7x=ߞ~\WZ.?V?o{Robͥt<{] >GmrYMR>ݿkN^֘w7'l9y\ToeaQՉFɣH'blIƓZ ;.-: wX6шUvސ7`^ICo4Ox`St\[}V94Tw<@D0FOȮ)QdqB ZZ:kv6}5ta!sm"J)D"x/0FBkAd5DdQD#?h-8 TG\ 1JU: چ[M7A.mG60FZc$cQ^5r.R7_\U~xxB|M>ŋ`,+Rwmb{﷍7 &@kz2Gm=7{mk~1Lш>n:҉(gtSr*W?aRE8+:چ?j /IENDB`thonny-3.2.7/thonny/res/boxminus_light.png0000644000175000017500000000222213611773167021737 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2zTXtRaw profile type exifxڭ[( EEI`8GUϠqs|*$ YZ߿FƐB\r3Wwn׃=rcӚ`1,yK^ ?JmMly,GB /neِP~_3 q, 7'RcƑS䭎@{-COPeMH,nD(_ddC{*S}!@z=>@ICE[VN.7gskďrQAm{.%csmdkoHh -$ Q& %b`RNm BtX3*F*I*PlotB+EC0Fxf(> h2B\<#䈌%T?|kp3v݆<7LE~/`Һ E#S F@8ހ ىA7Qy /M Xyu{({{A¨45SAU&&Jt5ƘbN'OSJ9i匷3rxm~ nqK[.lW| EK,U*긆5Ts\-4m;Zk=o֗ j$5F Rf Ǝ\k~KsqԮ>z[C~ZYy%ΗeLs߾c$y/,e߈'μ7M.ՇϤMoby\KDJ'曲S~]gk曲8/|Sęo89}"r2 =bKGD pHYs.#.#x?vtIME*Z3tEXtCommentCreated with GIMPW[IDAT(͒A @ YxЊe=8ХC@ U'h:L.IgؗwUۧ8lS-5ksIENDB`thonny-3.2.7/thonny/res/16x16-blank.gif0000644000175000017500000000150013611773167020535 0ustar annamaaannamaa00000000000000GIF89aiACw %!5!mUku]-!57ߏ% 53%#yoW{a#!;=w!症))#]Wgcyc-)%!瓁sYg?COK#ua#99}{e}#+#kek o w_77'?7yo[=?!雋+'1-#}ekA?{ 3+w}u_-#߯''qY##;=陉)#ic--%!s[?COI#mgm 79'?7{!#}g!,H*\ȰÇ#JHŁ;thonny-3.2.7/thonny/res/_disabled_boxdot_light.png0000644000175000017500000000025113611773167023360 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2pIDATx ! NۋH7!+X^'aMD4.[k<'T @fnߛM[REOܖ6~1M0;$! sےNJ\O['~1%IENDB`thonny-3.2.7/thonny/res/step-over_2x.png0000644000175000017500000000176613611773167021255 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxOSWy?`>w%{a 5>.D}[NDU BK3<iDWĊ E+Va#4*5*R;s`CZ]'=w}HHG<!nHXU+)8hnъE_TK#ZjՈ5UƏ*n)m,;İ0ګYt ACtլH?)MPW5 Gn"81oAˣLc%bA{،x.@X_b~tѯ77OZx:DS1[ J_(3& 6SiAŗMC_3rV `=3&Fl1fl4`T1iMEGT\_19\ >XdrnǬO"lEumNΫϤ@Jd_:%#+^Žs;&oNau wm#e0ڽ z ?c&RLg3j9ǧàV `%\㴂r ջ9#s*-Qv*=WEuWu2[>9GtsTUJv$XraMrDE*_<5ei_5O7da}F)kؑd}l. mToPd(+]co%jاJCd(dEi^ɪ 8 cR|k{9s>욬!iPawΙ]<ȋ5ר/ӗι'Wi=݃_>~㧧_}( plÃ`R*rQ}ؾ L"0*!ݵk3L"p>wĒ:7`YZ:2~xUw6 ƿgX-Yf\v[FB7v)hK[@LۅXK., KcrnxQؔ0M"y;8B4%sA 8n%2Z+ B^)&A  [ e3ڹoɎ, ć): A8J&*ysX[]K >=ٕ̖} RC<6ED4#` *P6@ #]@3gp壷 B"DxMDj=t3jǩVmmNTrnI[&\W+;jUKI_f 8;5B6쓋/,l~DzNl)M)ۘ'R$R ؘd:n'n5Z'D$ 'rvBސWhj2~6|߾nsHv#`^}0\[AO=0P&"-"Rtp!RlbXXY_(h;YcI oQDs(8"QKF\ZjYXt: d28NE(bG3-ϯ Kb N&Dɐ B@U:u]}B_4lr%v8h?lT(gD@[@D90j4V$P$f%ID"r- L@ DEHV@  xmdQ.LMMEX"P6GuM·dDI0qLD$lp@0{Fe!S"<mqs+&IȊ|FIENDB`thonny-3.2.7/thonny/res/_disabled_python-file.gif0000644000175000017500000000175513611773167023123 0ustar annamaaannamaa00000000000000GIF87aŹyvtƷ~ž,@H"`bGB@$0P rP`  ( @@PHժ5Š , (P`p 8 `(v @@ 0 ˘@0 $@۶;thonny-3.2.7/thonny/res/step-over.png0000644000175000017500000000071113611773167020631 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxc`>`~㓵oOֽ~_z ͢lJ`RMI;;;l3ÊغTS+Z[IΆ :;;(~rr"rW$Buuu"{K;###QԎ |+1'Ǝ qDȹ/^KJx,V'_~6H$k(1GdBl&'j։C|q˲G[4 `DlY’2^$I6-4$nKpDZ*p701qkkFU[5sees"KKKUeI"Eo޼e444|$`J>\0P|ˢ|x}} SMC{{{U%iǼ]ݺa SSSx< eqFP$Y*x^{JdE#B8:bD!=ł+$$ BI-$$2N80H !h3;3Uag{gzfF#}DE|з(.T^ObAͦS3yn_zw;Y}'P.^(Ozq#s1q̷N#y{㵷k}3˾__./d!RBkRJBTU<U@eiV7oޤjcER$I?]#֎o(T8sAR:u c ys]w~g(1Ibiik-ι RJ^{UYyc<À PJaCt:ۍ .ƘdBiZ6V=J)jaͷˁ2A=?,رcIQ cc߇Rs#+eFCnmmO:jW.c EPrv]0??oVWW&>t\}!8 dWF{nuFΏ6_;oFz/_`105c ߒ#>3?&AU5YftYZlngz- w!@ &J*',Iާji. 5ޥh9M?35$g/nB@YKj<5pba71d#Ԓ81kmjGix@"n[K yTE?N3!\cc;&w(%X11H-xQ1P~ pԩO-֖̋jc8Y&NM]\hmkj ؐ1enzL^{1AQjƲӋjj!2unl؍ qf1ZNIFOs`0խ思SnČ$-;GAFߎuZIsnH;0dƍYu gDbl\JNrR~|Wb+<M?R).\3'<ZZz (}+|gVT=![]=0% k&T|ͱ [㘝3:&J7JIBK3Uh@*yث!9RB.jy8%?շ6 IENDB`thonny-3.2.7/thonny/res/new-file_Linux_2x.png0000644000175000017500000000176013611773167022210 0ustar annamaaannamaa00000000000000PNG  IHDR szzsBIT|dIDATXŗKO[G3sm .L %Rd n*Tj.*FAjC"5ܙŵøT=hf4s,_l'n`m[g/B;`}}\.1c' Cs}w<^x;LOoWxqζj_s)Q߬D"0 cY7!45)H caNj9GXnӅq"lr>VjD0fTm<еJD[< =$>֜#{/U@K8|1ཏUX#u[^csg zb&F 3yƂ zUFdoKqas/@RhBbj9<1jKԣJpݝ_/n 7AFSWrY?]W8i1iqs^E/Ӷ9&P? 2ŋHarfqL9B$7 œ=,7K/@Z ¬LUi&@ו۞ ig"@Jeh):FH<6660f0q4da^jee%bJR8I A՜3![RC0Ҭ,*H*Qz䁻[Y2F譌,UM(cNU\.Ag

ξ'B;tdz x;B-/=윊p=FO0kJxƵO@m {0tr߇.R:˖0$i`Yi {FR<ځc[2<jdץ\Ei-W``"R2X"V,Z5BT"OhkYMÇ *Xj ;qЙsXe4MjY6grq4lH@a )3D*HbyYu` $. 1[`Y 1h%1h`"$CM7n($`Y!"@r*O3`Y" 592$%FT`  < $ p[h =ŊT'Q$aRkYS]5RS.( ;thonny-3.2.7/thonny/res/debug-current-script.png0000644000175000017500000000106313611773167022756 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxc`0 O!al OP$vq7rMfpgtb"|^:A}]OU?~R?|ێD{xY7M `a[1;C|ųU-HqpmktRAO;X_'AA tvNO"wlWz{8z7t} yx+ۻ|9,@a` bFjf[~jmWVu+K}` 7 NJ|*K[Ohi2y0u^X F]_ \ D"sE| !QtW6&-o\?Yjm (Cct5bjIENDB`thonny-3.2.7/thonny/res/_disabled_boxminus_light.png0000644000175000017500000000024013611773167023723 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2gIDATxQ 0 3]2P٦mT}PCvZ+ "@ұE׌H"HU $! T4x)03Hj[*ߠUn0 $,v4IENDB`thonny-3.2.7/thonny/res/stop.png0000644000175000017500000000131613611773167017674 0ustar annamaaannamaa00000000000000PNG  IHDR(-SePLTEpeiACw %!5!mUku]-!57ߏ% 53%#yoW{a#!;=w!症))#]Wgcyc-)%!瓁sYg?COK#ua#99}{e}#+#kek o w_77'?7yo[=?!雋+'1-#}ekA?{ 3+w}u_-#߯''qY##;=陉)#ic--%!s[?COI#mgm 79'?7{!#}gϦtRNS@fbKGDH pHYs.#.#x?vtIME 7 |iIDATc`,U$UK#(HK0w/䶇u}|}Mr!|?߲2SSS55_AiMI 0h rdHrp t刈 p z\\NNN B@P/A4"0"A " 4nPpbCp\ CgJi?l ȩ2Q9<,(((xym옟/bbYj61IENDB`thonny-3.2.7/thonny/res/boxplus_light.png0000644000175000017500000000223313611773167021571 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2zTXtRaw profile type exifxڭm(Y.=gv0˟Wc{Vt ߝ1yR1:\>,䎫;;?;9&"EcK ˒e@n & IZP#Á[,C*˳?cY.dKK4W"݋3$@{-Ct bw?"TI q rJ!G% |.r:C_^FOзi&TBҿsv95{,uR{;VW|ĒZԹ965ߊh_pi${%*hGmh3 0vsm+BЋTQa,uqӬ;PVB*Xx];'B01^_>Q}l(| qibc&P+a&l f N ŀl2!`XAE1# B ;T !@6Y `yP?j >r(Qa1Z'j15o%V(i),Sɒ'n؏9Ko(ɦ7ҖRV_Cj]vݱ۞ | -6kV:Jk=ح }A5]Ajvq 3 J"K r˂]AgA }c /inh3W2?t: m8JEkGM|IݹίGh?1}}sG?-'7ЉdǣE~ؓ|h?I/|I#دbKGD pHYs.#.#x?vtIMEG*tEXtCommentCreated with GIMPWgIDAT(ϵK 0CЃf.˜1 I$X0p>6JRU]U݇ |åmU|?C=xFwQ̴IENDB`thonny-3.2.7/thonny/res/_disabled_run-current-script.png0000644000175000017500000000115413611773167024463 0ustar annamaaannamaa00000000000000PNG  IHDRa3IDATxS]OA=v-(B!i4D%#g'>D"-111H +egwgPO}sə;&'/Ֆʭ($DD}{?{ټ[QD+ô;Xta%MTlx31w^^|_VՖO O%,M>ƴ?4E ςfP+&$ 3X`!I&0S|Vj1e_$LIїQb8{rQ:GHmOlnCgtu t&QQhEgm#A &2+8&:5rmۅ8>Ho83YKnt|skuӖ *BaEgn-? f7jIENDB`thonny-3.2.7/thonny/res/information.png0000644000175000017500000000153713611773167021241 0ustar annamaaannamaa00000000000000PNG  IHDRabKGDC pHYs  tIME 2:P5tEXtComment(c) 2004 Jakub Steiner Created with The GIMPًoIDAT8˕KHTqƿ;:G&YjfR>E"ġ%ԤlbpaE1EM%It&JJ͊4Lqtwo5~s~s8T\L)%) 1ek^v}STޔ0bmeZqU7S{z?\!&,zIW׈%ooߓc,RFg}ZUYEӣm%Y{[n=v_0kEI珖D N Jhs;u&%srm'$=Wn/@ ,C-f PPn(.*rraB+YWUH43 sW߽%::6ilZN̾24PU}z YXXx(7VL6^|IENDB`thonny-3.2.7/thonny/res/1x1-white.gif0000644000175000017500000000144713611773167020424 0ustar annamaaannamaa00000000000000GIF89a3f++3+f+++UU3UfUUU3f3f3fՙ3f3333f3333+3+33+f3+3+3+3U3U33Uf3U3U3U3333f3333333f3333333f3ՙ333333f333ff3ffffff+f+3f+ff+f+f+fUfU3fUffUfUfUff3fffffff3fffffff3fffՙffff3fffff3f̙++3+f++̙+UU3UfUU̙U3f̙3f̙3fՙ̙3f̙3f++3+f+++UU3UfUUÙ̀3̀f̪̪̀̀̀3̪f̪̪̪3fՙ3f3f++3+f+++UU3UfUUU3f3f3fՙ3f!,;thonny-3.2.7/thonny/res/_disabled_boxx_light.png0000644000175000017500000000026313611773167023044 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2zIDATx Aǖ{ (jf.$vs wL^;AQB\]b֠ҺId&Of"DfGo3;{ٞPe1ܽ:3viIENDB`thonny-3.2.7/thonny/res/_disabled_star_2x.png0000644000175000017500000000272113611773167022260 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxŗnEK։A,,X M\+CUAE| @${+S'J+ɴs\Д,>6HF>|ȧn(klgm1~O` D_;?*V6:7$q"Zskn|0lgzg39*@ۍG0U'4^ 4=~mgš3 Z7;~Ѭ[ ts]`N`1n4JZN9``w-prҿ^ @^;se@95\;%4:%f`$ƬtucfS p `7X? ίWpNs@Y5~"zwc .WpaFLgGj:1jjSdtưpheH ?&J2q ,,ղk3lk5{i%׭J nǏuL1ڿ~,J`[5/,C5·"ZoM4ptzfʹz2McVE^Mg鼳Mk?mi\\=! nӃGr$wަBԿVScC[ghZHGC+rlYx_}7+q1]oX3ҼpOe-vw_<{ &H 25vrT95o7,diiI~yOV``*8߳@F[ kEsh}V% B߿ ˳Jt6Dx^Q] kۉ*.vNOl|q&OǟW\;og"NQÙ7Hkqq1Q,OBcSh*~-WXDb+.ΥRGG푚=~e<_fՔSA5T"G,tpzr\)U3Wgx p]&0X.P".يCrIZJ' I:r{ нb·DnY^h-PE,2gAsR  kej3J*z>0KP𴎠K  %`#Zo "߶W[~VOTsnIENDB`thonny-3.2.7/thonny/res/_disabled_text-file.gif0000644000175000017500000000175013611773167022561 0ustar annamaaannamaa00000000000000GIF87aƄq~zp~,@a"JH@h` )ɓ(  08qgO *ѣH TP&(* `ŠEY ` K ;@@XX ,3@@MZ X]@װa3( ;thonny-3.2.7/thonny/res/save-file_alt.png0000644000175000017500000000115113611773167021417 0ustar annamaaannamaa00000000000000PNG  IHDRa pHYs  ~IDAT8˥OKTQ)clTF!܄ڟMZ m[*Oa}A ]-[dA*u"wѹc3sg{:; }<ENֳn:?_~|Xk> |ݓN6s8ʋ u:u864n 'Ņ,/QE@Quh,^5' Fגs7||duKE<TwAՁ*b= Qa].O V'}] Y \F#(NNsu/Ai k{9A&Xg7 8PbonY8T5l# \ _#6;H[ml׸I4Mo3 N$bCjL?Tk7 : |,XQWc$as7T5ZZ 뵖g@Xp R?jPTP4 Dk1^p:,o. ևדl4ݿTHs( ɺidM!iWj0wL>MLcIENDB`thonny-3.2.7/thonny/res/_disabled_stop.png0000644000175000017500000000116613611773167021665 0ustar annamaaannamaa00000000000000PNG  IHDRa=IDATxeMkSQ9MR~7 mB]A\ݵ+\  pFAP\.b[쇦I~{M:03sec8'P@],^1h ΢4a&/MjU\|FxQajyZ0P7#ހjN_G{WXxoq=4)9}E4E8Kv\^L):rrmuJ'IZI ZȚI` PrP 2cu;ӄf`I$an 91+pIENDB`thonny-3.2.7/thonny/res/run-to-cursor_2x.png0000644000175000017500000000075413611773167022064 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxc`4y#cB4Q2|Ibf$rX} ]Q? nXAn >:xpco()8`}o֩P'~}UIXW+V?9`{X^T(\Z3'v _r|IYT hЗs¿o;2 뀕b*DtZ}@fo N+E?r/ʽZAT"\Y&L?9m`ۻV>z̀pYzo_ߠ,V,|q!jWZ(E)] %QUYN~|aC+tvqEA;.(Ac( NGcnݼ5'qU?uIVvqc4@.l"@2a録yr SZJ߾ݚj$[UV$M^\aU(C0?,ٶEYR8GQ8W0!s~24#"viG R١ZT@qQIENDB`thonny-3.2.7/thonny/res/_disabled_1x1-white.gif0000644000175000017500000000144013611773167022403 0ustar annamaaannamaa00000000000000GIF87a,;thonny-3.2.7/thonny/res/resume_2x.png0000644000175000017500000000202613611773167020617 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATx]lSuƹ DEk+zYY׮ka|%Y2Ǻp̡Bdl> 75/jCb0+wn{|v:䗾}.ZYY3vQL&Vt MIs+AR56C8{@fz2驿f,b&*3`&'F ~H3kv0C-(ٍuNMklY *0 0rt0Ϭ _Ւ ׄt9jުU``_CEA;gք/LUw'aKu^Dg?}IhfM"_c!ݨ\Bav1R Y*r%ãw-pe9 GBޑfք/k-`0/JҺ"_m 7/ Av̚E^Ue̟78|A7iSN,o]}/{̚E*8c.BAٗ۷ `ˤ h\&v~`Yȯ,vʐ/2gĮP0LB3kUT[g}Yh3u13\ț} z< &v䟛k̚E>g(: %{Åfp6AeIxs.H3m' ͬ KS9K}BJHxaw`)ߏ@B7$5|W4ĶW '^j}SN&TnqsYȯ#N:'v v`u+=ei=V? &>=m b{̚E^GlwxBwQr<uu3E^.bw@:|ŏ 6^-:]ya:dAe=nKoJqKwKyP}X~aZZ`_cf`;lmnoītrysuȻ{}zĠĠšššġšŢƢƣƣ ǣǤǤǤĤǤ Ȧɦ ɧǧɧɧɨɨȨċ˪˪̋ԏͭϰ%זҕؙ՗ۜոڝԹBݡ֢ۿ#ڿ,ڬ9==\QNL1TZU([/DN75Y]`Bc7a]cdfZ]Na`fa_\dXad`bex!Created with GIMP! ,  *:qX8p 8p3)2iH"VTh'K Jɿ %RD)ԤG-zD'@0ԉ0[P1PIK(U(sNFDH@E€;thonny-3.2.7/thonny/res/_disabled_step-into_2x.png0000644000175000017500000000137013611773167023230 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxMOW;cR)DH"RVDXd$*;V(0$4 ֨% 6gyq,X+]׹y3gyβg(tvfJYCju{㓿: ]C1` iLڰ]dL\Os Ȍw{1of\(?\΅cE&&opy=UZs|:=GX(alt x՜c'O!?|&ww__aG 08;Jg ;#@Q Fw@yF|5NAzIYa_y~%0 < M$tJӍ~ g7\{LLjr L8;vsP"Ki`apW"B6Rt)mm&jha5<5ZDvPRn}$$a9դ2HwI k|e{cŌåa:'/ }0ZOVu.OIVlU8s [-tbד"qD˕;{"YYY:nYeM,mo,7$ySv}1^ʊ z}8n~Y<Іrgk_KArGH`v`.-Lȑ9Nl;oݣ Okq_Ȗ Lw|r(RGg]tp\^Lldf%ytwNޚxXrY]?²t]Ҍa6B^ c s3I|x~;<0MU5'|_ !9vAJ0«FhR"ɫ=vRvŸ>S*x5|)ͮ}5YV,U [Ǽ^ Ex/BAt_k44O8.X^1="XˋWqSJ;Ջc!ë4bSʥ(lRIdWRkt;i -4Zkvؖ˷f?}y/=7ģ/Ƭlʢ첱[ 8s9 $Ʉi$/4E61UsqIYܜ % @lJ%bX4(^ܶL <bnLJ)nf4ʣyL1๐q(5w=03d6RJЊH[-bΦ<Ǎ9`[hD8:"XJX۪q[fąINm*#&ū"Ԍi@Ń""q}N2CmEʰ7@@-ScWɔ\@d@8%"Rb WZS="e!9Dp| Pրʥ4S@#{m:=):P @krwi`a"a%,,Z'H ^6F#}vD֜4z~\;B\fXB$՛ݠ@v PHbFCH6BK't` l4秋hQ?64$#H=DjftqZoL=5u)RdmZݫFրe#}⠵7riL8cu<ַ?D1Rjf~jDEAk L)sU >(JS ,ZZ{IC6|pҌ8W"Jupz nsxՊVW^af?cqgaR_ioj}!~XkHHr{gmw]Κ]>p@xeM:WZ>O_yz9k:K/߽wό7\"J|lΩޫZoy2?ݩ|cn|1SEcvĊqޫfsm~sOpw~♔y" k|޹׽87kZn |S ЄR7{uA0/OD# !oǿ Y IENDB`thonny-3.2.7/thonny/res/_disabled_birdseye.png0000644000175000017500000000133613611773167022505 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxOOFS9 JlOHt(/wK.\@]Jw7 C@RQVꜟ7oގ3Mʶj:E~xR^. ĥyqFn `ZZ?e2r.Tu@JitkkkR`}HKR>ˋe0bQT*\׍ V`]:^KDFуSrWq10,o!q4!@oU a}]JimoMh`8M1w‚|G f:O(5=L$@Qi(0;rYx݂&HJPt]("JquuLFV*P @.?ٙ}}ww<;;;eRX%4jKrl8Wbww!ϕRJuܟ-7aoIENDB`thonny-3.2.7/thonny/res/_disabled_terminal_2x.png0000644000175000017500000000234713611773167023126 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxŗQSEwNcS勚T`,?G7 ,|UߌʃpI cowۇ݃#$hjvggg{.Rw|9AvR\q07ppw-{{!3_.ܻC]*l6vaL$o/5ŋ#XX\^^iWEH&fdFK;OUƥsakkVr޿ )ID!wEAUih `( /*g`L=䯻s &'5oLp/5~Y[ PU\}*͜8E}0x>`3GD0S : YrT@JHByDQ9"ݬ`"v{HE:`YKTshLĨ&DQ04~%E xT}-\5\2"M0)x7$&N"TܪESK c LM̰NWfE!QHLhnNAf0 "ݘK7ثﰵ^ VWINV+m-jS[fi6UĎ^7"8?i,ss })d$p _&}.T8j mb Cc̔R6=D f@Gm|706:V;7ƨijlwGղp̕ \_IG+o㉧ɲoyI˫i?<M ]Ǐ0B:*3Y.P3?ϚM4 Ry"CyU-sYʀJrl\]>]?Sakφܿ.!&&t/>u&r J+UnjMN.}=4~ؼN2^v^&"RJe[_>&1@~4hAH$IHAY>lpΣ ^/ovD}gFJծ*!Z#qZ@zln|T](J%VJlŅ$[ޚݩMY~91wZ! Ct^jzsr =&30THo䥢@NW %X SeA+CKi:u,ؘ) @o `.Rt8|Tk!dD"!z@2WP%l`_(>l[5.4wGs;puVfi `xū ̤\Tjs #'sIӂ;ϖ Ap߱MN~a_Q|jPbBZN^(܂I0=^Dtbf< HLّg`tm߽!̗(O6jE}&l4ߘ<#1Sz@yfBֵ;HE> |}|:L&fH okcamH)Op3S8?07v&Yf'ᜫ~uOlqf<&tkL((GX\Ǣ}GGjEFtJS6ZLJ iy{sTi _:oj[_?l- IENDB`thonny-3.2.7/thonny/res/_disabled_tab-close-active.gif0000644000175000017500000000154213611773167024001 0ustar annamaaannamaa00000000000000GIF87a ```, GHX ! 3Ǐ =ɓ˗/ 8sSg@;thonny-3.2.7/thonny/res/tab-close-active.gif0000644000175000017500000000007213611773167022010 0ustar annamaaannamaa00000000000000GIF89a ! , { dLj;thonny-3.2.7/thonny/res/open-file.png0000644000175000017500000000106713611773167020570 0ustar annamaaannamaa00000000000000PNG  IHDR(-SPLTE dddJ”4zdt4dj$4*Բt$ĒTJDT„ڄ42$TTjrTdZDԊDԪTz$4"$IJԒ҄$dztbTĊttdJ$ҤD4tr$ԒTʄڄD:4$tbD4*$ĺtz͜etRNS@fbKGDH pHYs.#.#x?vtIME :!IDATun@E'0."] EA6t }hH&&>9;c/ET4iu 6m"acӡ* )׽s-D+Z4{{h>ř5']5o)p @m{LS0bl4@"F?5mVpa>0Mӧ[ǷJ؀7IENDB`thonny-3.2.7/thonny/res/birdseye.png0000644000175000017500000000231113611773167020511 0ustar annamaaannamaa00000000000000PNG  IHDRagAMA a cHRMz&u0`:pQ< pHYs  YiTXtXML:com.adobe.xmp 1 L'YIDAT8mS]Ha~iYpiVJMP16ۅZ-ptj] ֨Av1^؈ Fr㘱4ޝiw~>ss>d( huvv&8RT,ZoW:6I SX,?.HkkZl]{T*rvsSN!2_ANMM'''>FV^  }d2N&&&Γ$@*|5LKAiks=D]H$B]],Zjtb[juvnaa^hP= e`O(f},ބQ*ʥF8teYJ^x~>(lnn\W{!Le?rDfT*L&#GGdl il4~} &D"2/X,Fr#~Am610r*`!Jtzz:#|>/<.S> !j6}hyޙc!=6 rP hصP8  XS 6ވԱY<0+I` r9Z_)®(+1bxcc#{rwvroꚚ-yuURiT*u~򳪪ZhA ;~_^xA?Uh5*IENDB`thonny-3.2.7/thonny/res/outline-method.gif0000644000175000017500000000110213611773167021616 0ustar annamaaannamaa00000000000000GIF89ahtɂЉӋE}MKNMQNRSS]`_badffnnv{~}͂ψґ֓זחךڨ۩۫ݱNORUUVW[]b_a۰߲!A,A??$$$4 &>& 4 -- +@@+"5*@@==;6 '@,@,@' 0(@//,.ɂ"3)@@:2%9=9<7# pah bX@я`H ŋ;thonny-3.2.7/thonny/res/boxdot.png0000644000175000017500000000043213611773167020204 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2bKGD pHYs.#.#x?vtIME . >iTXtCommentCreated with GIMPd.e~IDAT(cd]ܾ~ }Z n. &N81Taĉ((,3goO1 a}0C M}hjiYntn:M-mq}MyIENDB`thonny-3.2.7/thonny/res/_disabled_resume_2x.png0000644000175000017500000000156513611773167022614 0ustar annamaaannamaa00000000000000PNG  IHDR szz oWƏEv`8 7ʛ;:|zQ?'261ΕA+onNO `)O|wo8n}fPONw^gHQ2XO5(XdueM|pgLYC \`"k }ZQkA\VS2p  FvęB2kE]:`Fp_W+o0LƖp@P1`79[:ӶP{־fr4,xyU|)UXa 1|clO1C9iF8]. Qq &>(o3c Reg30zEH_=yB _!t^EBeޛqe8t@DrI'4ސFUXgtv4pAԀ؄odD11EqѱIoPI~t1t f)38XͶŹtHDh_cq4 ˌG3蕈7kiiZ~~9LJ ;$U& 1߹Vc1 T:48F͎?NlFy?jW4`ŕܿ5UKש ]*7!(V[.esZN>'IENDB`thonny-3.2.7/thonny/res/_disabled_boxminus.png0000644000175000017500000000030013611773167022531 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2IDATxcLHH`````=? Ç+m g1>|xϯK?õk]"΄SbX9~b8p "s<^?UMza xQ u,DƂuIENDB`thonny-3.2.7/thonny/res/quit_2x.png0000644000175000017500000000173013611773167020302 0ustar annamaaannamaa00000000000000PNG  IHDR szzsBIT|d pHYs  zIDATXoE?c;MXD(^H4pE؎Ҟ{ilV)H $(I]﮽.c:k_id~ߛff1p7$H־>='n2y=*xK8Lp\{_n&b,Pdr2IBQD܇Zn2ЕgcaD7YJ:TH2WJP~|R2>K{avM?spiD]u?*tS)\ i+%buOgPZ@w.oL%lvR)#%ruBX<Λ^,ҍg@U:\ya/J`>^_\bڵ @"B z|rY:ͦOD{l[]cC!40TGhdp1 q 7\<{~)#|%B>gϞOtm,|7 :a9_;_͙\q}xva-3 a/kp"K34 m/B/pt#y!STH1 w pbNA 84kV? [q_,nP7_3c$QIENDB`thonny-3.2.7/thonny/res/step-into_2x.png0000644000175000017500000000137113611773167021243 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxKSQBwݵ ARKK+|q)kwa{Hד:E```e`B슏Ko  M"y{Ͻ GXN%x"Z =]D#skwJ!HK}ӎWY x!sN V ;ُh3Xϸ@딘 )OXA`h-1Jdcqoبߩg ߦ_]܃.>˴Q u A =D!sp4V.ڵx̃/]a}î"889Tؖ܃V5[Ռh0xv!N‡γXid[zDRʈVCl3ScVi?EN͂d7_(fbFl-y!>K36n[MDL'l:!k&$GlUr*-8o$ =SaX'QMBOLh,QK^7y"K[PA*igI7$ $Pnþsf:3 LumȎ\Oݨ_򺇋 +v s4i>]2~fC IENDB`thonny-3.2.7/thonny/res/_disabled_quit.png0000644000175000017500000000071513611773167021661 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxN0qⴽ$^.I1J+` ,Hn!ipv,X{Dz^K&$"|"n;w(a9A.ҫ%p.Ji:S{xp~yEZ2Cq"@GB $e23+KfiYFY̊|N$Dӱ0ΪW󺹷5/g+LOMR)H.Ab\bzryChOVD)!X#;"p]wP!Q7 b\Im,br?+R @C/ۤJSS")%]8C7)yl4%MӁ]Rضmη(hZqlյm<37ߨmۆٰ^NYyxGk ֈ 0\`i}}uaoMlMIENDB`thonny-3.2.7/thonny/res/_disabled_debug-current-script_2x.png0000644000175000017500000000245013611773167025356 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxŖMsTE&$Ac@DبUK5_pÏh CWn,$LCd} Duw~缧ٳu:'{;v@i:?Ng=(?ugtlA4}z΀V*_WOE4&wQ;Rt?تջaNo| ˝xqCxy dF~)FNw=4NV!Ze11ݜ;zbSWlTH[DCΔg{`çۧ FDW^qW~ ZXD ˝G[K ce1-"EC8O?߉8_IENDB`thonny-3.2.7/thonny/res/_disabled_hard-drive.gif0000644000175000017500000000165713611773167022713 0ustar annamaaannamaa00000000000000GIF87aƶ,@H (\P!@"Ǐ IɑR K @8o @ JthG(]*PJ jʕ Kv ۷m `ݻ ߿;thonny-3.2.7/thonny/res/debug-current-script_2x.png0000644000175000017500000000265513611773167023377 0ustar annamaaannamaa00000000000000PNG  IHDR szztIDATxWiPSWGÎ :"yIuCH C)SkepݸU[ۢ (*0( *R\@-Ψ=ewL&3;|9fРkB q3"0pl!`,!;Ӎby{<9% #G7+ 9Ɨ73|ɖHiMtPi Jxs^4]Gg5ōXʐ *jBPIJP #8$_g@lL:;pߔ(3󰻪w8Xwi+Dٟ K"I[:$Qmhz'$;`(@Tᒽ C/HbSrq 5k!@X-.JbGSr[pqR%Sm.$e€IuJl$9dnK(fp )Hpznmt޻ǯ8 |~r !7%B(+G4ОY*-Jo2=nǵ;ܾw|wRg8+Pv;ń>IoJ!SfX ujg Ρj%Z4~D#8|aRZ ,dj^3\֏9i{\?Cv9kXʯf l;-9pU&ͫ+O2dxq\Uw.r> 뎭AqJƱ8t[l?=D0w=}\gI8fӳe#wFԶ@CG oL[%[fA݂`_&l]UǗ`.X-c[i:6%+ylL+~h:GQMZ)#(:`f-jl%5˱#OB`:/%c#'*]rp1j3,M%;~"8zq 0X?cUYƥgsʌ-)^c+ dT/b_)֗Nf>wmP Z6˅k{Izx&rTO>$oVRiK>&hI>WSo +J _S0n\x$d`Dn߿7Y!%PB;D\1=i2'5&2 x0{z=MJ}ҀJ=<%pA|ƃwtI}ײ,4"A쑠]iu [T1,N[4B &L`,=N=uMvj.|xϯK?õk]"΄Sl7[% d1lŸ?l%0wM<`D2GhIENDB`thonny-3.2.7/thonny/res/_disabled_star.png0000644000175000017500000000114713611773167021650 0ustar annamaaannamaa00000000000000PNG  IHDRa.IDATxnP9ۤu&$T VHPu`Puʢ;JQ+!^Ic 6ܚvHG8~|6Uk+*/c;I#2Z79{ycok_dV\ % 3Ƌ89=s\ĒyN6T8=1Q9Ae8fOVoV(שT0;c#eARb ~ce0 tpsr}'ڻE7.m,.. SDTffL>Hg^1 -zNIPyDY&2) N?;^uy9x4,+߷h +1eN9YXzM%L#>)EHOx30IENDB`thonny-3.2.7/thonny/res/_disabled_closed-folder.gif0000644000175000017500000000172313611773167023402 0ustar annamaaannamaa00000000000000GIF87aŹpÚabĴzůƾŠ,@H  !C `G @$IX)0c S @ ӧO Jժh ׯ_ KY p&  0 ߿~ @@(^L@h6Ϡ;;thonny-3.2.7/thonny/res/_disabled_open-file_Linux_2x.png0000644000175000017500000000230113611773167024336 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxŗoE?ofכ6дjCRrBB\ gnT Ю&MFg̼Yǎwӈ$kٙ7ZrEs{1g\xc<Ϲsg?#Mמ_>]"9kkkzj U. ʊ4mF#qMU`v"'UT=|O ~ummͅpR7Mh7~ߘn/8k4esswիx z(朙"#3iʕ+WPǓ˗< ceTl{d7n,F0sUջ{Wչh EAQ9`fB:f"2ٳXSXdY2U׌n>Tjn`8jד,58j' d08@sx[T4,xq`ϨI>_Z>{69op Ǘ'Z+QﱲM/v1[\ujƍ4I,CG&*`:;ŷ_HQy(D=uqRgX#"5%Gm{G#*$^Fin !I*ԕaVUMYV] w|h3:*wBj{G%nAyp jUv~ XU5GK3T':TNEhjt!ޓjm]ښqrK2h \Ѭ#kґd:(QOj ٩搖oԨ mE)N&uP]h5::!FEykWuސjU~qyIQQ~vtdbS* "a0j6U4'^PZ.""TWgj5Guuc׀2F0)}y^ i t4Oz{NnRf10md0y Mu?TyPGy=O'θ zIENDB`thonny-3.2.7/thonny/res/_disabled_harddisk_2x.png0000644000175000017500000000223113611773167023074 0ustar annamaaannamaa00000000000000PNG  IHDR szz`IDATx]kF3WnqCS:nMhC~Aoʏ ^4)Vbwd@irF3:y=gfѣGOSyۮvww :~/eryB@ !@XB޹? ^a) e""!B9Z{^5"?}'OAXF<ʲLf3s+-:9 "TUEUUu?`Fn8@? 3Iw:{ж-M5Z%vwwaȽ{ww6!Gumuι~QuB sBXkx! +,5sw4 m.&+շi$:6V6QDqI44MCucVh1iڷHe뺮Y Rn޼9 "鵩TUE۶+ilF]u ȡ5M%MXh/iv(J?Ջ2Y1^qR Smj|Ʀ}G)@&֚Wuz,#24%IWF/"t]ܸqcHQwk*Ҕ)J>!C ñZV%m۲< (+vB4(+}Xd1uPkֺfY8禓$3Gyu0V:c > },juUUBb&"hL&shnnlQJQ|%>~kɲ˰szzt:4MS8ב)Ʉ4M{ XYmcKsμx9=dӟZ;I=Z#JY0c]+^qѶ-UUsv~Fv!ZzA666|}]YZlI&kޥE.X.W 6 )P0hk[Xm5e.-"JWKRQSqρhOeg9sΆ\l|S(9sh]n؋^ԱCt <PJ6ƍ7>6 nlnTfRfG߬=)@솪q䝓TF: `<Jx37ǎfc8u2i!ygq58L`ڙ–t(?=.[g`ޅ[uj.o-3Ǵ;O"׃Yy<㭡s2`F8Tdȶ3mELU? 5 H4s2Z#ܹ"c1ǽd!d@(Mq%) =ma-=.΍n.G eI, E闪-n%clc ِ {=)SvA,ܲ7i sҾ^釗SZ|MϜ˴D=9dcZ`R1^+[@kOLvIAR{,}\sy#E`vJOO\ Ȑ*qBbk8`,MvYGe`븎z5\Wˑ9*aE őȑCmu!Y}~ < 6p{#a'.xR }^խvna;n|* dAܙ )sR8ӷ:Ƭl.l FO-Tm8G* g pb-xz۠G9vۡ2$ET8`v[4a$;7NiЀE$թ/6C䦧iw.1rRc!f"!ԳMd^ dHܷ`uL3i;zcaE aE6?nHSx* ĩ?B'?k\7ёYb̋}җ=sNJXIENDB`thonny-3.2.7/thonny/res/nav-backward_2x.png0000644000175000017500000000121413611773167021655 0ustar annamaaannamaa00000000000000PNG  IHDR szzSIDATx_OPݒ,(;^3dA ;2؜lcnc 14dF Y61j||_HeHkv_Ҟ6yYZړI^p 5Rl W(|%,6 zP}>f6ʇV~\ 0>l >g<7&T;uCRG6,f^yqθY:ʨnT?33U  Oo|SlE= q^:uLӲY~4 csF{n _ !EϣR4Kp; ɩB#`Ւ|}aSɀ'2Q_[0܉AIO N`vZ3؉0o\5BEx*kM㳺aVb_X\ӔD=CE.c)}S%_C.Ah%0^>&LZ3Ï5`v_Θ ~fqrGd ~17$z;}>sZ[ >glx%z%}Wb>fmJ#W:#^Ixeg붜*5Z?/tIENDB`thonny-3.2.7/thonny/res/_disabled_boxplus_light.png0000644000175000017500000000026013611773167023555 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2wIDATx0Bqλ1؆Fv`|>N"ARBUy%a LOig~2d`I4I*lo{ } *, U$x3 I"ɥ7iIENDB`thonny-3.2.7/thonny/res/_disabled_run-to-cursor.png0000644000175000017500000000052313611773167023433 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxcLHH`XN!ѕ`l xt,A06> ƜR> 57#g1'Y ,gc165,n|q-(%;wŀk*xvƿ ljϟ8b$g{6\ \ \INɀ?d``MGϯo=}A].x7 Ӂ+cS׀bu2@qfb4;b h>IENDB`thonny-3.2.7/thonny/res/_disabled_thonny.png0000644000175000017500000001210213611773167022207 0ustar annamaaannamaa00000000000000PNG  IHDR\rf IDATxob$RbY#zԖce˖ij Ty /d+zӻPAb"T~EUy\S(E@P](S9䜙F‡G&7=}/^DDԟtD$9 )D<@c )D<@c )D<@c )D<@c )D<@c )D<@c )D<@c )D<@c )D<@c )D<@c )D<@c .H9`p7˒I qM8 Fׁ_H2F .]O/Őp UJ at3,0Bpw'UI:9O!};q9Svq-qH''2 'I$}\yncO> me>,M;ܭ*㾆OU* S(bZR.T*Rn|/PZ߰4h 9y}P`vvIiJ 靁7ž\ !'ccc It]?{^# \ u=bJ#YYYi| |@QRGwddUO<ʭ[#h>='׿0bxj),>SOm7.A_T*VVVJP/GI"\ zt ? y Q,P$'w'/w:.>4sM}f/YIE)s I>O./P,9rGXܷU2u7sieJ%[IN\;1Fv̅Htc sss>}z͵X= 럘i{#ֱvØ#J&]0PW) QyO3$SO H<22Ø\Vt{z,-X~ÖfxE sW|>r1;}oxE NJݝm[Ǔ.Sk(fT )d`mmV }=$LMM1>>N.kţG/_o6UD* >TjcLOOS*"r9JR-{k-}P@$ 3X^^6 Qfgg)Jټx\.$=9?Sc?0E4m;H@`lnnvbȡCx饗8|pOF|7xUA࿀iRD`&}b\y Zѣ\rr\0='?P' _$LX>G_oppwyᰗ,pxsyOYvhB4k/(s\U Ç{)ޔm ha?$  }io[onII 3]w澀J$] +wm$GzW*h =WM 7I꾀ȱcǬN sNSӣP(0==͉'b78VzE85PV/u'O͛7#-TUXXX`xx344044,׮]kSa Y&@t{1 yQ&Y__>ڵk;2,--*ɓ'5 x/H)@L1 $NMoKFp%;*"'Bo U3wi;kwC\\p!d˗[Y(j*C h||3gt~ іt΅ 299i1@xn [/9$ji  |Hg"mVU]Ёv[66<@tF+޽k6ڤiө߁0#EC?3}]ONN{XGΞ=tIӢ |jLq %M7n`c#Z6 tRD{ՌhQUݻ5\!iPVrJ!Ϸ >G)!բ߫YMꂠ6D%dnǧ0 v4Sx?4T )ܸq#ҁayy9rHOT Z, @t{;o>a}Q: {٩diYs)|(Úih7y hNIsWc)3B&5wYث hl7HvYU3Új:t? dGjsM ?Hqٸo& KEMfo9-{5vsƳZH~5pĤf@2u'W~f9lu e&X@l`U3l&6)dWg92u.m̦ZJi=&&&.|(Z,~U|?' YӅu=6]uCosY#"jJ {l ˻怃OZPHgRP66ۂ@&F3@M})7S,m ˻Nha4cʹ@ia||+cfcki[^nZ,;>@ /AESU̙3{h1P&BW^yツfTdƢVwn+EۂnzܹH!ہOAE}wnO&e(?~<_*Q( xlV4uF ibsYw>3324}.^ pVMEEV*(>#?PHZ 䨣2Qt.3WHf&ҿX4Qw,1byJй=+:"y+ 4lvCZx mQHRt4=k^H@k6{ϣM+S h,}6-߼nɕ'i dX__od)yjWӾ zj/K N\}z] xbeH<֜3lAP`nn7' W])e{CX>E@5D5T V z^ ,4l|3ok˒*>J3>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!Created with GIMP! , HVMd~(۸xRCMpR~M"y&cȖA3tP[nܶkV'Y7dڕ -Z`fX7a"IDiHZzWAQER)#Sիbb*SȾJ7MZ4hΚ5[LY2dX4!@zQS&-ZV;thonny-3.2.7/thonny/res/boxx_light.png0000644000175000017500000000041013611773167021050 0ustar annamaaannamaa00000000000000PNG  IHDR ;*2bKGD pHYs.#.#x?vtIME ,QiTXtCommentCreated with GIMPd.elIDAT(ϥ1P C?9YܡxXlEIĜ󷜠$&xCvmZE>OPUTC]C:z_9 ^IENDB`thonny-3.2.7/thonny/res/_disabled_folder.gif0000644000175000017500000000175413611773167022137 0ustar annamaaannamaa00000000000000GIF87aø|Ƨ,@@A `P@hH@@ `X@0) ͛ ϟ Q(`Uʵ+vXV@ @@x ``( c"K& @h0P@ӧ& kcm;thonny-3.2.7/thonny/res/_disabled_run-current-script_2x.png0000644000175000017500000000240113611773167025070 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxŗOWً@NM"ViqOm?ǪM M*Ub.!^6Ҫ?i3Μ3{Vnݺ)C{rN ||\BFA- j),׎xΩB3hS-"D!Q"[-=Qt)\orA"aZ.s]\ǒwi1/_7"lZRM ;?=%^stf #{1D 6wb^d9 埏j[xRp&ƲT "@@&|5Dcϕ'Cőz~Vr+8%1 j1;vbfuoŕ( 0UK7$_,L$91ce<1ӹD%PPn.^TOO[P2utqt#}~&\{XG(&S\pr6^^ {\.ٖکɌQ--gXpE>VsH2%~^^\nrh)\TK,Bd`2Жc9̗13~yh)-@.qHj579XZCj5PAi q(1`*i~Ei:aJY9P4ISy 5doDz\{UE2Pb;/Sgd@3:wח8 FQ r2~Ɔ\c_q2~ bQhOas&FEDR,}חpɎxܾ a}(&uLQ pe= X؎$#cQkkvL(,>zITq=66 6"('hۀ9#Q5Qp̝gwo ,ͦ`Obx)'"W5bCB#sg}zXD02:w,䇴`u7?}7AdF888N*7D u?"5Ǖ_NC헙ciU`D-TUqWt宿1,ƙF]-?P|"HEJn"3Nmx8PZ:A} ]|>4iyԲ?=00:KIENDB`thonny-3.2.7/thonny/res/_disabled_nav-forward_2x.png0000644000175000017500000000135513611773167023537 0ustar annamaaannamaa00000000000000PNG  IHDR szzIDATxMOQK ҕ!*X &n4!"$0LhR6-$'y9sI.2Z.T}g@x/J/o!u%^=O·!OwH15#@g#|F "Z w%4OBLD#C4 pa t.hݠ0stPX4O?WwGɁ;Z7^b  ( jp(Fj ]\=*So9]6/jP v>iʱmedM4r8y'L G~ڇ~:r{mN-`e2N,+D-d׏uhz7U&;Keq'VĊ%\THʱZ"I#BV`&W{Of&YGG9y"V6E15̻ؖ"fA<V&oJmd{c,x5Zm7vmZ{sՓg4|_^(Qk~i;?57`~~ 3Bܚ3gIENDB`thonny-3.2.7/thonny/res/save-file.png0000644000175000017500000000103713611773167020562 0ustar annamaaannamaa00000000000000PNG  IHDR(-SPLTEtD:dj$JTbtrDJ4BDTR:dbTRTDRĤtz䴺4:䄊DJTZ$2Ddz4RdjtzTR4:tTZdjTZt4BDBԔ4JdbTJ$Bz䔒42dtzzD:tdZtjTbtz'tRNS@fbKGDH pHYs.#.#x?vtIME ; bIDATe0P"E^ B!1l!sf Xu(X=~9ML*b}5Jp5>MkUojqk03p_@L^i>BϞH鷙0;tUp] MԢtTd볽ySyr+_,17z~zW:{/)(1t_= O 9caNZ18@ߟvpp2ʶ$~)g I ڈ+~H$IJ ~kndvj,ʢg_|/TWJ)w]={';Z[٦Mvvv" 74Ɛwܶi/hmIv;wb3˖-F"͗Xd-|>mcPJ*D9wfO#+(7w\0(#u]:::l߾]^N,Z6P(RQ,)h7sv#ϞF,­sy^cqpyAmxG2dΜ93>"!V\I. 1&D,Ï6si92ϑ`g3>RJRhq]ŋcY֖ ֭^Ѐ8(H)Rrooohw` Ch(++CA.CkMPή֯_o"Q|'HljF!,[CSlJSDQ8dd2y8)%H .Å: u%222 ¶eY$I`ߜN4PQn#Dkz,_ߑRJ{R!L2dddgϢFʱ,+4ԏb1=g!8ZkL@ @8\ Z%>/oX]xIENDB`thonny-3.2.7/thonny/res/help_2x.png0000644000175000017500000000426713611773167020260 0ustar annamaaannamaa00000000000000PNG  IHDR szzsBIT|dnIDATXŗ{pU{snnn޹ G^"D (Luv3:cgӇm+}MhV)vE ZÃ$JBBrܳw8$i359wo}kK^Jn]ّaFCq#6z_qxHCCmh[mO1Y+披Y>AXke<z h·!\(OՌ_"8ap$MǟY^:9|O>[O8ΆXm}UOIX~7i<ۍ4$!R )/Zk,(d-WS:'X_},>V|hSep'{K!Lba`)1 iHCr)dҨ,+Jpɖk['>@.7ܒn=ʞaibYnpmƤIe0${E\[15ˊ3}sCC-L V˛vT2di PQ GnV:}aZ?A(V V$lݛr .^eûGw47߼zÐyL,Ϫٜj'.IIa8]0rM x]meʻm<8Ri;@LO(  3? ,ebY&4ؽ#4pk 4Z6[^],9K'A<s4 [q|?5; s{Mi \|?$!m\ttssʢk-n^[C1N 7I0xy,,ٮA)1KI, ƕ>!ŎhU45d*,$4ncY N"`͒TZs?ek֠¥!*K Z/ gN_n=Wrf*2 NsRJc8 4?2@m<\tkO nhg0iN`%1lO$ Ȝ̴Td7H!RLc8Ջ(PJa6u^1;NoLR 3S-HM( @ χ8I).+I/+82DWedR/G X8/Թ@ "UfRӍJ)"):{yGHy"CݱWt.MhLB<c4⟲ce=)HH5<thMɲX;'5^>֏Ra$va|FC~Ebu47Ԇ /uMuBיS{4VXXұDMV([9SwI۶d>c|?XWN՝pS">1ĄM"amlN=ZSFia.}wl8KMMhN3\ܪ, M=(ZH"kJs&a;>h&a+D%l]]JV`W}%훪7҄j`sH)q[fZ 7.%h` /5շ63 8 fW[FUK .+ 8o(@v'<#a,([+*0>a_k:v=>>gYHx|ƧW~^<ʩ~Z O0# 'K/\8s0?hSw{p_t-D ~Aov;7,~k+W^Qˣ>>dddwww@@@;;;MMM:::dddgggSSSmmmCCC999ccckkkTTTAAAAAAQQQ```TTTYYYggg999nnnQQQfff111qqqBBBrrrHHH444UUUVVVEEEmmmoooBBBTTT222MMMQQQ𶶶www333JJJttt뙙VVVIII...aaa~~~hhhIIIrrr===UUU}}}IIIJJJlll~~~pppPPPUUU{{{YYYOOO@@@|||YYY⹹999NNN|||{{{QQQ<<<]]]```uuurrrrrrjjjQQQ<<<333333888AAA;;;~~~---===FFF[[[eee~~~bbbǵӼhhhfffaaaEEEHHHQQQvvvbbb񈈈eeepppYYYQQQOOOQQQbbbkkk[[[TTTXXXhhhkkkPPP___...KKK????????????????( @ ;;;;;;;;;;;;;;;;;;mmmmmmiiimmmiiizzziiizzzhhhzzzdddzzzdddzzzAAAzzzdddzzzdddzzz___zzzdddzzzdddzzzdddzzzdddzzzzzzdddzzzdddzzzfffdddyyydddzzzssssssssssssssssssfffdddzzzzzzdddzzzmmmjjjjjjjjjjjjjjjmmmdddzzziiizzzfffdddzzzdddzzz:::dddzzzdddzzzdddzzzhhhzzzdddyyyfffdddzzz::::::dddzzzdddzzzhhhzzz888zzz;;;mmmssssssssssssssssssssssssssssssssssssssssssfff888;;;mmmjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjmmm?    ( @???PNG  IHDR\rfIDATx_ř cYb;S`<]dp:v<89 y#$:.ҝtIĂxPS#~u޾FǕ:O:.q|vhS|$6b@^CT}2ʕ+Zl?~\MNNnslIJAD#:=TpyՖ-[ڵkՒ%K*ӧ޽{:v{"$ta:iYJ&&&pG_l.ul.٨W^mVzYu!ϫSN޿rJbs }gSw}J ccUۧި; _|QY! Br2P|rsNqFh"WFpEMPM[~ft`kBI@XוAN hko]]qEHޙMٯf*Dw$TɎaÆ9A۷`94h']u<{ M!T"x饗J=fhO6o9/@_ӱ[ RB;N `Yuv}K,58"@2AB@i !'C@`u@ҹ_=8dIqPPF`:+g:}Yʟs?gXT3i@m {ZzO/ge"+V|`P+6@j#On/,H oAyɤҷ࣏>R\rI'jؓo[nԓ'{zgJ=Bؓc-ARG@ {D'@dRx=N((M2z[vFYG#cb:r {RrRxDn"M:' l/GѦ;:=8 .wz? طh"ɥC9 KߓjjjLwd { PS~c {r)P 3,k-Ɖ 5<*W80 2 :K :k0 `GGu С  2Nt :8\ Wu A `A3#*@D#W@xg;Y9^H"ؑ@' *@D)4"3X~@= 2M)YA  `GS.Y {@d ;R@ct)@d ;@1 2ŐD"A P )@d ;@1 S{ᓭ>3j4RbDdֱIǭ:nбL4Nz̢*y[g[|_ǫ:8I `Ŋر,?' #K)pݼ|$V@Ez"ԲeJ=^J'''THktkƥ4h'W[lQk׮UKٳСCjǎw)/&8?`q AVZo߮e] +j֭C+Ѹ@n.l";:Ez+gΜQ<:p@:Qͬ@vdlL5\V^~auM7նϧ|/`Gf]J=>i!>|aLNju+ur@;wN v@<u+u TJH@~0'.urn*ϟ[ou{.wo9u+c]@!̅ O. }'.[hϞ=;0ĉj͚5R) {@dv .[T:!_~j޽jtt4 -cҥFO0`@ijXi`2vak}cӪF'OT^{%V@ybQzk tUf``@>|Ǹ{_^D7@ybQzؚzUV@y2םM6Jf7@y2gr)g}}}]Ȥnzd|GYgpU&! 0#3|||\t}B fMQpM(B`F\ޓ4 <111F9L8&#^lj'Ԛ5kok!dgzS6lP:uJ۷OvڄXlr,!! 0:~M8&'dKBrm ;^Աt ##& 6Rm򬎻 {TNbޑ&@nl񨎫{<5pœ܃Xw& ;F?q0Z:>=ľ#5M "bޑ$@'ؑ$ H0 a@ A $ H0 a@ A $ H0 a@ A $ H0 a@ A $ H0 a@ A $ H0 a@ A $ H0 agKYIENDB`thonny-3.2.7/thonny/res/open-file_Linux.png0000644000175000017500000000124013611773167021740 0ustar annamaaannamaa00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8KQ?}oIkRK?% rjХ7#M+hh!EB-siꛖ`p{9+CCCD͆."@Q""}ݸ\Uo/,-9s@D'&_Lslppp936&N3cxhͳ nTUnH)[fz+D07f cd "BUU]keY"=va#AUM5s}Eιvp5bPRJc MZd;8bL; y/qk"K;ʢX JJ_(H `|LH)YJ pJ[GDY Nq)%SMPPXlb{ט dr4f4ScD$mφI1s̝lNVJa.X33؎l7zԝ, ܉wgm`^Z?q!SKwY^ZôldoKu2IENDB`thonny-3.2.7/thonny/res/_disabled_open_folder.gif0000644000175000017500000000173513611773167023157 0ustar annamaaannamaa00000000000000GIF87aĭjŹÚpfġjfƭ,@H ! $  I@If 'P*-JXjZWKvlm  x  @0a #C.,0 pӨS;thonny-3.2.7/thonny/res/_disabled_debug-current-script.png0000644000175000017500000000110113611773167024735 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxkQ}of4ߙjR@wڂu.("dTqta]t')f L4f5J2Jouޥr44 V\0ӸL筈Y W*:iH>3 5XP0A; /,X%0GC80wp(N0-6հw Rq+v f0?lwhu~t]{[vV\N8{EݙIow:u$"+g9;O?^!ZCbΉ?DlZG&mZ ,X%(3hbϤ␂`5ħHFjG*!+|uxz~~V  vcC 29hÓ#)+\RȈBFD.ʅUHZ魽j m8VW@ Zg`}`5)6iwNT"w1yf2D$!Y`F IENDB`thonny-3.2.7/thonny/res/new-file.png0000644000175000017500000000045313611773167020416 0ustar annamaaannamaa00000000000000PNG  IHDR(-SEPLTEat-ԤԤ䔪4Jd䴺XtRNS@fbKGDH pHYs.#.#x?vtIME 9+hq/_IDATm EQR+ 1P{'eRpDsBE<`v(ۼQL4@F,]`@W?_W;niIENDB`thonny-3.2.7/thonny/res/outline-class.png0000644000175000017500000000116413611773167021472 0ustar annamaaannamaa00000000000000PNG  IHDRa;IDATxR[haˮC#E.5qiXߒmRaiKiZECckAvE1aj-OU5^>= %(Iw9..HM>+rPEt`CD,(gh:%ο%[2v =f{F<K'Ϡc$;YX׈2%]#VDXXIO-w4G!f-$;49hǥY^6=]_|@OAY5> x93pv-1 :[[&HH #$¼4 ct"ZҼ[{ /C2>h@C >%X&|ZZM^8LLAyM].5*ؘ̝bNQ}-hԂuy֬Y%-+Vݹ/a ,!74aT헔huY%mԧ͍C ǫc2`b7<2[ zf G+?dĦ( N^q;IENDB`thonny-3.2.7/thonny/res/_disabled_16x16-blank.gif0000644000175000017500000000147013611773167022531 0ustar annamaaannamaa00000000000000GIF87a```,@H*\ȰÇ#JHŁ;thonny-3.2.7/thonny/res/tab-close.gif0000644000175000017500000000151213611773167020537 0ustar annamaaannamaa00000000000000GIF89a 3f++3+f+++UU3UfUUU3f3f3fՙ3f3333f3333+3+33+f3+3+3+3U3U33Uf3U3U3U3333f3333333f3333333f3ՙ333333f333ff3ffffff+f+3f+ff+f+f+fUfU3fUffUfUfUff3fffffff3fffffff3fffՙffff3fffff3f̙++3+f++̙+UU3UfUU̙U3f̙3f̙3fՙ̙3f̙3f++3+f+++UU3UfUUÙ̀3̀f̪̪̀̀̀3̪f̪̪̪3fՙ! , ' HT@2OY& N4"Ə;thonny-3.2.7/thonny/res/_disabled_open-file_Linux.png0000644000175000017500000000075713611773167023742 0ustar annamaaannamaa00000000000000PNG  IHDRaIDATxSQ3X ƈ.Z}WXX ZfmL\E4${|7&Ѡ8 3ߟl0Y@`/|jUczq|taf[য়Nǣ3%p z^S?2H)UEpby3?=e`>׃fF[m_LΟ f2NAR `f5IݶI~q_+Ewg4Xlْd`d% nYTh4@R84{0fc2~YfkEǏ:*Kg{|\4^ U K*aZYfNDBYL!B"ڰ\$) 4Ƃ|H?>x Zh;>V"dLΙ3QFUNQfEfRZ9;ztUW{Ik8F^J{ Komm1*C9E͘ N5?7hFImBԬAΗ X4fJ^fu\q2|U\KQX)"rMs{\C,%gP\[&#oۜC|GDK: \ n@Huˢ17X bS; FccH⫃!&(ըKhV ZiTyL5=wIEx@{L|љUX~N5WP3#3@{A։lY * %H%aE띓Iz*& Qz\KMPg7]PDkh3t"T Gq&–nzLwY/]=M _ ~Yh6IENDB`thonny-3.2.7/thonny/res/thonny.png0000644000175000017500000001201613611773167020225 0ustar annamaaannamaa00000000000000PNG  IHDR\rfIDATx_ř cYb;S`<]dp:v<89 y#$:.ҝtIĂxPS#~u޾FǕ:O:.q|vhS|$6b@^CT}2ʕ+Zl?~\MNNnslIJAD#:=TpyՖ-[ڵkՒ%K*ӧ޽{:v{"$ta:iYJ&&&pG_l.ul.٨W^mVzYu!ϫSN޿rJbs }gSw}J ccUۧި; _|QY! Br2P|rsNqFh"WFpEMPM[~ft`kBI@XוAN hko]]qEHޙMٯf*Dw$TɎaÆ9A۷`94h']u<{ M!T"x饗J=fhO6o9/@_ӱ[ RB;N `Yuv}K,58"@2AB@i !'C@`u@ҹ_=8dIqPPF`:+g:}Yʟs?gXT3i@m {ZzO/ge"+V|`P+6@j#On/,H oAyɤҷ࣏>R\rI'jؓo[nԓ'{zgJ=Bؓc-ARG@ {D'@dRx=N((M2z[vFYG#cb:r {RrRxDn"M:' l/GѦ;:=8 .wz? طh"ɥC9 KߓjjjLwd { PS~c {r)P 3,k-Ɖ 5<*W80 2 :K :k0 `GGu С  2Nt :8\ Wu A `A3#*@D#W@xg;Y9^H"ؑ@' *@D)4"3X~@= 2M)YA  `GS.Y {@d ;R@ct)@d ;@1 2ŐD"A P )@d ;@1 S{ᓭ>3j4RbDdֱIǭ:nбL4Nz̢*y[g[|_ǫ:8I `Ŋر,?' #K)pݼ|$V@Ez"ԲeJ=^J'''THktkƥ4h'W[lQk׮UKٳСCjǎw)/&8?`q AVZo߮e] +j֭C+Ѹ@n.l";:Ez+gΜQ<:p@:Qͬ@vdlL5\V^~auM7նϧ|/`Gf]J=>i!>|aLNju+ur@;wN v@<u+u TJH@~0'.urn*ϟ[ou{.wo9u+c]@!̅ O. }'.[hϞ=;0ĉj͚5R) {@dv .[T:!_~j޽jtt4 -cҥFO0`@ijXi`2vak}cӪF'OT^{%V@ybQzk tUf``@>|Ǹ{_^D7@ybQzؚzUV@y2םM6Jf7@y2gr)g}}}]Ȥnzd|GYgpU&! 0#3|||\t}B fMQpM(B`F\ޓ4 <111F9L8&#^lj'Ԛ5kok!dgzS6lP:uJ۷OvڄXlr,!! 0:~M8&'dKBrm ;^Աt ##& 6Rm򬎻 {TNbޑ&@nl񨎫{<5pœ܃Xw& ;F?q0Z:>=ľ#5M "bޑ$@'ؑ$ H0 a@ A $ H0 a@ A $ H0 a@ A $ H0 a@ A $ H0 a@ A $ H0 a@ A $ H0 agKYIENDB`thonny-3.2.7/thonny/res/_disabled_information.png0000644000175000017500000000121613611773167023221 0ustar annamaaannamaa00000000000000PNG  IHDRaUIDATx}MOSA;s?J[AM{%H h+7.ʸ0ƵѸ$hE1B)-m۹ mfsM_9'gp׺z+Dβ,z98m a *Fx: TRinϤS?6<\ʃe?N%Jydq2N,-TQ 2bA0@qg_(ױ-(6&<wJT%zRJHa "lFRRI˶֚( Xp(l)5E* O2gah[ EǶ^uK^>e D4^('灐sbՅ:h~IlCe6OI ^ȶfW_n؏ < DyV.e"+k2F\Z18|ӿg^ugYoVXg1 _{iL6~o,_Z6_@$o>.9[hf>,xIENDB`thonny-3.2.7/thonny/languages.py0000644000175000017500000000240713611774245017730 0ustar annamaaannamaa00000000000000from thonny import get_workbench BASE_LANGUAGE_CODE = "en_US" BASE_LANGUAGE_NAME = "English" # http://www.internationalphoneticalphabet.org/languages/language-names-in-native-language/ LANGUAGES_DICT = { "de_DE": "Deutsch [ALPHA]", "et_EE": "Eesti", BASE_LANGUAGE_CODE: BASE_LANGUAGE_NAME, "es_ES": "Español [ALPHA]", "fr_FR": "Français [BETA]", "it_IT": "Italiano [ALPHA]", "nl_NL": "Nederlands [BETA]", "pl_PL": "Polski [BETA]", "pt_PT": "Português (PT) [BETA]", "pt_BR": "Português (BR) [ALPHA]", "ru_RU": "Русский", "tr_TR": "Türkçe [BETA]", "uk_UA": "Українська", "zh_TW": "繁體中文-TW", "zh_CN": "简体中文 ", "ja_JP": "日本語 [ALPHA]", "lt_LT": "Lietuvių", "el_GR": "Ελληνικά [BETA]", } # how many spaces to add to button caption in order to make whole text visible BUTTON_PADDING_SIZES = {"zh_TW": 4, "zh_CN": 4, "ja_JP": 4} def get_button_padding(): code = get_workbench().get_option("general.language") if code in BUTTON_PADDING_SIZES: return BUTTON_PADDING_SIZES[code] * " " else: return "" def get_language_code_by_name(name): for code in LANGUAGES_DICT: if LANGUAGES_DICT[code] == name: return code thonny-3.2.7/thonny/export.py0000644000175000017500000000275113611773167017307 0ustar annamaaannamaa00000000000000import tkinter as tk from tkinter import ttk from thonny.ui_utils import CommonDialog page_specs = [] class ExportDialog(CommonDialog): def __init__(self, master): super().__init__(master=master) self.title("Export file") self.protocol("WM_DELETE_WINDOW", self.on_cancel) mainframe = ttk.Frame(self) mainframe.grid(row=0, column=0, sticky="nsew") self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.notebook = ttk.Notebook(mainframe) self.notebook.grid(row=3, column=0, columnspan=3, padx=20, pady=(20, 0), sticky="nsew") self.ok_button = ttk.Button(mainframe, text="OK", command=self.on_ok) self.ok_button.grid(row=4, column=1, sticky="e", padx=(20, 10), pady=(10, 20)) self.cancel_button = ttk.Button(mainframe, text="Cancel", command=self.on_cancel) self.cancel_button.grid(row=4, column=2, sticky="e", padx=(0, 20), pady=(10, 20)) mainframe.columnconfigure(0, weight=1) mainframe.rowconfigure(3, weight=1) for title, page_class in page_specs: page = page_class(self.notebook) self.notebook.add(page, text=title) def on_ok(self): print("OK") def on_cancel(self): print("Cancel") self.destroy() class LocalFilesExportPage(ttk.Frame): def __init__(self, master): super().__init__(master=master) def add_export_page(title, page_class): page_specs.append((title, page_class)) thonny-3.2.7/thonny/codeview.py0000644000175000017500000003706113611773167017575 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import io import os import re import tkinter as tk import tokenize from typing import Dict, Union # @UnusedImport from thonny import get_workbench, roughparse, tktextext, ui_utils from thonny.common import TextRange from thonny.tktextext import EnhancedText from thonny.ui_utils import EnhancedTextWithLogging, scrollbar_style _syntax_options = {} # type: Dict[str, Union[str, int]] # BREAKPOINT_SYMBOL = "•" # Bullet # BREAKPOINT_SYMBOL = "○" # White circle BREAKPOINT_SYMBOL = "●" # Black circle OLD_MAC_LINEBREAK = re.compile("\r(?!\n)") UNIX_LINEBREAK = re.compile("(? 1: text.insert("insert", indent) else: text._reindent_to(y.compute_backslash_indent()) else: assert 0, "bogus continuation type %r" % (c,) return "break" # This line starts a brand new stmt; indent relative to # indentation of initial line of closest preceding # interesting stmt. indent = y.get_base_indent_string() text.insert("insert", indent) if y.is_block_opener(): text.perform_smart_tab(event) elif indent and y.is_block_closer(): text.perform_smart_backspace(event) return "break" finally: text.see("insert") text.event_generate("<>") return "break" class CodeViewText(EnhancedTextWithLogging, PythonText): """Provides opportunities for monkey-patching by plugins""" def __init__(self, master=None, cnf={}, **kw): if "replace_tabs" not in kw: kw["replace_tabs"] = False super().__init__( master=master, tag_current_line=get_workbench().get_option("view.highlight_current_line"), cnf=cnf, **kw ) # Allow binding to events of all CodeView texts self.bindtags(self.bindtags() + ("CodeViewText",)) tktextext.fixwordbreaks(tk._default_root) def on_secondary_click(self, event=None): super().on_secondary_click(event) self.mark_set("insert", "@%d,%d" % (event.x, event.y)) menu = get_workbench().get_menu("edit") try: from thonny.plugins.debugger import get_current_debugger debugger = get_current_debugger() if debugger is not None: menu = debugger.get_editor_context_menu() except ImportError: pass menu.tk_popup(event.x_root, event.y_root) class CodeView(tktextext.EnhancedTextFrame): def __init__(self, master, propose_remove_line_numbers=False, **text_frame_args): super().__init__( master, text_class=CodeViewText, undo=True, wrap=tk.NONE, vertical_scrollbar_style=scrollbar_style("Vertical"), horizontal_scrollbar_style=scrollbar_style("Horizontal"), horizontal_scrollbar_class=ui_utils.AutoScrollbar, **text_frame_args ) # TODO: propose_remove_line_numbers on paste?? assert self._first_line_number is not None self._syntax_theme_change_binding = get_workbench().bind( "SyntaxThemeChanged", self._reload_theme_options, True ) self._original_newlines = os.linesep self._reload_theme_options() self._gutter.bind("", self._toggle_breakpoint, True) # self.text.tag_configure("breakpoint_line", background="pink") self._gutter.tag_configure("breakpoint", foreground="crimson") editor_font = tk.font.nametofont("EditorFont") spacer_font = editor_font.copy() spacer_font.configure(size=editor_font.cget("size") // 4) self._gutter.tag_configure("spacer", font=spacer_font) self._gutter.tag_configure("active", font="BoldEditorFont") self._gutter.tag_raise("spacer") def get_content(self): return self.text.get("1.0", "end-1c") # -1c because Text always adds a newline itself def detect_encoding(self, data): encoding, _ = tokenize.detect_encoding(io.BytesIO(data).readline) return encoding def get_content_as_bytes(self): content = self.get_content() # convert all linebreaks to original format content = OLD_MAC_LINEBREAK.sub(self._original_newlines, content) content = WINDOWS_LINEBREAK.sub(self._original_newlines, content) content = UNIX_LINEBREAK.sub(self._original_newlines, content) return content.encode(self.detect_encoding(content.encode("ascii", errors="replace"))) def set_content_as_bytes(self, data, keep_undo=False): encoding = self.detect_encoding(data) chars = data.decode(encoding) self.set_content(chars, keep_undo) def set_content(self, content, keep_undo=False): content, self._original_newlines = tweak_newlines(content) self.text.direct_delete("1.0", tk.END) self.text.direct_insert("1.0", content) if not keep_undo: self.text.edit_reset() def _toggle_breakpoint(self, event): index = "@%d,%d" % (event.x, event.y) start_index = index + " linestart" end_index = index + " lineend" if self.text.tag_nextrange("breakpoint_line", start_index, end_index): self.text.tag_remove("breakpoint_line", start_index, end_index) else: line_content = self.text.get(start_index, end_index).strip() if line_content and line_content[0] != "#": self.text.tag_add("breakpoint_line", start_index, end_index) self.update_gutter(clean=True) def _clean_selection(self): self.text.tag_remove("sel", "1.0", "end") self._gutter.tag_remove("sel", "1.0", "end") def _text_changed(self, event): self.update_gutter( clean=self.text._last_event_changed_line_count and self.text.tag_ranges("breakpoint_line") ) def compute_gutter_line(self, lineno, plain=False): if plain: yield str(lineno) + " ", () else: visual_line_number = self._first_line_number + lineno - 1 linestart = str(visual_line_number) + ".0" yield str(lineno), () if self.text.tag_nextrange("breakpoint_line", linestart, linestart + " lineend"): yield BREAKPOINT_SYMBOL, ("breakpoint",) else: yield " ", () def select_range(self, text_range): self.text.tag_remove("sel", "1.0", tk.END) if text_range: if isinstance(text_range, int): # it's line number start = str(text_range - self._first_line_number + 1) + ".0" end = str(text_range - self._first_line_number + 1) + ".end" elif isinstance(text_range, TextRange): start = "%s.%s" % ( text_range.lineno - self._first_line_number + 1, text_range.col_offset, ) end = "%s.%s" % ( text_range.end_lineno - self._first_line_number + 1, text_range.end_col_offset, ) else: assert isinstance(text_range, tuple) start, end = text_range self.text.tag_add("sel", start, end) if isinstance(text_range, int): self.text.mark_set("insert", end) self.text.see("%s -1 lines" % start) def get_breakpoint_line_numbers(self): result = set() for num_line in self._gutter.get("1.0", "end").splitlines(): if BREAKPOINT_SYMBOL in num_line: result.add(int(num_line.replace(BREAKPOINT_SYMBOL, ""))) return result def get_selected_range(self): if self.text.has_selection(): lineno, col_offset = map(int, self.text.index(tk.SEL_FIRST).split(".")) end_lineno, end_col_offset = map(int, self.text.index(tk.SEL_LAST).split(".")) else: lineno, col_offset = map(int, self.text.index(tk.INSERT).split(".")) end_lineno, end_col_offset = lineno, col_offset return TextRange(lineno, col_offset, end_lineno, end_col_offset) def destroy(self): super().destroy() get_workbench().unbind("SyntaxThemeChanged", self._reload_theme_options) def _reload_gutter_theme_options(self, event=None): # super()._reload_gutter_theme_options(event) if "GUTTER" in _syntax_options: opts = _syntax_options["GUTTER"].copy() if "background" in opts and "selectbackground" not in opts: opts["selectbackground"] = opts["background"] opts["inactiveselectbackground"] = opts["background"] if "foreground" in opts and "selectforeground" not in opts: opts["selectforeground"] = opts["foreground"] self._gutter.configure(opts) if "background" in opts: background = opts["background"] self._margin_line.configure(background=background) self._gutter.tag_configure("sel", background=background) if "breakpoint" in _syntax_options: self._gutter.tag_configure("breakpoint", _syntax_options["breakpoint"]) def set_syntax_options(syntax_options): global _syntax_options _syntax_options = syntax_options get_workbench().event_generate("SyntaxThemeChanged") def get_syntax_options_for_tag(tag, **base_options): global _syntax_options if tag in _syntax_options: base_options.update(_syntax_options[tag]) return base_options def tweak_newlines(content): cr_count = len(OLD_MAC_LINEBREAK.findall(content)) lf_count = len(UNIX_LINEBREAK.findall(content)) crlf_count = len(WINDOWS_LINEBREAK.findall(content)) if cr_count > 0 and lf_count == 0 and crlf_count == 0: original_newlines = "\r" elif crlf_count > 0 and lf_count == 0 and cr_count == 0: original_newlines = "\r\n" elif lf_count > 0 and crlf_count == 0 and cr_count == 0: original_newlines = "\n" else: original_newlines = os.linesep content = OLD_MAC_LINEBREAK.sub("\n", content) content = WINDOWS_LINEBREAK.sub("\n", content) return content, original_newlines thonny-3.2.7/thonny/backend.py0000644000175000017500000031671713611776475017374 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import ast import builtins import functools import importlib import inspect import io import logging import os.path import pkgutil import pydoc import re import signal import site import sys import tokenize import traceback import types import warnings from collections import namedtuple from importlib.machinery import PathFinder, SourceFileLoader import __main__ # @UnresolvedImport import _ast import thonny from thonny.common import ( BackendEvent, DebuggerCommand, DebuggerResponse, FrameInfo, InlineCommand, InlineResponse, InputSubmission, TextRange, ToplevelCommand, ToplevelResponse, UserError, ValueInfo, parse_message, path_startswith, # TODO: try to get rid of this range_contains_smaller, range_contains_smaller_or_equal, serialize_message, get_exe_dirs, is_same_path, EOFCommand, execute_system_command, ) import queue import dis BEFORE_STATEMENT_MARKER = "_thonny_hidden_before_stmt" BEFORE_EXPRESSION_MARKER = "_thonny_hidden_before_expr" AFTER_STATEMENT_MARKER = "_thonny_hidden_after_stmt" AFTER_EXPRESSION_MARKER = "_thonny_hidden_after_expr" logger = logging.getLogger("thonny.backend") _CONFIG_FILENAME = os.path.join(thonny.THONNY_USER_DIR, "backend_configuration.ini") _CO_GENERATOR = getattr(inspect, "CO_GENERATOR", 0) _CO_COROUTINE = getattr(inspect, "CO_COROUTINE", 0) _CO_ITERABLE_COROUTINE = getattr(inspect, "CO_ITERABLE_COROUTINE", 0) _CO_ASYNC_GENERATOR = getattr(inspect, "CO_ASYNC_GENERATOR", 0) _CO_WEIRDO = _CO_GENERATOR | _CO_COROUTINE | _CO_ITERABLE_COROUTINE | _CO_ASYNC_GENERATOR TempFrameInfo = namedtuple( "TempFrameInfo", [ "system_frame", "locals", "globals", "event", "focus", "node_tags", "current_statement", "current_root_expression", "current_evaluations", ], ) _vm = None class VM: def __init__(self): global _vm _vm = self self._ini = None self._command_handlers = {} self._object_info_tweakers = [] self._import_handlers = {} self._input_queue = queue.Queue() self._source_preprocessors = [] self._ast_postprocessors = [] self._main_dir = os.path.dirname(sys.modules["thonny"].__file__) self._heap = {} # WeakValueDictionary would be better, but can't store reference to None self._source_info_by_frame = {} site.sethelper() # otherwise help function is not available pydoc.pager = pydoc.plainpager # otherwise help command plays tricks self._install_fake_streams() self._current_executor = None self._io_level = 0 self._tty_mode = True self._tcl = None # clean up path sys.path = [d for d in sys.path if d != ""] # start in shell mode sys.argv[:] = [""] # empty "script name" sys.path.insert(0, "") # current dir # clean __main__ global scope for key in list(__main__.__dict__.keys()): if not key.startswith("__") or key in {"__file__", "__cached__"}: del __main__.__dict__[key] # unset __doc__, then exec dares to write doc of the script there __main__.__doc__ = None self._frontend_sys_path = ast.literal_eval(os.environ["THONNY_FRONTEND_SYS_PATH"]) self._load_shared_modules() self._load_plugins() self._install_signal_handler() def mainloop(self): try: while True: try: cmd = self._fetch_command() if isinstance(cmd, InputSubmission): self._input_queue.put(cmd) elif isinstance(cmd, EOFCommand): self.send_message(ToplevelResponse(SystemExit=True)) sys.exit() elif isinstance(cmd, ToplevelCommand): self._source_info_by_frame = {} self._input_queue = queue.Queue() self.handle_command(cmd) else: self.handle_command(cmd) except KeyboardInterrupt: logger.exception("Interrupt in mainloop") # Interrupt must always result in waiting_toplevel_command state # Don't show error messages, as the interrupted command may have been InlineCommand # (handlers of ToplevelCommands in normal cases catch the interrupt and provide # relevant message) self.send_message(ToplevelResponse()) except Exception: logger.exception("Crash in mainloop") traceback.print_exc() def add_command(self, command_name, handler): """Handler should be 1-argument function taking command object. Handler may return None (in this case no response is sent to frontend) or a BackendResponse """ self._command_handlers[command_name] = handler def add_object_info_tweaker(self, tweaker): """Tweaker should be 2-argument function taking value and export record""" self._object_info_tweakers.append(tweaker) def add_import_handler(self, module_name, handler): if module_name not in self._import_handlers: self._import_handlers[module_name] = [] self._import_handlers[module_name].append(handler) def add_source_preprocessor(self, func): self._source_preprocessors.append(func) def add_ast_postprocessor(self, func): self._ast_postprocessors.append(func) def get_main_module(self): return __main__ def handle_command(self, cmd): assert isinstance(cmd, (ToplevelCommand, InlineCommand)) def create_error_response(**kw): if isinstance(cmd, ToplevelCommand): return ToplevelResponse(command_name=cmd.name, **kw) else: return InlineResponse(command_name=cmd.name, **kw) if cmd.name in self._command_handlers: handler = self._command_handlers[cmd.name] else: handler = getattr(self, "_cmd_" + cmd.name, None) if handler is None: response = create_error_response(error="Unknown command: " + cmd.name) else: try: response = handler(cmd) except SystemExit: # Must be caused by Thonny or plugins code if isinstance(cmd, ToplevelCommand): traceback.print_exc() response = create_error_response(SystemExit=True) except UserError as e: sys.stderr.write(str(e) + "\n") response = create_error_response() except KeyboardInterrupt: response = create_error_response(user_exception=self._prepare_user_exception()) except Exception: _report_internal_error() response = create_error_response(context_info="other unhandled exception") if response is False: # Command doesn't want to send any response return if response is None and isinstance(cmd, ToplevelCommand): # create simple default response response = ToplevelResponse(command_name=cmd.name) # TODO: add these in response creation time in a helper function if isinstance(response, ToplevelResponse): response["gui_is_active"] = ( self._get_tcl() is not None or self._get_qt_app() is not None ) self.send_message(response) def get_option(self, name, default=None): section, subname = self._parse_option_name(name) val = self._get_ini().get(section, subname, fallback=default) try: return ast.literal_eval(val) except Exception: return val def set_option(self, name, value): ini = self._get_ini() section, subname = self._parse_option_name(name) if not ini.has_section(section): ini.add_section(section) if not isinstance(value, str): value = repr(value) ini.set(section, subname, value) self.save_settings() def switch_env_to_script_mode(self, cmd): if "" in sys.path: sys.path.remove("") # current directory filename = cmd.args[0] if os.path.isfile(filename): sys.path.insert(0, os.path.abspath(os.path.dirname(filename))) __main__.__dict__["__file__"] = filename def _parse_option_name(self, name): if "." in name: return name.split(".", 1) else: return "general", name def _get_ini(self): if self._ini is None: import configparser self._ini = configparser.ConfigParser(interpolation=None) self._ini.read(_CONFIG_FILENAME) return self._ini def save_settings(self): if self._ini is None: return with open(_CONFIG_FILENAME, "w") as fp: self._ini.write(fp) def _custom_import(self, *args, **kw): module = self._original_import(*args, **kw) if not hasattr(module, "__name__"): return module # module specific handlers for handler in self._import_handlers.get(module.__name__, []): try: handler(module) except Exception: _report_internal_error() # general handlers for handler in self._import_handlers.get("*", []): try: handler(module) except Exception: _report_internal_error() return module def _load_shared_modules(self): self.load_modules_with_frontend_path(["parso", "jedi", "thonnycontrib", "six", "asttokens"]) def load_modules_with_frontend_path(self, names): from importlib import import_module original_sys_path = sys.path try: # add fallback import directory in case backend doesn't have these modules sys.path = sys.path + self._frontend_sys_path # remove current script dir / current dir to reduce chance of shadowing # (example: asttokens import numbers. The user wouldn't meet this problem when running # with plain python) sys.path = sys.path[1:] for name in names: try: import_module(name) except ImportError: pass finally: sys.path = original_sys_path def _load_plugins(self): # built-in plugins import thonny.plugins.backend # pylint: disable=redefined-outer-name self._load_plugins_from_path(thonny.plugins.backend.__path__, "thonny.plugins.backend.") # 3rd party plugins from namespace package try: import thonnycontrib.backend # @UnresolvedImport except ImportError: # No 3rd party plugins installed pass else: self._load_plugins_from_path(thonnycontrib.backend.__path__, "thonnycontrib.backend.") def _load_plugins_from_path(self, path, prefix): load_function_name = "load_plugin" for _, module_name, _ in sorted(pkgutil.iter_modules(path, prefix), key=lambda x: x[1]): try: m = importlib.import_module(module_name) if hasattr(m, load_function_name): f = getattr(m, load_function_name) sig = inspect.signature(f) if len(sig.parameters) == 0: f() else: f(self) except Exception: logger.exception("Failed loading plugin '" + module_name + "'") def _install_signal_handler(self): def signal_handler(signal_, frame): raise KeyboardInterrupt("Execution interrupted") if os.name == "nt": signal.signal(signal.SIGBREAK, signal_handler) # @UndefinedVariable else: signal.signal(signal.SIGINT, signal_handler) def _cmd_get_environment_info(self, cmd): return ToplevelResponse( main_dir=self._main_dir, path=sys.path, usersitepackages=site.getusersitepackages() if site.ENABLE_USER_SITE else None, prefix=sys.prefix, welcome_text="Python " + _get_python_version_string(), executable=sys.executable, exe_dirs=get_exe_dirs(), in_venv=( hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix or hasattr(sys, "real_prefix") and getattr(sys, "real_prefix") != sys.prefix ), python_version=_get_python_version_string(), cwd=os.getcwd(), ) def _cmd_cd(self, cmd): if len(cmd.args) == 1: path = cmd.args[0] try: os.chdir(path) return ToplevelResponse() except FileNotFoundError: raise UserError("No such folder: " + path) except OSError as e: raise UserError("\n".join(traceback.format_exception_only(type(e), e))) else: raise UserError("cd takes one parameter") def _cmd_Run(self, cmd): self.switch_env_to_script_mode(cmd) return self._execute_file(cmd, SimpleRunner) def _cmd_run(self, cmd): return self._execute_file(cmd, SimpleRunner) def _cmd_FastDebug(self, cmd): self.switch_env_to_script_mode(cmd) return self._execute_file(cmd, FastTracer) def _cmd_Debug(self, cmd): self.switch_env_to_script_mode(cmd) return self._execute_file(cmd, NiceTracer) def _cmd_debug(self, cmd): return self._execute_file(cmd, NiceTracer) def _cmd_execute_source(self, cmd): """Executes Python source entered into shell""" self._check_update_tty_mode(cmd) filename = "" ws_stripped_source = cmd.source.strip() source = ws_stripped_source.strip("?") num_stripped_question_marks = len(ws_stripped_source) - len(source) # let's see if it's single expression or something more complex try: root = ast.parse(source, filename=filename, mode="exec") except SyntaxError as e: error = "".join(traceback.format_exception_only(type(e), e)) sys.stderr.write(error) return ToplevelResponse() assert isinstance(root, ast.Module) if len(root.body) == 1 and isinstance(root.body[0], ast.Expr): mode = "eval" elif len(root.body) > 1 and isinstance(root.body[-1], ast.Expr): mode = "exec+eval" else: mode = "exec" result_attributes = self._execute_source( source, filename, mode, NiceTracer if getattr(cmd, "debug_mode", False) else SimpleRunner, cmd, ) result_attributes["num_stripped_question_marks"] = num_stripped_question_marks return ToplevelResponse(command_name="execute_source", **result_attributes) def _cmd_execute_system_command(self, cmd): self._check_update_tty_mode(cmd) execute_system_command(cmd) def _cmd_process_gui_events(self, cmd): # advance the event loop try: # First try Tkinter. # Need to update even when tkinter._default_root is None # because otherwise destroyed window will stay up in macOS. # When switching between closed user Tk window and another window, # the closed window may reappear in IDLE and CLI REPL tcl = self._get_tcl() if tcl is not None and tcl.has_default_root or tcl.updates_without_root < 1: # http://bugs.python.org/issue989712 # http://bugs.python.org/file6090/run.py.diff # https://bugs.python.org/review/989712/diff/4528/Lib/idlelib/run.py tcl.eval("update") # if not tcl.has_default_root: # tcl.updates_without_root += 1 else: # Try Qt only when Tkinter is not used app = self._get_qt_app() if app is not None: app.processEvents() except Exception: pass return False def _cmd_get_globals(self, cmd): warnings.warn("_cmd_get_globals is deprecated for CPython") try: return InlineResponse( "get_globals", module_name=cmd.module_name, globals=self.export_globals(cmd.module_name), ) except Exception as e: return InlineResponse("get_globals", module_name=cmd.module_name, error=str(e)) def _cmd_get_frame_info(self, cmd): atts = {} try: # TODO: make it work also in past states frame, location = self._lookup_frame_by_id(cmd["frame_id"]) if frame is None: atts["error"] = "Frame not found" else: atts["code_name"] = frame.f_code.co_name atts["module_name"] = frame.f_globals["__name__"] atts["locals"] = ( None if frame.f_locals is frame.f_globals else self.export_variables(frame.f_locals) ) atts["globals"] = self.export_variables(frame.f_globals) atts["freevars"] = frame.f_code.co_freevars atts["location"] = location except Exception as e: atts["error"] = str(e) return InlineResponse("get_frame_info", frame_id=cmd.frame_id, **atts) def _cmd_get_active_distributions(self, cmd): try: # if it is called after first installation to user site packages # this dir is not yet in sys.path if ( site.ENABLE_USER_SITE and site.getusersitepackages() and os.path.exists(site.getusersitepackages()) and site.getusersitepackages() not in sys.path ): # insert before first site packages item for i, item in enumerate(sys.path): if "site-packages" in item or "dist-packages" in item: sys.path.insert(i, site.getusersitepackages()) break else: sys.path.append(site.getusersitepackages()) import pkg_resources pkg_resources._initialize_master_working_set() dists = { dist.key: { "project_name": dist.project_name, "key": dist.key, "location": dist.location, "version": dist.version, } for dist in pkg_resources.working_set } # pylint: disable=not-an-iterable return InlineResponse( "get_active_distributions", distributions=dists, usersitepackages=site.getusersitepackages() if site.ENABLE_USER_SITE else None, ) except Exception: return InlineResponse("get_active_distributions", error=traceback.format_exc()) def _cmd_get_locals(self, cmd): for frame in inspect.stack(): if id(frame) == cmd.frame_id: return InlineResponse("get_locals", locals=self.export_variables(frame.f_locals)) raise RuntimeError("Frame '{0}' not found".format(cmd.frame_id)) def _cmd_get_heap(self, cmd): result = {} for key in self._heap: result[key] = self.export_value(self._heap[key]) return InlineResponse("get_heap", heap=result) def _cmd_shell_autocomplete(self, cmd): error = None try: import jedi except ImportError: completions = [] error = "Could not import jedi" else: try: # with warnings.catch_warnings(): interpreter = jedi.Interpreter(cmd.source, [__main__.__dict__]) completions = self._export_completions(interpreter.completions()) except Exception as e: completions = [] error = "Autocomplete error: " + str(e) return InlineResponse( "shell_autocomplete", source=cmd.source, completions=completions, error=error ) def _cmd_editor_autocomplete(self, cmd): error = None try: import jedi self._debug(jedi.__file__, sys.path) with warnings.catch_warnings(): script = jedi.Script(cmd.source, cmd.row, cmd.column, cmd.filename) completions = self._export_completions(script.completions()) except ImportError: completions = [] error = "Could not import jedi" except Exception as e: completions = [] error = "Autocomplete error: " + str(e) return InlineResponse( "editor_autocomplete", source=cmd.source, row=cmd.row, column=cmd.column, filename=cmd.filename, completions=completions, error=error, ) def _cmd_Reset(self, cmd): if len(cmd.args) == 0: # nothing to do, because Reset always happens in fresh process return ToplevelResponse( command_name="Reset", welcome_text="Python " + _get_python_version_string(), executable=sys.executable, ) else: raise UserError("Command 'Reset' doesn't take arguments") def _export_completions(self, jedi_completions): result = [] for c in jedi_completions: if not c.name.startswith("__"): record = { "name": c.name, "complete": c.complete, "type": c.type, "description": c.description, } """ TODO: try: if c.type in ["class", "module", "function"]: if c.type == "function": record["docstring"] = c.docstring() else: record["docstring"] = c.description + "\n" + c.docstring() except Exception: pass """ result.append(record) return result def _cmd_get_object_info(self, cmd): if isinstance(self._current_executor, NiceTracer) and self._current_executor.is_in_past(): info = {"id": cmd.object_id, "error": "past info not available"} elif cmd.object_id in self._heap: value = self._heap[cmd.object_id] attributes = {} if cmd.include_attributes: for name in dir(value): if not name.startswith("__") or cmd.all_attributes: # attributes[name] = inspect.getattr_static(value, name) try: attributes[name] = getattr(value, name) except Exception: pass self._heap[id(type(value))] = type(value) info = { "id": cmd.object_id, "repr": repr(value), "type": str(type(value)), "full_type_name": str(type(value)) .replace("", "") .strip(), "type_id": id(type(value)), "attributes": self.export_variables(attributes), } if isinstance(value, io.TextIOWrapper): self._add_file_handler_info(value, info) elif isinstance( value, ( types.BuiltinFunctionType, types.BuiltinMethodType, types.FunctionType, types.LambdaType, types.MethodType, ), ): self._add_function_info(value, info) elif isinstance(value, (list, tuple, set)): self._add_elements_info(value, info) elif isinstance(value, dict): self._add_entries_info(value, info) elif hasattr(value, "image_data"): info["image_data"] = value.image_data for tweaker in self._object_info_tweakers: try: tweaker(value, info, cmd) except Exception: logger.exception("Failed object info tweaker: " + str(tweaker)) else: info = {"id": cmd.object_id, "error": "object info not available"} return InlineResponse("get_object_info", id=cmd.object_id, info=info) def _get_tcl(self): if self._tcl is not None: return self._tcl tkinter = sys.modules.get("tkinter") if tkinter is None: return None if self._tcl is None: try: self._tcl = tkinter.Tcl() self._tcl.updates_without_root = 0 except Exception: pass self._tcl.has_default_root = tkinter._default_root is not None return self._tcl def _get_qt_app(self): mod = sys.modules.get("PyQt5.QtCore") if mod is None: mod = sys.modules.get("PyQt4.QtCore") if mod is None: mod = sys.modules.get("PySide.QtCore") if mod is None: return None app_class = getattr(mod, "QCoreApplication", None) if app_class is not None: try: return app_class.instance() except Exception: return None else: return None def _add_file_handler_info(self, value, info): try: assert isinstance(value.name, str) assert value.mode in ("r", "rt", "tr", "br", "rb") assert value.errors in ("strict", None) assert value.newlines is None or value.tell() > 0 # TODO: cache the content # TODO: don't read too big files with open(value.name, encoding=value.encoding) as f: info["file_encoding"] = f.encoding info["file_content"] = f.read() info["file_tell"] = value.tell() except Exception as e: info["file_error"] = "Could not get file content, error:" + str(e) def _add_function_info(self, value, info): try: info["source"] = inspect.getsource(value) except Exception: pass def _add_elements_info(self, value, info): info["elements"] = [] for element in value: info["elements"].append(self.export_value(element)) def _add_entries_info(self, value, info): info["entries"] = [] for key in value: info["entries"].append((self.export_value(key), self.export_value(value[key]))) def _execute_file(self, cmd, executor_class): self._check_update_tty_mode(cmd) if len(cmd.args) >= 1: sys.argv = cmd.args filename = cmd.args[0] if os.path.isabs(filename): full_filename = filename else: full_filename = os.path.abspath(filename) with tokenize.open(full_filename) as fp: source = fp.read() for preproc in self._source_preprocessors: source = preproc(source, cmd) result_attributes = self._execute_source( source, full_filename, "exec", executor_class, cmd, self._ast_postprocessors ) result_attributes["filename"] = full_filename return ToplevelResponse(command_name=cmd.name, **result_attributes) else: raise UserError("Command '%s' takes at least one argument" % cmd.name) def _execute_source( self, source, filename, execution_mode, executor_class, cmd, ast_postprocessors=[] ): self._current_executor = executor_class(self, cmd) try: return self._current_executor.execute_source( source, filename, execution_mode, ast_postprocessors ) finally: self._current_executor = None def _install_fake_streams(self): self._original_stdin = sys.stdin self._original_stdout = sys.stdout self._original_stderr = sys.stderr # yes, both out and err will be directed to out (but with different tags) # this allows client to see the order of interleaving writes to stdout/stderr sys.stdin = VM.FakeInputStream(self, sys.stdin) sys.stdout = VM.FakeOutputStream(self, sys.stdout, "stdout") sys.stderr = VM.FakeOutputStream(self, sys.stdout, "stderr") # fake it properly: replace also "backup" streams sys.__stdin__ = sys.stdin sys.__stdout__ = sys.stdout sys.__stderr__ = sys.stderr def _install_custom_import(self): self._original_import = builtins.__import__ builtins.__import__ = self._custom_import def _restore_original_import(self): builtins.__import__ = self._original_import def _fetch_command(self): line = self._original_stdin.readline() if line == "": logger.info("Read stdin EOF") sys.exit() cmd = parse_message(line) return cmd def send_message(self, msg): if "cwd" not in msg: msg["cwd"] = os.getcwd() if isinstance(msg, ToplevelResponse) and "globals" not in msg: msg["globals"] = self.export_globals() self._original_stdout.write(serialize_message(msg) + "\n") self._original_stdout.flush() def export_value(self, value, max_repr_length=5000): self._heap[id(value)] = value try: rep = repr(value) except Exception: # See https://bitbucket.org/plas/thonny/issues/584/problem-with-thonnys-back-end-obj-no rep = "??? " if len(rep) > max_repr_length: rep = rep[:max_repr_length] + "…" return ValueInfo(id(value), rep) def export_variables(self, variables): result = {} with warnings.catch_warnings(): warnings.simplefilter("ignore") for name in variables: if not name.startswith("__"): result[name] = self.export_value(variables[name], 100) return result def export_globals(self, module_name="__main__"): if module_name in sys.modules: return self.export_variables(sys.modules[module_name].__dict__) else: raise RuntimeError("Module '{0}' is not loaded".format(module_name)) def _debug(self, *args): logger.debug("VM: " + str(args)) def _enter_io_function(self): self._io_level += 1 def _exit_io_function(self): self._io_level -= 1 def is_doing_io(self): return self._io_level > 0 def _export_stack(self, newest_frame, relevance_checker=None): result = [] system_frame = newest_frame while system_frame is not None: module_name = system_frame.f_globals["__name__"] code_name = system_frame.f_code.co_name if not relevance_checker or relevance_checker(system_frame): source, firstlineno, in_library = self._get_frame_source_info(system_frame) result.insert( 0, FrameInfo( # TODO: can this id be reused by a later frame? # Need to store the refernce to avoid GC? # I guess it is not required, as id will be required # only for stacktrace inspection, and sys.last_exception # will have the reference anyway # (NiceTracer has its own reference keeping) id=id(system_frame), filename=system_frame.f_code.co_filename, module_name=module_name, code_name=code_name, locals=self.export_variables(system_frame.f_locals), globals=self.export_variables(system_frame.f_globals), freevars=system_frame.f_code.co_freevars, source=source, lineno=system_frame.f_lineno, firstlineno=firstlineno, in_library=in_library, event="line", focus=TextRange(system_frame.f_lineno, 0, system_frame.f_lineno + 1, 0), node_tags=None, current_statement=None, current_evaluations=None, current_root_expression=None, ), ) if module_name == "__main__" and code_name == "": # this was last frame relevant to the user break system_frame = system_frame.f_back assert result # not empty return result def _lookup_frame_by_id(self, frame_id): def lookup_from_stack(frame): if frame is None: return None elif id(frame) == frame_id: return frame else: return lookup_from_stack(frame.f_back) def lookup_from_tb(entry): if entry is None: return None elif id(entry.tb_frame) == frame_id: return entry.tb_frame else: return lookup_from_tb(entry.tb_next) result = lookup_from_stack(inspect.currentframe()) if result is not None: return result, "stack" if getattr(sys, "last_traceback"): result = lookup_from_tb(getattr(sys, "last_traceback")) if result: return result, "last_traceback" _, _, tb = sys.exc_info() return lookup_from_tb(tb), "current_exception" def _get_frame_source_info(self, frame): fid = id(frame) if fid not in self._source_info_by_frame: self._source_info_by_frame[fid] = _fetch_frame_source_info(frame) return self._source_info_by_frame[fid] def _prepare_user_exception(self): e_type, e_value, e_traceback = sys.exc_info() sys.last_type, sys.last_value, sys.last_traceback = (e_type, e_value, e_traceback) processed_tb = traceback.extract_tb(e_traceback) tb = e_traceback while tb.tb_next is not None: tb = tb.tb_next last_frame = tb.tb_frame if e_type is SyntaxError: # Don't show ast frame while last_frame.f_code.co_filename and last_frame.f_code.co_filename == ast.__file__: last_frame = last_frame.f_back if e_type is SyntaxError: msg = ( traceback.format_exception_only(e_type, e_value)[-1] .replace(e_type.__name__ + ":", "") .strip() ) else: msg = str(e_value) fr_tr = None try: fr_tr = self._explain_exception_with_friendly_traceback() except ImportError: print( "[Could not import friendly_traceback. You can install it with Tools => Manage packages]\n", file=sys.stderr, ) except Exception as e: print("[Could not get friendly traceback. Problem: %s]\n" % e, file=sys.stderr) return { "type_name": e_type.__name__, "message": msg, "stack": self._export_stack(last_frame), "items": format_exception_with_frame_info(e_type, e_value, e_traceback), "filename": getattr(e_value, "filename", processed_tb[-1].filename), "lineno": getattr(e_value, "lineno", processed_tb[-1].lineno), "col_offset": getattr(e_value, "offset", None), "line": getattr(e_value, "text", processed_tb[-1].line), "friendly_traceback": fr_tr, } def _explain_exception_with_friendly_traceback(self): ft_level = os.environ.get("FRIENDLY_TRACEBACK_LEVEL", "") try: ft_level = int(ft_level) if ft_level == 0: return None except ValueError: return None import friendly_traceback friendly_traceback.set_level(ft_level) thonny_lang = os.environ.get("THONNY_LANGUAGE", "") if thonny_lang: friendly_traceback.set_lang(thonny_lang) friendly_traceback.exclude_file_from_traceback(__file__) friendly_traceback.explain(redirect="capture") return friendly_traceback.get_output() def _check_update_tty_mode(self, cmd): if "tty_mode" in cmd: self._tty_mode = cmd["tty_mode"] class FakeStream: def __init__(self, vm, target_stream): self._vm = vm self._target_stream = target_stream self._processed_symbol_count = 0 def isatty(self): return self._vm._tty_mode and (os.name != "nt" or "click" not in sys.modules) def __getattr__(self, name): # TODO: is it safe to perform those other functions without notifying vm # via _enter_io_function? return getattr(self._target_stream, name) class FakeOutputStream(FakeStream): def __init__(self, vm, target_stream, stream_name): VM.FakeStream.__init__(self, vm, target_stream) self._stream_name = stream_name def write(self, data): try: self._vm._enter_io_function() # click may send bytes instead of strings if isinstance(data, bytes): data = data.decode(errors="replace") if data != "": self._vm.send_message( BackendEvent("ProgramOutput", stream_name=self._stream_name, data=data) ) self._processed_symbol_count += len(data) finally: self._vm._exit_io_function() def writelines(self, lines): try: self._vm._enter_io_function() self.write("".join(lines)) finally: self._vm._exit_io_function() class FakeInputStream(FakeStream): def __init__(self, vm, target_stream): super().__init__(vm, target_stream) self._buffer = "" self._eof = False def _generic_read(self, method, original_limit): if original_limit is None: effective_limit = -1 elif method == "readlines" and original_limit > -1: # NB! size hint is defined in weird way # "no more lines will be read if the total size (in bytes/characters) # of all lines so far **exceeds** the hint". effective_limit = original_limit + 1 else: effective_limit = original_limit try: self._vm._enter_io_function() while True: if effective_limit == 0: result = "" break elif effective_limit > 0 and len(self._buffer) >= effective_limit: result = self._buffer[:effective_limit] self._buffer = self._buffer[effective_limit:] if ( method == "readlines" and not result.endswith("\n") and "\n" in self._buffer ): # limit is just a hint # https://docs.python.org/3/library/io.html#io.IOBase.readlines extra = self._buffer[: self._buffer.find("\n") + 1] result += extra self._buffer = self._buffer[len(extra) :] break elif method == "readline" and "\n" in self._buffer: pos = self._buffer.find("\n") + 1 result = self._buffer[:pos] self._buffer = self._buffer[pos:] break elif self._eof: result = self._buffer self._buffer = "" self._eof = False # That's how official implementation does break else: self._vm.send_message( BackendEvent("InputRequest", method=method, limit=original_limit) ) cmd = self._vm._fetch_command() if isinstance(cmd, InputSubmission): self._buffer += cmd.data self._processed_symbol_count += len(cmd.data) elif isinstance(cmd, EOFCommand): self._eof = True elif isinstance(cmd, InlineCommand): self._vm.handle_command(cmd) else: raise RuntimeError("Wrong type of command when waiting for input") return result finally: self._vm._exit_io_function() def read(self, limit=-1): return self._generic_read("read", limit) def readline(self, limit=-1): return self._generic_read("readline", limit) def readlines(self, limit=-1): return self._generic_read("readlines", limit).splitlines(True) def __next__(self): result = self.readline() if not result: raise StopIteration return result def __iter__(self): return self def prepare_hooks(method): @functools.wraps(method) def wrapper(self, *args, **kwargs): try: sys.meta_path.insert(0, self) self._vm._install_custom_import() return method(self, *args, **kwargs) finally: del sys.meta_path[0] if hasattr(self._vm, "_original_import"): self._vm._restore_original_import() return wrapper def return_execution_result(method): @functools.wraps(method) def wrapper(self, *args, **kwargs): try: result = method(self, *args, **kwargs) if result is not None: return result return {"context_info": "after normal execution"} except Exception: return {"user_exception": self._vm._prepare_user_exception()} return wrapper class Executor: def __init__(self, vm, original_cmd): self._vm = vm self._original_cmd = original_cmd self._main_module_path = None def execute_source(self, source, filename, mode, ast_postprocessors): if isinstance(source, str): # TODO: simplify this or make sure encoding is correct source = source.encode("utf-8") if os.path.exists(filename): self._main_module_path = filename global_vars = __main__.__dict__ statements = expression = None try: if mode == "exec+eval": assert not ast_postprocessors # Useful in shell to get last expression value in multi-statement block root = self._prepare_ast(source, filename, "exec") statements = compile(ast.Module(body=root.body[:-1]), filename, "exec") expression = compile(ast.Expression(root.body[-1].value), filename, "eval") else: root = self._prepare_ast(source, filename, mode) if mode == "eval": assert not ast_postprocessors expression = compile(root, filename, mode) elif mode == "exec": for func in ast_postprocessors: func(root) statements = compile(root, filename, mode) else: raise ValueError("Unknown mode") return self._execute_prepared_user_code(statements, expression, global_vars) except SyntaxError: return {"user_exception": self._vm._prepare_user_exception()} except SystemExit: return {"SystemExit": True} except Exception: _report_internal_error() return {} @return_execution_result @prepare_hooks def _execute_prepared_user_code(self, statements, expression, global_vars): if statements: exec(statements, global_vars) if expression: value = eval(expression, global_vars) if value is not None: builtins._ = value return {"value_info": self._vm.export_value(value)} def find_spec(self, fullname, path=None, target=None): """override in subclass for custom-loading user modules""" return None def _prepare_ast(self, source, filename, mode): return ast.parse(source, filename, mode) class SimpleRunner(Executor): pass class Tracer(Executor): def __init__(self, vm, original_cmd): super().__init__(vm, original_cmd) self._thonny_src_dir = os.path.dirname(sys.modules["thonny"].__file__) self._fresh_exception = None self._prev_breakpoints = {} self._last_reported_frame_ids = set() self._canonic_path_cache = {} self._file_interest_cache = {} self._file_breakpoints_cache = {} self._command_completion_handler = None # first (automatic) stepping command depends on whether any breakpoints were set or not breakpoints = self._original_cmd.breakpoints assert isinstance(breakpoints, dict) if breakpoints: command_name = "resume" else: command_name = "step_into" self._current_command = DebuggerCommand( command_name, state=None, focus=None, frame_id=None, exception=None, breakpoints=breakpoints, ) self._initialize_new_command(None) def _get_canonic_path(self, path): # adapted from bdb result = self._canonic_path_cache.get(path) if result is None: if path.startswith("<"): result = path else: result = os.path.normcase(os.path.abspath(path)) self._canonic_path_cache[path] = result return result def _trace(self, frame, event, arg): raise NotImplementedError() def _execute_prepared_user_code(self, statements, expression, global_vars): try: sys.settrace(self._trace) if hasattr(sys, "breakpointhook"): old_breakpointhook = sys.breakpointhook sys.breakpointhook = self._breakpointhook return super()._execute_prepared_user_code(statements, expression, global_vars) finally: sys.settrace(None) if hasattr(sys, "breakpointhook"): sys.breakpointhook = old_breakpointhook def _is_interesting_frame(self, frame): code = frame.f_code return not ( code is None or code.co_filename is None or not self._is_interesting_module_file(code.co_filename) or code.co_flags & _CO_GENERATOR and code.co_flags & _CO_COROUTINE and code.co_flags & _CO_ITERABLE_COROUTINE and code.co_flags & _CO_ASYNC_GENERATOR # or "importlib._bootstrap" in code.co_filename or code.co_name in ["", "", ""] ) def _is_interesting_module_file(self, path): # interesting files are the files in the same directory as main module # or the ones with breakpoints # When command is "resume", then only modules with breakpoints are interesting # (used to be more flexible, but this caused problems # when main script was in ~/. Then user site library became interesting as well) result = self._file_interest_cache.get(path, None) if result is not None: return result _, extension = os.path.splitext(path.lower()) result = ( self._get_breakpoints_in_file(path) or self._main_module_path is not None and is_same_path(path, self._main_module_path) or extension in (".py", ".pyw") and ( self._current_command.get("allow_stepping_into_libraries", False) or ( path_startswith(path, os.path.dirname(self._main_module_path)) # main module may be at the root of the fs and not path_startswith(path, sys.prefix) and not path_startswith(path, sys.base_prefix) and not path_startswith(path, site.getusersitepackages() or "usersitenotexists") ) ) and not path_startswith(path, self._thonny_src_dir) ) self._file_interest_cache[path] = result return result def _is_interesting_exception(self, frame, arg): return arg[0] not in (StopIteration, StopAsyncIteration) def _fetch_next_debugger_command(self, current_frame): while True: cmd = self._vm._fetch_command() if isinstance(cmd, InlineCommand): self._vm.handle_command(cmd) else: assert isinstance(cmd, DebuggerCommand) self._prev_breakpoints = self._current_command.breakpoints self._current_command = cmd self._initialize_new_command(current_frame) return def _initialize_new_command(self, current_frame): self._command_completion_handler = getattr( self, "_cmd_%s_completed" % self._current_command.name ) if self._current_command.breakpoints != self._prev_breakpoints: self._file_interest_cache = {} # because there may be new breakpoints self._file_breakpoints_cache = {} for path, linenos in self._current_command.breakpoints.items(): self._file_breakpoints_cache[path] = linenos self._file_breakpoints_cache[self._get_canonic_path(path)] = linenos def _register_affected_frame(self, exception_obj, frame): if not hasattr(exception_obj, "_affected_frame_ids_"): exception_obj._affected_frame_ids_ = set() exception_obj._affected_frame_ids_.add(id(frame)) def _get_breakpoints_in_file(self, filename): result = self._file_breakpoints_cache.get(filename, None) if result is not None: return result canonic_path = self._get_canonic_path(filename) result = self._file_breakpoints_cache.get(canonic_path, set()) self._file_breakpoints_cache[filename] = result return result def _get_current_exception(self): if self._fresh_exception is not None: return self._fresh_exception else: return sys.exc_info() def _export_exception_info(self): exc = self._get_current_exception() if exc[0] is None: return { "id": None, "msg": None, "type_name": None, "lines_with_frame_info": None, "affected_frame_ids": set(), "is_fresh": False, } else: return { "id": id(exc[1]), "msg": str(exc[1]), "type_name": exc[0].__name__, "lines_with_frame_info": format_exception_with_frame_info(*exc), "affected_frame_ids": exc[1]._affected_frame_ids_, "is_fresh": exc == self._fresh_exception, } def _breakpointhook(self, *args, **kw): pass def _check_notify_return(self, frame_id): if frame_id in self._last_reported_frame_ids: # Need extra notification, because it may be long time until next interesting event self._vm.send_message(InlineResponse("debugger_return", frame_id=frame_id)) def _check_store_main_frame_id(self, frame): # initial command doesn't have a frame id if self._current_command.frame_id is None and self._get_canonic_path( frame.f_code.co_filename ) == self._get_canonic_path(self._main_module_path): self._current_command.frame_id = id(frame) class FastTracer(Tracer): def __init__(self, vm, original_cmd): super().__init__(vm, original_cmd) self._command_frame_returned = False self._code_linenos_cache = {} self._code_breakpoints_cache = {} def _initialize_new_command(self, current_frame): super()._initialize_new_command(current_frame) self._command_frame_returned = False if self._current_command.breakpoints != self._prev_breakpoints: self._code_breakpoints_cache = {} # restore tracing for active frames which were skipped before # but have breakpoints now frame = current_frame while frame is not None: if ( frame.f_trace is None and frame.f_code is not None and self._get_breakpoints_in_code(frame.f_code) ): frame.f_trace = self._trace frame = frame.f_back def _breakpointhook(self, *args, **kw): frame = inspect.currentframe() while not self._is_interesting_frame(frame): frame = frame.f_back self._report_current_state(frame) self._fetch_next_debugger_command(frame) def _should_skip_frame(self, frame, event): if event == "call": # new frames return ( ( self._current_command.name == "resume" and not self._get_breakpoints_in_code(frame.f_code) or self._current_command.name == "step_over" and not self._get_breakpoints_in_code(frame.f_code) and id(frame) not in self._last_reported_frame_ids or self._current_command.name == "step_out" and not self._get_breakpoints_in_code(frame.f_code) ) or not self._is_interesting_frame(frame) or self._vm.is_doing_io() ) else: # once we have entered a frame, we need to reach the return event return False def _trace(self, frame, event, arg): if self._should_skip_frame(frame, event): return None # return None # return self._trace frame_id = id(frame) if event == "call": self._check_store_main_frame_id(frame) self._fresh_exception = None # can we skip this frame? if self._current_command.name == "step_over" and not self._current_command.breakpoints: return None elif event == "return": self._fresh_exception = None if frame_id == self._current_command["frame_id"]: self._command_frame_returned = True self._check_notify_return(frame_id) elif event == "exception": if self._is_interesting_exception(frame, arg): self._fresh_exception = arg self._register_affected_frame(arg[1], frame) # UI doesn't know about separate exception events self._report_current_state(frame) self._fetch_next_debugger_command(frame) elif event == "line": self._fresh_exception = None if self._command_completion_handler(frame): self._report_current_state(frame) self._fetch_next_debugger_command(frame) else: self._fresh_exception = None return self._trace def _report_current_state(self, frame): stack = self._vm._export_stack(frame, self._is_interesting_frame) msg = DebuggerResponse( stack=stack, in_present=True, io_symbol_count=None, exception_info=self._export_exception_info(), tracer_class="FastTracer", ) self._last_reported_frame_ids = set(map(lambda f: f.id, stack)) self._vm.send_message(msg) def _cmd_step_into_completed(self, frame): return True def _cmd_step_over_completed(self, frame): return ( id(frame) == self._current_command.frame_id or self._command_frame_returned or self._at_a_breakpoint(frame) ) def _cmd_step_out_completed(self, frame): return self._command_frame_returned or self._at_a_breakpoint(frame) def _cmd_resume_completed(self, frame): return self._at_a_breakpoint(frame) def _get_breakpoints_in_code(self, f_code): bps_in_file = self._get_breakpoints_in_file(f_code.co_filename) code_id = id(f_code) result = self._code_breakpoints_cache.get(code_id, None) if result is None: if not bps_in_file: result = set() else: co_linenos = self._code_linenos_cache.get(code_id, None) if co_linenos is None: co_linenos = {pair[1] for pair in dis.findlinestarts(f_code)} self._code_linenos_cache[code_id] = co_linenos result = bps_in_file.intersection(co_linenos) self._code_breakpoints_cache[code_id] = result return result def _at_a_breakpoint(self, frame): # TODO: try re-entering same line in loop return frame.f_lineno in self._get_breakpoints_in_code(frame.f_code) def _is_interesting_exception(self, frame, arg): return super()._is_interesting_exception(frame, arg) and ( self._current_command.name in ["step_into", "step_over"] and ( # in command frame or its parent frames id(frame) == self._current_command["frame_id"] or self._command_frame_returned ) ) class NiceTracer(Tracer): def __init__(self, vm, original_cmd): super().__init__(vm, original_cmd) self._instrumented_files = set() self._install_marker_functions() self._custom_stack = [] self._saved_states = [] self._current_state_index = 0 from collections import Counter self._fulltags = Counter() self._nodes = {} def _breakpointhook(self, *args, **kw): self._report_state(len(self._saved_states) - 1) self._fetch_next_debugger_command(None) def _install_marker_functions(self): # Make dummy marker functions universally available by putting them # into builtin scope self.marker_function_names = { BEFORE_STATEMENT_MARKER, AFTER_STATEMENT_MARKER, BEFORE_EXPRESSION_MARKER, AFTER_EXPRESSION_MARKER, } for name in self.marker_function_names: if not hasattr(builtins, name): setattr(builtins, name, getattr(self, name)) def _prepare_ast(self, source, filename, mode): # ast_utils need to be imported after asttokens # is (custom-)imported from thonny import ast_utils root = ast.parse(source, filename, mode) ast_utils.mark_text_ranges(root, source) self._tag_nodes(root) self._insert_expression_markers(root) self._insert_statement_markers(root) self._insert_for_target_markers(root) self._instrumented_files.add(filename) return root def _should_skip_frame(self, frame, event): # nice tracer can't skip any of the frames which need to be # shown in the stacktrace code = frame.f_code if code is None: return True if event == "call": # new frames if code.co_name in self.marker_function_names: return False else: return not self._is_interesting_frame(frame) or self._vm.is_doing_io() else: # once we have entered a frame, we need to reach the return event return False def _is_interesting_frame(self, frame): return frame.f_code.co_filename in self._instrumented_files and super()._is_interesting_frame( frame ) def find_spec(self, fullname, path=None, target=None): spec = PathFinder.find_spec(fullname, path, target) if ( spec is not None and isinstance(spec.loader, SourceFileLoader) and getattr(spec, "origin", None) and self._is_interesting_module_file(spec.origin) ): spec.loader = FancySourceFileLoader(fullname, spec.origin, self) return spec else: return super().find_spec(fullname, path, target) def is_in_past(self): return self._current_state_index < len(self._saved_states) - 1 def _trace(self, frame, event, arg): try: return self._trace_and_catch(frame, event, arg) except BaseException: traceback.print_exc() sys.settrace(None) return None def _trace_and_catch(self, frame, event, arg): """ 1) Detects marker calls and responds to client queries in these spots 2) Maintains a customized view of stack """ # frame skipping test should be done both in new frames and old ones (because of Resume) # Note that intermediate frames can't be skipped when jumping to a breakpoint # because of the need to maintain custom stack if self._should_skip_frame(frame, event): return None code_name = frame.f_code.co_name if event == "call": self._fresh_exception = ( None # some code is running, therefore exception is not fresh anymore ) if code_name in self.marker_function_names: self._check_store_main_frame_id(frame.f_back) # the main thing if code_name == BEFORE_STATEMENT_MARKER: event = "before_statement" elif code_name == AFTER_STATEMENT_MARKER: event = "after_statement" elif code_name == BEFORE_EXPRESSION_MARKER: event = "before_expression" elif code_name == AFTER_EXPRESSION_MARKER: event = "after_expression" else: raise AssertionError("Unknown marker function") marker_function_args = frame.f_locals.copy() node = self._nodes[marker_function_args["node_id"]] del marker_function_args["self"] if "call_function" not in node.tags: self._handle_progress_event(frame.f_back, event, marker_function_args, node) self._try_interpret_as_again_event(frame.f_back, event, marker_function_args, node) # Don't need any more events from these frames return None else: # Calls to proper functions. # Client doesn't care about these events, # it cares about "before_statement" events in the first statement of the body self._custom_stack.append(CustomStackFrame(frame, "call")) elif event == "exception": # Note that Nicer can't filter out exception based on current command # because it must be possible to go back and replay with different command if self._is_interesting_exception(frame, arg): self._fresh_exception = arg self._register_affected_frame(arg[1], frame) # Last command (step_into or step_over) produced this exception # Show red after-state for this focus # use the state prepared by previous event last_custom_frame = self._custom_stack[-1] assert last_custom_frame.system_frame == frame # TODO: instead of producing an event here, next before_-event # should create matching after event for each before event # which would remain unclosed because of this exception. # Existence of these after events would simplify step_over management assert last_custom_frame.event.startswith("before_") pseudo_event = last_custom_frame.event.replace("before_", "after_").replace( "_again", "" ) # print("handle", pseudo_event, {}, last_custom_frame.node) self._handle_progress_event(frame, pseudo_event, {}, last_custom_frame.node) elif event == "return": self._fresh_exception = None if code_name not in self.marker_function_names: frame_id = id(self._custom_stack[-1].system_frame) self._check_notify_return(frame_id) self._custom_stack.pop() if len(self._custom_stack) == 0: # We popped last frame, this means our program has ended. # There may be more events coming from upper (system) frames # but we're not interested in those sys.settrace(None) else: pass else: self._fresh_exception = None return self._trace def _handle_progress_event(self, frame, event, args, node): self._save_current_state(frame, event, args, node) self._respond_to_commands() def _save_current_state(self, frame, event, args, node): """ Updates custom stack and stores the state self._custom_stack always keeps last info, which gets exported as FrameInfos to _saved_states["stack"] """ focus = TextRange(node.lineno, node.col_offset, node.end_lineno, node.end_col_offset) custom_frame = self._custom_stack[-1] custom_frame.event = event custom_frame.focus = focus custom_frame.node = node custom_frame.node_tags = node.tags if self._saved_states: prev_state = self._saved_states[-1] prev_state_frame = self._create_actual_active_frame(prev_state) else: prev_state = None prev_state_frame = None # store information about current statement / expression if "statement" in event: custom_frame.current_statement = focus if event == "before_statement_again": # keep the expression information from last event pass else: custom_frame.current_root_expression = None custom_frame.current_evaluations = [] else: assert "expression" in event assert prev_state_frame is not None # see whether current_root_expression needs to be updated prev_root_expression = prev_state_frame.current_root_expression if event == "before_expression" and ( id(frame) != id(prev_state_frame.system_frame) or "statement" in prev_state_frame.event or not range_contains_smaller_or_equal(prev_root_expression, focus) ): custom_frame.current_root_expression = focus custom_frame.current_evaluations = [] if event == "after_expression" and "value" in args: # value is missing in case of exception custom_frame.current_evaluations.append( (focus, self._vm.export_value(args["value"])) ) # Save the snapshot. # Check if we can share something with previous state if ( prev_state is not None and id(prev_state_frame.system_frame) == id(frame) and prev_state["exception_value"] is self._get_current_exception()[1] and prev_state["fresh_exception_id"] == id(self._fresh_exception) and ("before" in event or "skipexport" in node.tags) ): exception_info = prev_state["exception_info"] # share the stack ... stack = prev_state["stack"] # ... but override certain things active_frame_overrides = { "event": custom_frame.event, "focus": custom_frame.focus, "node_tags": custom_frame.node_tags, "current_root_expression": custom_frame.current_root_expression, "current_evaluations": custom_frame.current_evaluations.copy(), "current_statement": custom_frame.current_statement, } else: # make full export stack = self._export_stack() exception_info = self._export_exception_info() active_frame_overrides = {} msg = { "stack": stack, "active_frame_overrides": active_frame_overrides, "in_client_log": False, "io_symbol_count": ( sys.stdin._processed_symbol_count + sys.stdout._processed_symbol_count + sys.stderr._processed_symbol_count ), "exception_value": self._get_current_exception()[1], "fresh_exception_id": id(self._fresh_exception), "exception_info": exception_info, } self._saved_states.append(msg) def _respond_to_commands(self): """Tries to respond to client commands with states collected so far. Returns if these states don't suffice anymore and Python needs to advance the program""" # while the state for current index is already saved: while self._current_state_index < len(self._saved_states): state = self._saved_states[self._current_state_index] # Get current state's most recent frame (together with overrides frame = self._create_actual_active_frame(state) # Is this state meant to be seen? if "skip_" + frame.event not in frame.node_tags: # if True: # Has the command completed? tester = getattr(self, "_cmd_" + self._current_command.name + "_completed") cmd_complete = tester(frame, self._current_command) if cmd_complete: state["in_client_log"] = True self._report_state(self._current_state_index) self._fetch_next_debugger_command(frame) if self._current_command.name == "step_back": if self._current_state_index == 0: # Already in first state. Remain in this loop pass else: assert self._current_state_index > 0 # Current event is no longer present in GUI "undo log" self._saved_states[self._current_state_index]["in_client_log"] = False self._current_state_index -= 1 else: # Other commands move the pointer forward self._current_state_index += 1 def _create_actual_active_frame(self, state): return state["stack"][-1]._replace(**state["active_frame_overrides"]) def _report_state(self, state_index): in_present = state_index == len(self._saved_states) - 1 if in_present: # For reported new events re-export stack to make sure it is not shared. # (There is tiny chance that sharing previous state # after executing BinOp, Attribute, Compare or Subscript # was not the right choice. See tag_nodes for more.) # Re-exporting reduces the harm by showing correct data at least # for present states. self._saved_states[state_index]["stack"] = self._export_stack() # need to make a copy for applying overrides # and removing helper fields without modifying original state = self._saved_states[state_index].copy() state["stack"] = state["stack"].copy() state["in_present"] = in_present if not in_present: # for past states fix the newest frame state["stack"][-1] = self._create_actual_active_frame(state) del state["exception_value"] del state["active_frame_overrides"] # Convert stack of TempFrameInfos to stack of FrameInfos new_stack = [] self._last_reported_frame_ids = set() for tframe in state["stack"]: system_frame = tframe.system_frame module_name = system_frame.f_globals["__name__"] code_name = system_frame.f_code.co_name source, firstlineno, in_library = self._vm._get_frame_source_info(system_frame) assert firstlineno is not None, "nofir " + str(system_frame) frame_id = id(system_frame) new_stack.append( FrameInfo( id=frame_id, filename=system_frame.f_code.co_filename, module_name=module_name, code_name=code_name, locals=tframe.locals, globals=tframe.globals, freevars=system_frame.f_code.co_freevars, source=source, lineno=system_frame.f_lineno, firstlineno=firstlineno, in_library=in_library, event=tframe.event, focus=tframe.focus, node_tags=tframe.node_tags, current_statement=tframe.current_statement, current_evaluations=tframe.current_evaluations, current_root_expression=tframe.current_root_expression, ) ) self._last_reported_frame_ids.add(frame_id) state["stack"] = new_stack state["tracer_class"] = "NiceTracer" self._vm.send_message(DebuggerResponse(**state)) def _try_interpret_as_again_event(self, frame, original_event, original_args, original_node): """ Some after_* events can be interpreted also as "before_*_again" events (eg. when last argument of a call was evaluated, then we are just before executing the final stage of the call) """ if original_event == "after_expression": value = original_args.get("value") if ( "last_child" in original_node.tags or "or_arg" in original_node.tags and value or "and_arg" in original_node.tags and not value ): # there may be explicit exceptions if ( "skip_after_statement_again" in original_node.parent_node.tags or "skip_after_expression_again" in original_node.parent_node.tags ): return # next step will be finalizing evaluation of parent of current expr # so let's say we're before that parent expression again_args = {"node_id": id(original_node.parent_node)} again_event = ( "before_expression_again" if "child_of_expression" in original_node.tags else "before_statement_again" ) self._handle_progress_event( frame, again_event, again_args, original_node.parent_node ) def _cmd_step_over_completed(self, frame, cmd): """ Identifies the moment when piece of code indicated by cmd.frame_id and cmd.focus has completed execution (either successfully or not). """ if self._at_a_breakpoint(frame, cmd): return True # Make sure the correct frame_id is selected if id(frame.system_frame) == cmd.frame_id: # We're in the same frame if "before_" in cmd.state: if not range_contains_smaller_or_equal(cmd.focus, frame.focus): # Focus has changed, command has completed return True else: # Keep running return False elif "after_" in cmd.state: if ( frame.focus != cmd.focus or "before_" in frame.event or "_expression" in cmd.state and "_statement" in frame.event or "_statement" in cmd.state and "_expression" in frame.event ): # The state has changed, command has completed return True else: # Keep running return False else: # We're in another frame if self._frame_is_alive(cmd.frame_id): # We're in a successor frame, keep running return False else: # Original frame has completed, assumedly because of an exception # We're done return True return True # not actually required, just to make Pylint happy def _cmd_step_into_completed(self, frame, cmd): return frame.event != "after_statement" def _cmd_step_back_completed(self, frame, cmd): # Check if the selected message has been previously sent to front-end return ( self._saved_states[self._current_state_index]["in_client_log"] or self._current_state_index == 0 ) def _cmd_step_out_completed(self, frame, cmd): if self._current_state_index == 0: return False if frame.event == "after_statement": return False if self._at_a_breakpoint(frame, cmd): return True prev_state_frame = self._saved_states[self._current_state_index - 1]["stack"][-1] return ( # the frame has completed not self._frame_is_alive(cmd.frame_id) # we're in the same frame but on higher level # TODO: expression inside statement expression has same range as its parent or id(frame.system_frame) == cmd.frame_id and range_contains_smaller(frame.focus, cmd.focus) # or we were there in prev state or id(prev_state_frame.system_frame) == cmd.frame_id and range_contains_smaller(prev_state_frame.focus, cmd.focus) ) def _cmd_resume_completed(self, frame, cmd): return self._at_a_breakpoint(frame, cmd) def _at_a_breakpoint(self, frame, cmd, breakpoints=None): if breakpoints is None: breakpoints = cmd["breakpoints"] return ( frame.event in ["before_statement", "before_expression"] and frame.system_frame.f_code.co_filename in breakpoints and frame.focus.lineno in breakpoints[frame.system_frame.f_code.co_filename] # consider only first event on a line # (but take into account that same line may be reentered) and ( cmd.focus is None or (cmd.focus.lineno != frame.focus.lineno) or (cmd.focus == frame.focus and cmd.state == frame.event) or id(frame.system_frame) != cmd.frame_id ) ) def _frame_is_alive(self, frame_id): for frame in self._custom_stack: if id(frame.system_frame) == frame_id: return True return False def _export_stack(self): result = [] exported_globals_per_module = {} def export_globals(module_name, frame): if module_name not in exported_globals_per_module: exported_globals_per_module[module_name] = self._vm.export_variables( frame.f_globals ) return exported_globals_per_module[module_name] for custom_frame in self._custom_stack: system_frame = custom_frame.system_frame module_name = system_frame.f_globals["__name__"] result.append( TempFrameInfo( # need to store the reference to the frame to avoid it being GC-d # otherwise frame id-s would be reused and this would # mess up communication with the frontend. system_frame=system_frame, locals=None if system_frame.f_locals is system_frame.f_globals else self._vm.export_variables(system_frame.f_locals), globals=export_globals(module_name, system_frame), event=custom_frame.event, focus=custom_frame.focus, node_tags=custom_frame.node_tags, current_evaluations=custom_frame.current_evaluations.copy(), current_statement=custom_frame.current_statement, current_root_expression=custom_frame.current_root_expression, ) ) assert result # not empty return result def _thonny_hidden_before_stmt(self, node_id): # The code to be debugged will be instrumented with this function # inserted before each statement. # Entry into this function indicates that statement as given # by the code range is about to be evaluated next. return None def _thonny_hidden_after_stmt(self, node_id): # The code to be debugged will be instrumented with this function # inserted after each statement. # Entry into this function indicates that statement as given # by the code range was just executed successfully. return None def _thonny_hidden_before_expr(self, node_id): # Entry into this function indicates that expression as given # by the code range is about to be evaluated next return node_id def _thonny_hidden_after_expr(self, node_id, value): # The code to be debugged will be instrumented with this function # wrapped around each expression (given as 2nd argument). # Entry into this function indicates that expression as given # by the code range was just evaluated to given value return value def _tag_nodes(self, root): """Marks interesting properties of AST nodes""" # ast_utils need to be imported after asttokens # is (custom-)imported from thonny import ast_utils def add_tag(node, tag): if not hasattr(node, "tags"): node.tags = set() node.tags.add("class=" + node.__class__.__name__) node.tags.add(tag) # ignore module docstring if it is before from __future__ import if ( isinstance(root.body[0], ast.Expr) and isinstance(root.body[0].value, ast.Str) and len(root.body) > 1 and isinstance(root.body[1], ast.ImportFrom) and root.body[1].module == "__future__" ): add_tag(root.body[0], "ignore") add_tag(root.body[0].value, "ignore") add_tag(root.body[1], "ignore") for node in ast.walk(root): if not isinstance(node, (ast.expr, ast.stmt)): if isinstance(node, ast.comprehension): for expr in node.ifs: add_tag(expr, "comprehension.if") continue # tag last children last_child = ast_utils.get_last_child(node) assert last_child in [True, False, None] or isinstance( last_child, (ast.expr, ast.stmt, type(None)) ), ("Bad last child " + str(last_child) + " of " + str(node)) if last_child is not None: add_tag(node, "has_children") if isinstance(last_child, ast.AST): last_child.parent_node = node add_tag(last_child, "last_child") if isinstance(node, _ast.expr): add_tag(last_child, "child_of_expression") else: add_tag(last_child, "child_of_statement") if isinstance(node, ast.Call): add_tag(last_child, "last_call_arg") # other cases if isinstance(node, ast.Call): add_tag(node.func, "call_function") node.func.parent_node = node if isinstance(node, ast.BoolOp) and node.op == ast.Or(): for child in node.values: add_tag(child, "or_arg") child.parent_node = node if isinstance(node, ast.BoolOp) and node.op == ast.And(): for child in node.values: add_tag(child, "and_arg") child.parent_node = node # TODO: assert (it doesn't evaluate msg when test == True) if isinstance(node, ast.Str): add_tag(node, "skipexport") if hasattr(ast, "JoinedStr") and isinstance(node, ast.JoinedStr): # can't present children normally without # ast giving correct locations for them # https://bugs.python.org/issue29051 add_tag(node, "ignore_children") elif isinstance(node, ast.Num): add_tag(node, "skipexport") elif isinstance(node, ast.List): add_tag(node, "skipexport") elif isinstance(node, ast.Tuple): add_tag(node, "skipexport") elif isinstance(node, ast.Set): add_tag(node, "skipexport") elif isinstance(node, ast.Dict): add_tag(node, "skipexport") elif isinstance(node, ast.Name): add_tag(node, "skipexport") elif isinstance(node, ast.NameConstant): add_tag(node, "skipexport") elif hasattr(ast, "Constant") and isinstance(node, ast.Constant): add_tag(node, "skipexport") elif isinstance(node, ast.Expr): if not isinstance(node.value, (ast.Yield, ast.YieldFrom)): add_tag(node, "skipexport") elif isinstance(node, ast.If): add_tag(node, "skipexport") elif isinstance(node, ast.Return): add_tag(node, "skipexport") elif isinstance(node, ast.While): add_tag(node, "skipexport") elif isinstance(node, ast.Continue): add_tag(node, "skipexport") elif isinstance(node, ast.Break): add_tag(node, "skipexport") elif isinstance(node, ast.Pass): add_tag(node, "skipexport") elif isinstance(node, ast.For): add_tag(node, "skipexport") elif isinstance(node, ast.Try): add_tag(node, "skipexport") elif isinstance(node, ast.ListComp): add_tag(node.elt, "ListComp.elt") if len(node.generators) > 1: add_tag(node, "ignore_children") elif isinstance(node, ast.SetComp): add_tag(node.elt, "SetComp.elt") if len(node.generators) > 1: add_tag(node, "ignore_children") elif isinstance(node, ast.DictComp): add_tag(node.key, "DictComp.key") add_tag(node.value, "DictComp.value") if len(node.generators) > 1: add_tag(node, "ignore_children") elif isinstance(node, ast.BinOp): # TODO: use static analysis to detect type of left child add_tag(node, "skipexport") elif isinstance(node, ast.Attribute): # TODO: use static analysis to detect type of left child add_tag(node, "skipexport") elif isinstance(node, ast.Subscript): # TODO: use static analysis to detect type of left child add_tag(node, "skipexport") elif isinstance(node, ast.Compare): # TODO: use static analysis to detect type of left child add_tag(node, "skipexport") if isinstance(node, (ast.Assign)): # value will be presented in assignment's before_statement_again add_tag(node.value, "skip_after_expression") if isinstance(node, (ast.Expr, ast.While, ast.For, ast.If, ast.Try, ast.With)): add_tag(node, "skip_after_statement_again") # make sure every node has this field if not hasattr(node, "tags"): node.tags = set() def _should_instrument_as_expression(self, node): return ( isinstance(node, _ast.expr) and hasattr(node, "end_lineno") and hasattr(node, "end_col_offset") and not getattr(node, "incorrect_range", False) and "ignore" not in node.tags and (not hasattr(node, "ctx") or isinstance(node.ctx, ast.Load)) # TODO: repeatedly evaluated subexpressions of comprehensions # can be supported (but it requires some redesign both in backend and GUI) and "ListComp.elt" not in node.tags and "SetComp.elt" not in node.tags and "DictComp.key" not in node.tags and "DictComp.value" not in node.tags and "comprehension.if" not in node.tags ) def _should_instrument_as_statement(self, node): return ( isinstance(node, _ast.stmt) and not getattr(node, "incorrect_range", False) and "ignore" not in node.tags # Shouldn't insert anything before from __future__ import # as this is not a normal statement # https://bitbucket.org/plas/thonny/issues/183/thonny-throws-false-positive-syntaxerror and (not isinstance(node, ast.ImportFrom) or node.module != "__future__") ) def _insert_statement_markers(self, root): # find lists of statements and insert before/after markers for each statement for name, value in ast.iter_fields(root): if isinstance(root, ast.Try) and name == "handlers": # contains statements but is not statement itself for handler in value: self._insert_statement_markers(handler) elif isinstance(value, ast.AST): self._insert_statement_markers(value) elif isinstance(value, list): if len(value) > 0: new_list = [] for node in value: if self._should_instrument_as_statement(node): # self._debug("EBFOMA", node) # add before marker new_list.append( self._create_statement_marker(node, BEFORE_STATEMENT_MARKER) ) # original statement if self._should_instrument_as_statement(node): self._insert_statement_markers(node) new_list.append(node) if ( self._should_instrument_as_statement(node) and "skipexport" not in node.tags ): # add after marker new_list.append( self._create_statement_marker(node, AFTER_STATEMENT_MARKER) ) setattr(root, name, new_list) def _create_statement_marker(self, node, function_name): call = self._create_simple_marker_call(node, function_name) stmt = ast.Expr(value=call) ast.copy_location(stmt, node) ast.fix_missing_locations(stmt) return stmt def _insert_for_target_markers(self, root): """inserts markers which notify assignment to for-loop variables""" for node in ast.walk(root): if isinstance(node, ast.For): old_target = node.target # print(vars(old_target)) temp_name = "__for_loop_var" node.target = ast.Name(temp_name, ast.Store()) name_load = ast.Name(temp_name, ast.Load()) # value will be visible in parent's before_statement_again event name_load.tags = {"skip_before_expression", "skip_after_expression", "last_child"} name_load.lineno, name_load.col_offset = (node.iter.lineno, node.iter.col_offset) name_load.end_lineno, name_load.end_col_offset = ( node.iter.end_lineno, node.iter.end_col_offset, ) before_name_load = self._create_simple_marker_call( name_load, BEFORE_EXPRESSION_MARKER ) after_name_load = ast.Call( func=ast.Name(id=AFTER_EXPRESSION_MARKER, ctx=ast.Load()), args=[before_name_load, name_load], keywords=[], ) ass = ast.Assign([old_target], after_name_load) ass.lineno, ass.col_offset = old_target.lineno, old_target.col_offset ass.end_lineno, ass.end_col_offset = ( node.iter.end_lineno, node.iter.end_col_offset, ) ass.tags = {"skip_before_statement"} # before_statement_again will be shown name_load.parent_node = ass ass_before = self._create_statement_marker(ass, BEFORE_STATEMENT_MARKER) node.body.insert(0, ass_before) node.body.insert(1, ass) node.body.insert(2, self._create_statement_marker(ass, AFTER_STATEMENT_MARKER)) ast.fix_missing_locations(node) def _insert_expression_markers(self, node): """ TODO: this docstring is outdated each expression e gets wrapped like this: _after(_before(_loc, _node_is_zoomable), e, _node_role, _parent_range) where _after is function that gives the resulting value _before is function that signals the beginning of evaluation of e _loc gives the code range of e _node_is_zoomable indicates whether this node has subexpressions _node_role is either 'last_call_arg', 'last_op_arg', 'first_or_arg', 'first_and_arg', 'function' or None """ tracer = self class ExpressionVisitor(ast.NodeTransformer): def generic_visit(self, node): if isinstance(node, _ast.expr): if isinstance(node, ast.Starred): # keep this node as is, but instrument its children return ast.NodeTransformer.generic_visit(self, node) elif tracer._should_instrument_as_expression(node): # before marker before_marker = tracer._create_simple_marker_call( node, BEFORE_EXPRESSION_MARKER ) ast.copy_location(before_marker, node) if "ignore_children" in node.tags: transformed_node = node else: transformed_node = ast.NodeTransformer.generic_visit(self, node) # after marker after_marker = ast.Call( func=ast.Name(id=AFTER_EXPRESSION_MARKER, ctx=ast.Load()), args=[before_marker, transformed_node], keywords=[], ) ast.copy_location(after_marker, node) ast.fix_missing_locations(after_marker) # further transformations may query original node location from after marker if hasattr(node, "end_lineno"): after_marker.end_lineno = node.end_lineno after_marker.end_col_offset = node.end_col_offset return after_marker else: # This expression (and its children) should be ignored return node else: # Descend into statements return ast.NodeTransformer.generic_visit(self, node) return ExpressionVisitor().visit(node) def _create_simple_marker_call(self, node, fun_name, extra_args=[]): args = [self._export_node(node)] + extra_args return ast.Call(func=ast.Name(id=fun_name, ctx=ast.Load()), args=args, keywords=[]) def _export_node(self, node): assert isinstance(node, (ast.expr, ast.stmt)) node_id = id(node) self._nodes[node_id] = node return ast.Num(node_id) def _debug(self, *args): logger.debug("TRACER: " + str(args)) def _execute_prepared_user_code(self, statements, expression, global_vars): try: return Tracer._execute_prepared_user_code(self, statements, expression, global_vars) finally: """ from thonny.misc_utils import _win_get_used_memory print("Memory:", _win_get_used_memory() / 1024 / 1024) print("States:", len(self._saved_states)) print(self._fulltags.most_common()) """ class CustomStackFrame: def __init__(self, frame, event, focus=None): self.system_frame = frame self.event = event self.focus = focus self.current_evaluations = [] self.current_statement = None self.current_root_expression = None self.node_tags = set() class FancySourceFileLoader(SourceFileLoader): """Used for loading and instrumenting user modules during fancy tracing""" def __init__(self, fullname, path, tracer): super().__init__(fullname, path) self._tracer = tracer def source_to_code(self, data, path, *, _optimize=-1): old_tracer = sys.gettrace() sys.settrace(None) try: root = self._tracer._prepare_ast(data, path, "exec") return super().source_to_code(root, path) finally: sys.settrace(old_tracer) def _get_frame_prefix(frame): return str(id(frame)) + " " + ">" * len(inspect.getouterframes(frame, 0)) + " " def _get_python_version_string(add_word_size=False): result = ".".join(map(str, sys.version_info[:3])) if sys.version_info[3] != "final": result += "-" + sys.version_info[3] if add_word_size: result += " (" + ("64" if sys.maxsize > 2 ** 32 else "32") + " bit)" return result def _fetch_frame_source_info(frame): if frame.f_code.co_filename is None or not os.path.exists(frame.f_code.co_filename): return None, None, True is_libra = _is_library_file(frame.f_code.co_filename) if frame.f_code.co_name == "": source = inspect.getsource(frame.f_code) return source, frame.f_code.co_firstlineno, is_libra elif frame.f_code.co_name == "": # inspect.getsource and getsourcelines don't help here with tokenize.open(frame.f_code.co_filename) as fp: return fp.read(), 1, is_libra else: # function or class try: source = inspect.getsource(frame.f_code) # inspect.getsource is not reliable, see eg: # https://bugs.python.org/issue35101 # If the code name is not present as definition # in the beginning of the source, # then play safe and return the whole script first_line = source.splitlines()[0] if re.search(r"\b(class|def)\b\s+\b%s\b" % frame.f_code.co_name, first_line) is None: with tokenize.open(frame.f_code.co_filename) as fp: return fp.read(), 1, is_libra else: return source, frame.f_code.co_firstlineno, is_libra except OSError: logger.exception("Problem getting source") return None, None, True def format_exception_with_frame_info(e_type, e_value, e_traceback, shorten_filenames=False): """Need to suppress thonny frames to avoid confusion""" _traceback_message = "Traceback (most recent call last):\n" _cause_message = getattr( traceback, "_cause_message", ("\nThe above exception was the direct cause " + "of the following exception:") + "\n\n", ) _context_message = getattr( traceback, "_context_message", ("\nDuring handling of the above exception, " + "another exception occurred:") + "\n\n", ) def rec_format_exception_with_frame_info(etype, value, tb, chain=True): # Based on # https://www.python.org/dev/peps/pep-3134/#enhanced-reporting # and traceback.format_exception if etype is None: etype = type(value) if tb is None: tb = value.__traceback__ if chain: if value.__cause__ is not None: yield from rec_format_exception_with_frame_info(None, value.__cause__, None) yield (_cause_message, None, None, None) elif value.__context__ is not None and not value.__suppress_context__: yield from rec_format_exception_with_frame_info(None, value.__context__, None) yield (_context_message, None, None, None) if tb is not None: yield (_traceback_message, None, None, None) tb_temp = tb for entry in traceback.extract_tb(tb): assert tb_temp is not None # actual tb doesn't end before extract_tb if ( "thonny/backend" not in entry.filename and "thonny\\backend" not in entry.filename and ( not entry.filename.endswith(os.sep + "ast.py") or entry.name != "parse" or etype is not SyntaxError ) or in_debug_mode() ): fmt = ' File "{}", line {}, in {}\n'.format( entry.filename, entry.lineno, entry.name ) if entry.line: fmt += " {}\n".format(entry.line.strip()) yield (fmt, id(tb_temp.tb_frame), entry.filename, entry.lineno) tb_temp = tb_temp.tb_next assert tb_temp is None # tb was exhausted for line in traceback.format_exception_only(etype, value): if etype is SyntaxError and line.endswith("^\n"): # for some reason it may add several empty lines before ^-line partlines = line.splitlines() while len(partlines) >= 2 and partlines[-2].strip() == "": del partlines[-2] line = "\n".join(partlines) + "\n" yield (line, None, None, None) items = rec_format_exception_with_frame_info(e_type, e_value, e_traceback) return list(items) def in_debug_mode(): return os.environ.get("THONNY_DEBUG", False) in [1, "1", True, "True", "true"] def _is_library_file(filename): return ( filename is None or path_startswith(filename, sys.prefix) or hasattr(sys, "base_prefix") and path_startswith(filename, sys.base_prefix) or hasattr(sys, "real_prefix") and path_startswith(filename, getattr(sys, "real_prefix")) or site.ENABLE_USER_SITE and path_startswith(filename, site.getusersitepackages()) ) def _report_internal_error(): print("PROBLEM WITH THONNY'S BACK-END:\n", file=sys.stderr) traceback.print_exc() def get_vm(): return _vm thonny-3.2.7/thonny/roughparse.py0000644000175000017500000010173513611773167020147 0ustar annamaaannamaa00000000000000"""Facilities for learning the structure of incomplete Python code Mostly copied/adapted from idlelib.HyperParser and idlelib.PyParse """ import re import string from collections.abc import Mapping from keyword import iskeyword from typing import Dict # @UnusedImport NUM_CONTEXT_LINES = (50, 500, 5000000) # Reason last stmt is continued (or C_NONE if it's not). (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, C_STRING_NEXT_LINES, C_BRACKET) = range(5) # Find what looks like the start of a popular stmt. _synchre = re.compile( r""" ^ [ \t]* (?: while | else | def | return | assert | break | class | continue | elif | try | except | raise | import | yield ) \b """, re.VERBOSE | re.MULTILINE, ).search # Match blank line or non-indenting comment line. _junkre = re.compile( r""" [ \t]* (?: \# \S .* )? \n """, re.VERBOSE, ).match # Match any flavor of string; the terminating quote is optional # so that we're robust in the face of incomplete program text. _match_stringre = re.compile( r""" \""" [^"\\]* (?: (?: \\. | "(?!"") ) [^"\\]* )* (?: \""" )? | " [^"\\\n]* (?: \\. [^"\\\n]* )* "? | ''' [^'\\]* (?: (?: \\. | '(?!'') ) [^'\\]* )* (?: ''' )? | ' [^'\\\n]* (?: \\. [^'\\\n]* )* '? """, re.VERBOSE | re.DOTALL, ).match # Match a line that starts with something interesting; # used to find the first item of a bracket structure. _itemre = re.compile( r""" [ \t]* [^\s#\\] # if we match, m.end()-1 is the interesting char """, re.VERBOSE, ).match # Match start of stmts that should be followed by a dedent. _closere = re.compile( r""" \s* (?: return | break | continue | raise | pass ) \b """, re.VERBOSE, ).match # Chew up non-special chars as quickly as possible. If match is # successful, m.end() less 1 is the index of the last boring char # matched. If match is unsuccessful, the string starts with an # interesting char. _chew_ordinaryre = re.compile( r""" [^[\](){}#'"\\]+ """, re.VERBOSE, ).match class StringTranslatePseudoMapping(Mapping): r"""Utility class to be used with str.translate() This Mapping class wraps a given dict. When a value for a key is requested via __getitem__() or get(), the key is looked up in the given dict. If found there, the value from the dict is returned. Otherwise, the default value given upon initialization is returned. This allows using str.translate() to make some replacements, and to replace all characters for which no replacement was specified with a given character instead of leaving them as-is. For example, to replace everything except whitespace with 'x': >>> whitespace_chars = ' \t\n\r' >>> preserve_dict = {ord(c): ord(c) for c in whitespace_chars} >>> mapping = StringTranslatePseudoMapping(preserve_dict, ord('x')) >>> text = "a + b\tc\nd" >>> text.translate(mapping) 'x x x\tx\nx' """ def __init__(self, non_defaults, default_value): self._non_defaults = non_defaults self._default_value = default_value def _get(key, _get=non_defaults.get, _default=default_value): return _get(key, _default) self._get = _get def __getitem__(self, item): return self._get(item) def __len__(self): return len(self._non_defaults) def __iter__(self): return iter(self._non_defaults) def get(self, key, default=None): return self._get(key) class RoughParser: def __init__(self, indent_width, tabwidth): self.indent_width = indent_width self.tabwidth = tabwidth def set_str(self, s): assert len(s) == 0 or s[-1] == "\n" self.str = s self.study_level = 0 # Return index of a good place to begin parsing, as close to the # end of the string as possible. This will be the start of some # popular stmt like "if" or "def". Return None if none found: # the caller should pass more prior context then, if possible, or # if not (the entire program text up until the point of interest # has already been tried) pass 0 to set_lo. # # This will be reliable iff given a reliable is_char_in_string # function, meaning that when it says "no", it's absolutely # guaranteed that the char is not in a string. def find_good_parse_start(self, is_char_in_string=None, _synchre=_synchre): # pylint: disable=redefined-builtin str, pos = self.str, None # @ReservedAssignment if not is_char_in_string: # no clue -- make the caller pass everything return None # Peek back from the end for a good place to start, # but don't try too often; pos will be left None, or # bumped to a legitimate synch point. limit = len(str) for _ in range(5): i = str.rfind(":\n", 0, limit) if i < 0: break i = str.rfind("\n", 0, i) + 1 # start of colon line m = _synchre(str, i, limit) if m and not is_char_in_string(m.start()): pos = m.start() break limit = i if pos is None: # Nothing looks like a block-opener, or stuff does # but is_char_in_string keeps returning true; most likely # we're in or near a giant string, the colorizer hasn't # caught up enough to be helpful, or there simply *aren't* # any interesting stmts. In any of these cases we're # going to have to parse the whole thing to be sure, so # give it one last try from the start, but stop wasting # time here regardless of the outcome. m = _synchre(str) if m and not is_char_in_string(m.start()): pos = m.start() return pos # Peeking back worked; look forward until _synchre no longer # matches. i = pos + 1 while 1: m = _synchre(str, i) if m: s, i = m.span() if not is_char_in_string(s): pos = s else: break return pos # Throw away the start of the string. Intended to be called with # find_good_parse_start's result. def set_lo(self, lo): assert lo == 0 or self.str[lo - 1] == "\n" if lo > 0: self.str = self.str[lo:] # Build a translation table to map uninteresting chars to 'x', open # brackets to '(', close brackets to ')' while preserving quotes, # backslashes, newlines and hashes. This is to be passed to # str.translate() in _study1(). _tran1 = {} # type: Dict[int, int] _tran1.update((ord(c), ord("(")) for c in "({[") _tran1.update((ord(c), ord(")")) for c in ")}]") _tran1.update((ord(c), ord(c)) for c in "\"'\\\n#") _tran = StringTranslatePseudoMapping(_tran1, default_value=ord("x")) # As quickly as humanly possible , find the line numbers (0- # based) of the non-continuation lines. # Creates self.{goodlines, continuation}. def _study1(self): # pylint: disable=redefined-builtin if self.study_level >= 1: return self.study_level = 1 # Map all uninteresting characters to "x", all open brackets # to "(", all close brackets to ")", then collapse runs of # uninteresting characters. This can cut the number of chars # by a factor of 10-40, and so greatly speed the following loop. str = ( self.str.translate(self._tran) # @ReservedAssignment .replace("xxxxxxxx", "x") .replace("xxxx", "x") .replace("xx", "x") .replace("xx", "x") .replace("\nx", "\n") ) # note that replacing x\n with \n would be incorrect, because # x may be preceded by a backslash # March over the squashed version of the program, accumulating # the line numbers of non-continued stmts, and determining # whether & why the last stmt is a continuation. continuation = C_NONE level = lno = 0 # level is nesting level; lno is line number self.goodlines = goodlines = [0] push_good = goodlines.append i, n = 0, len(str) while i < n: ch = str[i] i = i + 1 # cases are checked in decreasing order of frequency if ch == "x": continue if ch == "\n": lno = lno + 1 if level == 0: push_good(lno) # else we're in an unclosed bracket structure continue if ch == "(": level = level + 1 continue if ch == ")": if level: level = level - 1 # else the program is invalid, but we can't complain continue if ch == '"' or ch == "'": # consume the string quote = ch if str[i - 1 : i + 2] == quote * 3: quote = quote * 3 firstlno = lno w = len(quote) - 1 i = i + w while i < n: ch = str[i] i = i + 1 if ch == "x": continue if str[i - 1 : i + w] == quote: i = i + w break if ch == "\n": lno = lno + 1 if w == 0: # unterminated single-quoted string # It doesn't matter if we're in brackets, # this should lead to # SyntaxError: EOL while scanning string literal level = 0 push_good(lno) break continue if ch == "\\": assert i < n if str[i] == "\n": lno = lno + 1 i = i + 1 continue # else comment char or paren inside string else: # didn't break out of the loop, so we're still # inside a string if (lno - 1) == firstlno: # before the previous \n in str, we were in the first # line of the string continuation = C_STRING_FIRST_LINE else: continuation = C_STRING_NEXT_LINES continue # with outer loop if ch == "#": # consume the comment i = str.find("\n", i) assert i >= 0 continue assert ch == "\\" assert i < n if str[i] == "\n": lno = lno + 1 if i + 1 == n: continuation = C_BACKSLASH i = i + 1 # The last stmt may be continued for all 3 reasons. # String continuation takes precedence over bracket # continuation, which beats backslash continuation. if ( continuation != C_STRING_FIRST_LINE and continuation != C_STRING_NEXT_LINES and level > 0 ): continuation = C_BRACKET self.continuation = continuation # Push the final line number as a sentinel value, regardless of # whether it's continued. assert (continuation == C_NONE) == (goodlines[-1] == lno) if goodlines[-1] != lno: push_good(lno) def get_continuation_type(self): self._study1() return self.continuation # study1 was sufficient to determine the continuation status, # but doing more requires looking at every character. study2 # does this for the last interesting statement in the block. # Creates: # self.stmt_start, stmt_end # slice indices of last interesting stmt # self.stmt_bracketing # the bracketing structure of the last interesting stmt; # for example, for the statement "say(boo) or die", stmt_bracketing # will be [(0, 0), (3, 1), (8, 0)]. Strings and comments are # treated as brackets, for the matter. # self.lastch # last non-whitespace character before optional trailing # comment # self.lastopenbracketpos # if continuation is C_BRACKET, index of last open bracket def _study2(self): # pylint: disable=redefined-builtin if self.study_level >= 2: return self._study1() self.study_level = 2 # Set p and q to slice indices of last interesting stmt. str, goodlines = self.str, self.goodlines # @ReservedAssignment i = len(goodlines) - 1 p = len(str) # index of newest line while i: assert p # p is the index of the stmt at line number goodlines[i]. # Move p back to the stmt at line number goodlines[i-1]. q = p for _ in range(goodlines[i - 1], goodlines[i]): # @UnusedVariable # tricky: sets p to 0 if no preceding newline p = str.rfind("\n", 0, p - 1) + 1 # The stmt str[p:q] isn't a continuation, but may be blank # or a non-indenting comment line. if _junkre(str, p): i = i - 1 else: break if i == 0: # nothing but junk! assert p == 0 q = p self.stmt_start, self.stmt_end = p, q # Analyze this stmt, to find the last open bracket (if any) # and last interesting character (if any). lastch = "" stack = [] # stack of open bracket indices push_stack = stack.append bracketing = [(p, 0)] while p < q: # suck up all except ()[]{}'"#\\ m = _chew_ordinaryre(str, p, q) if m: # we skipped at least one boring char newp = m.end() # back up over totally boring whitespace i = newp - 1 # index of last boring char while i >= p and str[i] in " \t\n": i = i - 1 if i >= p: lastch = str[i] p = newp if p >= q: break ch = str[p] if ch in "([{": push_stack(p) bracketing.append((p, len(stack))) lastch = ch p = p + 1 continue if ch in ")]}": if stack: del stack[-1] lastch = ch p = p + 1 bracketing.append((p, len(stack))) continue if ch == '"' or ch == "'": # consume string # Note that study1 did this with a Python loop, but # we use a regexp here; the reason is speed in both # cases; the string may be huge, but study1 pre-squashed # strings to a couple of characters per line. study1 # also needed to keep track of newlines, and we don't # have to. bracketing.append((p, len(stack) + 1)) lastch = ch p = _match_stringre(str, p, q).end() bracketing.append((p, len(stack))) continue if ch == "#": # consume comment and trailing newline bracketing.append((p, len(stack) + 1)) p = str.find("\n", p, q) + 1 assert p > 0 bracketing.append((p, len(stack))) continue assert ch == "\\" p = p + 1 # beyond backslash assert p < q if str[p] != "\n": # the program is invalid, but can't complain lastch = ch + str[p] p = p + 1 # beyond escaped char # end while p < q: self.lastch = lastch if stack: self.lastopenbracketpos = stack[-1] self.stmt_bracketing = tuple(bracketing) # Assuming continuation is C_BRACKET, return the number # of spaces the next line should be indented. def compute_bracket_indent(self): # pylint: disable=redefined-builtin self._study2() assert self.continuation == C_BRACKET j = self.lastopenbracketpos str = self.str # @ReservedAssignment n = len(str) origi = i = str.rfind("\n", 0, j) + 1 j = j + 1 # one beyond open bracket # find first list item; set i to start of its line while j < n: m = _itemre(str, j) if m: j = m.end() - 1 # index of first interesting char extra = 0 break else: # this line is junk; advance to next line i = j = str.find("\n", j) + 1 else: # nothing interesting follows the bracket; # reproduce the bracket line's indentation + a level j = i = origi while str[j] in " \t": j = j + 1 extra = self.indent_width return len(str[i:j].expandtabs(self.tabwidth)) + extra # Return number of physical lines in last stmt (whether or not # it's an interesting stmt! this is intended to be called when # continuation is C_BACKSLASH). def get_num_lines_in_stmt(self): self._study1() goodlines = self.goodlines return goodlines[-1] - goodlines[-2] # Assuming continuation is C_BACKSLASH, return the number of spaces # the next line should be indented. Also assuming the new line is # the first one following the initial line of the stmt. def compute_backslash_indent(self): # pylint: disable=redefined-builtin self._study2() assert self.continuation == C_BACKSLASH str = self.str # @ReservedAssignment i = self.stmt_start while str[i] in " \t": i = i + 1 startpos = i # See whether the initial line starts an assignment stmt; i.e., # look for an = operator endpos = str.find("\n", startpos) + 1 found = level = 0 while i < endpos: ch = str[i] if ch in "([{": level = level + 1 i = i + 1 elif ch in ")]}": if level: level = level - 1 i = i + 1 elif ch == '"' or ch == "'": i = _match_stringre(str, i, endpos).end() elif ch == "#": break elif ( level == 0 and ch == "=" and (i == 0 or str[i - 1] not in "=<>!") and str[i + 1] != "=" ): found = 1 break else: i = i + 1 if found: # found a legit =, but it may be the last interesting # thing on the line i = i + 1 # move beyond the = found = re.match(r"\s*\\", str[i:endpos]) is None if not found: # oh well ... settle for moving beyond the first chunk # of non-whitespace chars i = startpos while str[i] not in " \t\n": i = i + 1 return len(str[self.stmt_start : i].expandtabs(self.tabwidth)) + 1 # Return the leading whitespace on the initial line of the last # interesting stmt. def get_base_indent_string(self): self._study2() i, n = self.stmt_start, self.stmt_end j = i str_ = self.str while j < n and str_[j] in " \t": j = j + 1 return str_[i:j] # Did the last interesting stmt open a block? def is_block_opener(self): self._study2() return self.lastch == ":" # Did the last interesting stmt close a block? def is_block_closer(self): self._study2() return _closere(self.str, self.stmt_start) is not None # index of last open bracket ({[, or None if none lastopenbracketpos = None def get_last_open_bracket_pos(self): self._study2() return self.lastopenbracketpos # the structure of the bracketing of the last interesting statement, # in the format defined in _study2, or None if the text didn't contain # anything stmt_bracketing = None def get_last_stmt_bracketing(self): self._study2() return self.stmt_bracketing # all ASCII chars that may be in an identifier _ASCII_ID_CHARS = frozenset(string.ascii_letters + string.digits + "_") # all ASCII chars that may be the first char of an identifier _ASCII_ID_FIRST_CHARS = frozenset(string.ascii_letters + "_") # lookup table for whether 7-bit ASCII chars are valid in a Python identifier _IS_ASCII_ID_CHAR = [(chr(x) in _ASCII_ID_CHARS) for x in range(128)] # lookup table for whether 7-bit ASCII chars are valid as the first # char in a Python identifier _IS_ASCII_ID_FIRST_CHAR = [(chr(x) in _ASCII_ID_FIRST_CHARS) for x in range(128)] class HyperParser: """Provide advanced parsing abilities for ParenMatch and other extensions. HyperParser uses PyParser. PyParser mostly gives information on the proper indentation of code. HyperParser gives additional information on the structure of code. """ def __init__(self, text, index): "To initialize, analyze the surroundings of the given index." self.text = text parser = RoughParser(text.indent_width, text.tabwidth) def index2line(index): return int(float(index)) lno = index2line(text.index(index)) for context in NUM_CONTEXT_LINES: startat = max(lno - context, 1) startatindex = repr(startat) + ".0" stopatindex = "%d.end" % lno # We add the newline because PyParse requires a newline # at end. We add a space so that index won't be at end # of line, so that its status will be the same as the # char before it, if should. parser.set_str(text.get(startatindex, stopatindex) + " \n") bod = parser.find_good_parse_start(_build_char_in_string_func(startatindex)) if bod is not None or startat == 1: break parser.set_lo(bod or 0) # We want what the parser has, minus the last newline and space. self.rawtext = parser.str[:-2] # Parser.str apparently preserves the statement we are in, so # that stopatindex can be used to synchronize the string with # the text box indices. self.stopatindex = stopatindex self.bracketing = parser.get_last_stmt_bracketing() # find which pairs of bracketing are openers. These always # correspond to a character of rawtext. self.isopener = [ i > 0 and self.bracketing[i][1] > self.bracketing[i - 1][1] for i in range(len(self.bracketing)) ] self.set_index(index) def set_index(self, index): """Set the index to which the functions relate. The index must be in the same statement. """ indexinrawtext = len(self.rawtext) - len(self.text.get(index, self.stopatindex)) if indexinrawtext < 0: raise ValueError("Index %s precedes the analyzed statement" % index) self.indexinrawtext = indexinrawtext # find the rightmost bracket to which index belongs self.indexbracket = 0 while ( self.indexbracket < len(self.bracketing) - 1 and self.bracketing[self.indexbracket + 1][0] < self.indexinrawtext ): self.indexbracket += 1 if ( self.indexbracket < len(self.bracketing) - 1 and self.bracketing[self.indexbracket + 1][0] == self.indexinrawtext and not self.isopener[self.indexbracket + 1] ): self.indexbracket += 1 def is_in_string(self): """Is the index given to the HyperParser in a string?""" # The bracket to which we belong should be an opener. # If it's an opener, it has to have a character. return self.isopener[self.indexbracket] and self.rawtext[ self.bracketing[self.indexbracket][0] ] in ('"', "'") def is_in_code(self): """Is the index given to the HyperParser in normal code?""" return not self.isopener[self.indexbracket] or self.rawtext[ self.bracketing[self.indexbracket][0] ] not in ("#", '"', "'") def get_surrounding_brackets(self, openers="([{", mustclose=False): """Return bracket indexes or None. If the index given to the HyperParser is surrounded by a bracket defined in openers (or at least has one before it), return the indices of the opening bracket and the closing bracket (or the end of line, whichever comes first). If it is not surrounded by brackets, or the end of line comes before the closing bracket and mustclose is True, returns None. """ bracketinglevel = self.bracketing[self.indexbracket][1] before = self.indexbracket while ( not self.isopener[before] or self.rawtext[self.bracketing[before][0]] not in openers or self.bracketing[before][1] > bracketinglevel ): before -= 1 if before < 0: return None bracketinglevel = min(bracketinglevel, self.bracketing[before][1]) after = self.indexbracket + 1 while after < len(self.bracketing) and self.bracketing[after][1] >= bracketinglevel: after += 1 beforeindex = self.text.index( "%s-%dc" % (self.stopatindex, len(self.rawtext) - self.bracketing[before][0]) ) if after >= len(self.bracketing) or self.bracketing[after][0] > len(self.rawtext): if mustclose: return None afterindex = self.stopatindex else: # We are after a real char, so it is a ')' and we give the # index before it. afterindex = self.text.index( "%s-%dc" % (self.stopatindex, len(self.rawtext) - (self.bracketing[after][0] - 1)) ) return beforeindex, afterindex # the set of built-in identifiers which are also keywords, # i.e. keyword.iskeyword() returns True for them _ID_KEYWORDS = frozenset({"True", "False", "None"}) @classmethod def _eat_identifier(cls, s, limit, pos): """Given a string and pos, return the number of chars in the identifier which ends at pos, or 0 if there is no such one. This ignores non-identifier eywords are not identifiers. """ is_ascii_id_char = _IS_ASCII_ID_CHAR # Start at the end (pos) and work backwards. i = pos # Go backwards as long as the characters are valid ASCII # identifier characters. This is an optimization, since it # is faster in the common case where most of the characters # are ASCII. while i > limit and (ord(s[i - 1]) < 128 and is_ascii_id_char[ord(s[i - 1])]): i -= 1 # If the above loop ended due to reaching a non-ASCII # character, continue going backwards using the most generic # test for whether a string contains only valid identifier # characters. if i > limit and ord(s[i - 1]) >= 128: while i - 4 >= limit and ("a" + s[i - 4 : pos]).isidentifier(): i -= 4 if i - 2 >= limit and ("a" + s[i - 2 : pos]).isidentifier(): i -= 2 if i - 1 >= limit and ("a" + s[i - 1 : pos]).isidentifier(): i -= 1 # The identifier candidate starts here. If it isn't a valid # identifier, don't eat anything. At this point that is only # possible if the first character isn't a valid first # character for an identifier. if not s[i:pos].isidentifier(): return 0 elif i < pos: # All characters in str[i:pos] are valid ASCII identifier # characters, so it is enough to check that the first is # valid as the first character of an identifier. if not _IS_ASCII_ID_FIRST_CHAR[ord(s[i])]: return 0 # All keywords are valid identifiers, but should not be # considered identifiers here, except for True, False and None. if i < pos and (iskeyword(s[i:pos]) and s[i:pos] not in cls._ID_KEYWORDS): return 0 return pos - i # This string includes all chars that may be in a white space _whitespace_chars = " \t\n\\" def get_expression(self): """Return a string with the Python expression which ends at the given index, which is empty if there is no real one. """ if not self.is_in_code(): raise ValueError("get_expression should only be called" "if index is inside a code.") rawtext = self.rawtext bracketing = self.bracketing brck_index = self.indexbracket brck_limit = bracketing[brck_index][0] pos = self.indexinrawtext last_identifier_pos = pos postdot_phase = True while 1: # Eat whitespaces, comments, and if postdot_phase is False - a dot while 1: if pos > brck_limit and rawtext[pos - 1] in self._whitespace_chars: # Eat a whitespace pos -= 1 elif not postdot_phase and pos > brck_limit and rawtext[pos - 1] == ".": # Eat a dot pos -= 1 postdot_phase = True # The next line will fail if we are *inside* a comment, # but we shouldn't be. elif ( pos == brck_limit and brck_index > 0 and rawtext[bracketing[brck_index - 1][0]] == "#" ): # Eat a comment brck_index -= 2 brck_limit = bracketing[brck_index][0] pos = bracketing[brck_index + 1][0] else: # If we didn't eat anything, quit. break if not postdot_phase: # We didn't find a dot, so the expression end at the # last identifier pos. break ret = self._eat_identifier(rawtext, brck_limit, pos) if ret: # There is an identifier to eat pos = pos - ret last_identifier_pos = pos # Now, to continue the search, we must find a dot. postdot_phase = False # (the loop continues now) elif pos == brck_limit: # We are at a bracketing limit. If it is a closing # bracket, eat the bracket, otherwise, stop the search. level = bracketing[brck_index][1] while brck_index > 0 and bracketing[brck_index - 1][1] > level: brck_index -= 1 if bracketing[brck_index][0] == brck_limit: # We were not at the end of a closing bracket break pos = bracketing[brck_index][0] brck_index -= 1 brck_limit = bracketing[brck_index][0] last_identifier_pos = pos if rawtext[pos] in "([": # [] and () may be used after an identifier, so we # continue. postdot_phase is True, so we don't allow a dot. pass else: # We can't continue after other types of brackets if rawtext[pos] in "'\"": # Scan a string prefix while pos > 0 and rawtext[pos - 1] in "rRbBuU": pos -= 1 last_identifier_pos = pos break else: # We've found an operator or something. break return rawtext[last_identifier_pos : self.indexinrawtext] def _is_char_in_string(text_index): # in idlelib.EditorWindow this used info from colorer # to speed up things, but I dont want to rely on this return 1 def _build_char_in_string_func(startindex): # copied from idlelib.EditorWindow (Python 3.4.2) # Our editwin provides a _is_char_in_string function that works # with a Tk text index, but PyParse only knows about offsets into # a string. This builds a function for PyParse that accepts an # offset. def inner(offset, _startindex=startindex, _icis=_is_char_in_string): return _icis(_startindex + "+%dc" % offset) return inner thonny-3.2.7/thonny/base_file_browser.py0000644000175000017500000011760313611773167021445 0ustar annamaaannamaa00000000000000import tkinter as tk from tkinter import ttk, messagebox, simpledialog import os.path from thonny import get_workbench, misc_utils, tktextext, get_runner from thonny.ui_utils import ( scrollbar_style, lookup_style_option, show_dialog, create_string_var, CommonDialog, ) from tkinter.simpledialog import askstring from thonny.common import InlineCommand, get_dirs_child_data from copy import deepcopy from thonny.misc_utils import running_on_windows, sizeof_fmt import datetime import shutil _dummy_node_text = "..." _LOCAL_FILES_ROOT_TEXT = "" # needs to be initialized later TEXT_EXTENSIONS = [".py", ".pyw", ".txt", ".log", ".csv", ".json", ".yml", ".yaml"] ROOT_NODE_ID = "" class BaseFileBrowser(ttk.Frame): def __init__(self, master, show_hidden_files=False, show_expand_buttons=True): self.show_expand_buttons = show_expand_buttons self._cached_child_data = {} self.path_to_highlight = None ttk.Frame.__init__(self, master, borderwidth=0, relief="flat") self.vert_scrollbar = ttk.Scrollbar( self, orient=tk.VERTICAL, style=scrollbar_style("Vertical") ) self.vert_scrollbar.grid(row=0, column=1, sticky=tk.NSEW, rowspan=3) tktextext.fixwordbreaks(tk._default_root) self.building_breadcrumbs = False self.init_header(row=0, column=0) spacer = ttk.Frame(self, height=1) spacer.grid(row=1, sticky="nsew") self.tree = ttk.Treeview( self, columns=["#0", "kind", "path", "name", "time", "size"], displaycolumns=( # 4, # 5 ), yscrollcommand=self.vert_scrollbar.set, selectmode="extended", ) self.tree.grid(row=2, column=0, sticky=tk.NSEW) self.vert_scrollbar["command"] = self.tree.yview self.columnconfigure(0, weight=1) self.rowconfigure(2, weight=1) self.show_hidden_files = show_hidden_files self.tree["show"] = "tree" self.tree.bind("<3>", self.on_secondary_click, True) if misc_utils.running_on_mac_os(): self.tree.bind("<2>", self.on_secondary_click, True) self.tree.bind("", self.on_secondary_click, True) self.tree.bind("", self.on_double_click, True) self.tree.bind("<>", self.on_open_node) wb = get_workbench() self.folder_icon = wb.get_image("folder") self.python_file_icon = wb.get_image("python-file") self.text_file_icon = wb.get_image("text-file") self.generic_file_icon = wb.get_image("generic-file") self.hard_drive_icon = wb.get_image("hard-drive") self.tree.column("#0", width=200, anchor=tk.W) self.tree.heading("#0", text="Name", anchor=tk.W) self.tree.column("time", width=60, anchor=tk.W) self.tree.heading("time", text="Time", anchor=tk.W) self.tree.column("size", width=40, anchor=tk.E) self.tree.heading("size", text="Size (bytes)", anchor=tk.E) self.tree.column("kind", width=30, anchor=tk.W) # self.tree.heading("kind", text="Kind") # self.tree.column("path", width=300, anchor=tk.W) # self.tree.heading("path", text="path") # self.tree.column("name", width=60, anchor=tk.W) # self.tree.heading("name", text="name") # set-up root node self.tree.set(ROOT_NODE_ID, "kind", "root") self.menu = tk.Menu(self.tree, tearoff=False) self.current_focus = None def init_header(self, row, column): header_frame = ttk.Frame(self, style="ViewToolbar.TFrame") header_frame.grid(row=row, column=column, sticky="nsew") header_frame.columnconfigure(0, weight=1) self.path_bar = tktextext.TweakableText( header_frame, borderwidth=0, relief="flat", height=1, font="TkDefaultFont", wrap="word", padx=6, pady=5, insertwidth=0, highlightthickness=0, background=lookup_style_option("ViewToolbar.TFrame", "background"), ) self.path_bar.grid(row=0, column=0, sticky="nsew") self.path_bar.set_read_only(True) self.path_bar.bind("", self.resize_path_bar, True) self.path_bar.tag_configure( "dir", foreground=lookup_style_option("Url.TLabel", "foreground") ) self.path_bar.tag_configure("underline", underline=True) def get_dir_range(event): mouse_index = self.path_bar.index("@%d,%d" % (event.x, event.y)) return self.path_bar.tag_prevrange("dir", mouse_index + "+1c") def dir_tag_motion(event): self.path_bar.tag_remove("underline", "1.0", "end") dir_range = get_dir_range(event) if dir_range: range_start, range_end = dir_range self.path_bar.tag_add("underline", range_start, range_end) def dir_tag_enter(event): self.path_bar.config(cursor="hand2") def dir_tag_leave(event): self.path_bar.config(cursor="") self.path_bar.tag_remove("underline", "1.0", "end") def dir_tag_click(event): mouse_index = self.path_bar.index("@%d,%d" % (event.x, event.y)) lineno = int(float(mouse_index)) if lineno == 1: self.request_focus_into("") else: assert lineno == 2 dir_range = get_dir_range(event) if dir_range: _, end_index = dir_range path = self.path_bar.get("2.0", end_index) if path.endswith(":"): path += "\\" self.request_focus_into(path) self.path_bar.tag_bind("dir", "<1>", dir_tag_click) self.path_bar.tag_bind("dir", "", dir_tag_enter) self.path_bar.tag_bind("dir", "", dir_tag_leave) self.path_bar.tag_bind("dir", "", dir_tag_motion) # self.menu_button = ttk.Button(header_frame, text="≡ ", style="ViewToolbar.Toolbutton") self.menu_button = ttk.Button( header_frame, text=" ≡ ", style="ViewToolbar.Toolbutton", command=self.post_button_menu ) # self.menu_button.grid(row=0, column=1, sticky="ne") self.menu_button.place(anchor="ne", rely=0, relx=1) def clear(self): self.clear_error() self.invalidate_cache() self.path_bar.direct_delete("1.0", "end") self.tree.set_children("") self.current_focus = None def request_focus_into(self, path): return self.focus_into(path) def focus_into(self, path): self.clear_error() # clear self.tree.set_children(ROOT_NODE_ID) self.tree.set(ROOT_NODE_ID, "path", path) self.building_breadcrumbs = True self.path_bar.direct_delete("1.0", "end") self.path_bar.direct_insert("1.0", self.get_root_text(), ("dir",)) if path and path != "/": self.path_bar.direct_insert("end", "\n") def create_spacer(): return ttk.Frame(self.path_bar, height=1, width=4, style="ViewToolbar.TFrame") parts = self.split_path(path) for i, part in enumerate(parts): if i > 0: if parts[i - 1] != "": self.path_bar.window_create("end", window=create_spacer()) self.path_bar.direct_insert("end", self.get_dir_separator()) self.path_bar.window_create("end", window=create_spacer()) self.path_bar.direct_insert("end", part, tags=("dir",)) self.building_breadcrumbs = False self.resize_path_bar() self.render_children_from_cache() self.current_focus = path def split_path(self, path): return path.split(self.get_dir_separator()) def get_root_text(self): return get_local_files_root_text() def on_open_node(self, event): node_id = self.get_selected_node() path = self.tree.set(node_id, "path") if path: # and path not in self._cached_child_data: self.render_children_from_cache(node_id) # self.request_dirs_child_data(node_id, [path]) # else: def resize_path_bar(self, event=None): if self.building_breadcrumbs: return height = self.tk.call((self.path_bar, "count", "-update", "-displaylines", "1.0", "end")) self.path_bar.configure(height=height) def get_selected_node(self): """Returns single node (or nothing)""" nodes = self.tree.selection() if len(nodes) == 1: return nodes[0] elif len(nodes) > 1: return self.tree.focus() or None else: return None def get_selected_nodes(self, notify_if_empty=False): """Can return several nodes""" result = self.tree.selection() if not result and notify_if_empty: self.notify_missing_selection() return result def get_selection_info(self, notify_if_empty=False): nodes = self.get_selected_nodes(notify_if_empty) if not nodes: return None elif len(nodes) == 1: description = "'" + self.tree.set(nodes[0], "name") + "'" else: description = _("%d items") % len(nodes) paths = [self.tree.set(node, "path") for node in nodes] kinds = [self.tree.set(node, "kind") for node in nodes] return {"description": description, "nodes": nodes, "paths": paths, "kinds": kinds} def get_selected_path(self): return self.get_selected_value("path") def get_selected_kind(self): return self.get_selected_value("kind") def get_selected_name(self): return self.get_selected_value("name") def get_selected_value(self, key): node_id = self.get_selected_node() if node_id: return self.tree.set(node_id, key) else: return None def get_active_directory(self): path = self.tree.set(ROOT_NODE_ID, "path") return path def request_dirs_child_data(self, node_id, paths): raise NotImplementedError() def show_fs_info(self): path = self.get_selected_path() if path is None: path = self.current_focus self.request_fs_info(path) def request_fs_info(self, path): raise NotImplementedError() def present_fs_info(self, info): total_str = "?" if info["total"] is None else sizeof_fmt(info["total"]) used_str = "?" if info["used"] is None else sizeof_fmt(info["used"]) free_str = "?" if info["free"] is None else sizeof_fmt(info["free"]) text = ( "Storage space on this drive or filesystem:\n\n" " total: %s\n" % total_str + " used: %s\n" % used_str + " free: %s\n" % free_str ) if info.get("comment"): text += "\n" + info["comment"] messagebox.showinfo("Storage info", text) def cache_dirs_child_data(self, data): data = deepcopy(data) for parent_path in data: children_data = data[parent_path] if isinstance(children_data, dict): for child_name in children_data: child_data = children_data[child_name] assert isinstance(child_data, dict) if "label" not in child_data: child_data["label"] = child_name if "isdir" not in child_data: child_data["isdir"] = child_data.get("size", 0) is None else: assert children_data is None self._cached_child_data.update(data) def file_exists_in_cache(self, path): for parent_path in self._cached_child_data: # hard to split because it may not be in this system format name = path[len(parent_path) :] if name[0:1] in ["/", "\\"]: name = name[1:] if name in self._cached_child_data[parent_path]: return True return False def select_path_if_visible(self, path, node_id=""): for child_id in self.tree.get_children(node_id): if self.tree.set(child_id, "path") == path: self.tree.selection_set(child_id) return if self.tree.item(child_id, "open"): self.select_path_if_visible(path, child_id) def get_open_paths(self, node_id=ROOT_NODE_ID): if self.tree.set(node_id, "kind") == "file": return set() elif node_id == ROOT_NODE_ID or self.tree.item(node_id, "open"): result = {self.tree.set(node_id, "path")} for child_id in self.tree.get_children(node_id): result.update(self.get_open_paths(child_id)) return result else: return set() def invalidate_cache(self, paths=None): if paths is None: self._cached_child_data.clear() else: for path in paths: if path in self._cached_child_data: del self._cached_child_data[path] def render_children_from_cache(self, node_id=""): """ This node is supposed to be a directory and its contents needs to be shown and/or refreshed""" path = self.tree.set(node_id, "path") if path not in self._cached_child_data: self.request_dirs_child_data(node_id, self.get_open_paths() | {path}) # leave it as is for now, it will be updated later return children_data = self._cached_child_data[path] if children_data in ["file", "missing"]: # path used to be a dir but is now a file or does not exist # if browser is focused into this path if node_id == "": self.show_error("Directory " + path + " does not exist anymore", node_id) elif children_data == "missing": self.tree.delete(node_id) else: assert children_data == "file" self.tree.set_children(node_id) # clear the list of children self.tree.item(node_id, open=False) elif children_data is None: raise RuntimeError("None data for %s" % path) else: fs_children_names = children_data.keys() tree_children_ids = self.tree.get_children(node_id) # recollect children children = {} # first the ones, which are present already in tree for child_id in tree_children_ids: name = self.tree.set(child_id, "name") if name in fs_children_names: children[name] = child_id self.update_node_data(child_id, name, children_data[name]) # add missing children for name in fs_children_names: if name not in children: child_id = self.tree.insert(node_id, "end") children[name] = child_id self.tree.set(children[name], "path", self.join(path, name)) self.update_node_data(child_id, name, children_data[name]) def file_order(name): # items in a folder should be ordered so that # folders come first and names are ordered case insensitively return ( not children_data[name]["isdir"], # prefer directories not ":" in name, # prefer drives name.upper(), name, ) # update tree ids_sorted_by_name = list( map(lambda key: children[key], sorted(children.keys(), key=file_order)) ) self.tree.set_children(node_id, *ids_sorted_by_name) # recursively update open children for child_id in ids_sorted_by_name: if self.tree.item(child_id, "open"): self.render_children_from_cache(child_id) def show_error(self, msg, node_id=""): if not node_id: # clear tree self.tree.set_children("") err_id = self.tree.insert(node_id, "end") self.tree.item(err_id, text=msg) self.tree.set_children(node_id, err_id) def clear_error(self): "TODO:" def update_node_data(self, node_id, name, data): assert node_id != "" path = self.tree.set(node_id, "path") if data.get("time"): try: dtime = datetime.datetime.fromtimestamp(int(data["time"])) except Exception: time_str = "" else: time_str = dtime.isoformat().replace("T", " ") else: time_str = "" self.tree.set(node_id, "time", time_str) if data["isdir"]: self.tree.set(node_id, "kind", "dir") self.tree.set(node_id, "size", "") # Ensure that expand button is visible # unless we know it doesn't have children children_ids = self.tree.get_children(node_id) if ( self.show_expand_buttons and len(children_ids) == 0 and (path not in self._cached_child_data or self._cached_child_data[path]) ): self.tree.insert(node_id, "end", text=_dummy_node_text) if path.endswith(":") or path.endswith(":\\"): img = self.hard_drive_icon else: img = self.folder_icon else: self.tree.set(node_id, "kind", "file") self.tree.set(node_id, "size", data["size"]) # Make sure it doesn't have children self.tree.set_children(node_id) if path.lower().endswith(".py"): img = self.python_file_icon elif path.lower().endswith(".txt") or path.lower().endswith(".csv"): img = self.text_file_icon else: img = self.generic_file_icon self.tree.set(node_id, "name", name) self.tree.item(node_id, text=" " + data["label"], image=img) def join(self, parent, child): if parent == "": if self.get_dir_separator() == "/": return "/" + child else: return child if parent.endswith(self.get_dir_separator()): return parent + child else: return parent + self.get_dir_separator() + child def get_dir_separator(self): return os.path.sep def on_double_click(self, event): path = self.get_selected_path() kind = self.get_selected_kind() parts = path.split(".") ext = "." + parts[-1] if path.endswith(ext) and kind == "file" and ext.lower() in TEXT_EXTENSIONS: self.open_file(path) elif kind == "dir": self.request_focus_into(path) return "break" def open_file(self, path): pass def on_secondary_click(self, event): node_id = self.tree.identify_row(event.y) if node_id: if node_id not in self.tree.selection(): # replace current selection self.tree.selection_set(node_id) self.tree.focus(node_id) else: self.tree.selection_set() self.path_bar.focus_set() self.tree.update() self.refresh_menu() self.menu.tk_popup(event.x_root, event.y_root) def post_button_menu(self): self.refresh_menu() self.menu.tk_popup( self.menu_button.winfo_rootx(), self.menu_button.winfo_rooty() + self.menu_button.winfo_height(), ) def refresh_menu(self): self.menu.delete(0, "end") self.add_first_menu_items() self.menu.add_separator() self.add_middle_menu_items() self.menu.add_separator() self.add_last_menu_items() def add_first_menu_items(self): selected_path = self.get_selected_path() selected_kind = self.get_selected_kind() self.menu.add_command(label=_("Refresh"), command=self.cmd_refresh_tree) if selected_kind == "dir": self.menu.add_command( label=_("Focus into"), command=lambda: self.request_focus_into(selected_path) ) else: "TODO: add open command" def cmd_refresh_tree(self): self.refresh_tree() def add_middle_menu_items(self): if self.supports_trash(): if running_on_windows(): trash_label = _("Move to Recycle Bin") else: trash_label = _("Move to Trash") self.menu.add_command(label=trash_label, command=self.move_to_trash) else: self.menu.add_command(label=_("Delete"), command=self.delete) if self.supports_directories(): self.menu.add_command(label=_("New directory") + "...", command=self.mkdir) def add_last_menu_items(self): self.menu.add_command(label=_("Properties"), command=self.show_properties) self.menu.add_command(label=_("Storage space"), command=self.show_fs_info) def show_properties(self): node_id = self.get_selected_node() if node_id is None: self.notify_missing_selection() return values = self.tree.set(node_id) text = _("Path") + ":\n " + values["path"] + "\n\n" if values["kind"] == "dir": title = _("Directory properties") else: title = _("File properties") size_fmt_str = sizeof_fmt(int(values["size"])) bytes_str = str(values["size"]) + " " + _("bytes") text += ( _("Size") + ":\n " + ( bytes_str if size_fmt_str.endswith(" B") else size_fmt_str + " (" + bytes_str + ")" ) + "\n\n" ) if values["time"].strip(): text += _("Modified") + ":\n " + values["time"] + "\n\n" messagebox.showinfo(title, text.strip()) def refresh_tree(self, paths_to_invalidate=None): self.invalidate_cache(paths_to_invalidate) if self.winfo_ismapped(): self.render_children_from_cache("") if self.path_to_highlight: self.select_path_if_visible(self.path_to_highlight) self.path_to_highlight = None def create_new_file(self): selected_node_id = self.get_selected_node() if selected_node_id: selected_path = self.tree.set(selected_node_id, "path") selected_kind = self.tree.set(selected_node_id, "kind") if selected_kind == "dir": parent_path = selected_path else: parent_id = self.tree.parent(selected_node_id) parent_path = self.tree.set(parent_id, "path") else: parent_path = self.current_focus name = askstring("File name", "Provide filename", initialvalue="") if not name: return path = self.join(parent_path, name) if name in self._cached_child_data[parent_path]: # TODO: ignore case in windows messagebox.showerror("Error", "The file '" + path + "' already exists") else: self.open_file(path) def delete(self): selection = self.get_selection_info(True) if not selection: return confirmation = "Are you sure want to delete %s?" % selection["description"] confirmation += "\n\nNB! Recycle bin won't be used (no way to undelete)!" if "dir" in selection["kinds"]: confirmation += "\n" + "Directories will be deleted with content." if not messagebox.askyesno("Are you sure?", confirmation): return self.perform_delete(selection["paths"], _("Deleting %s") % selection["description"]) self.refresh_tree() def move_to_trash(self): assert self.supports_trash() selection = self.get_selection_info(True) if not selection: return trash = "Recycle Bin" if running_on_windows() else "Trash" if not messagebox.askokcancel( "Moving to %s" % trash, "I'll try to move %s to %s,\n" % (selection["description"], trash) + "but my method is not always reliable —\n" + "in some cases the files will be deleted\n" + "without the possibility to restore.", icon="info", ): return self.perform_move_to_trash( selection["paths"], _("Moving %s to %s") % (selection["description"], trash) ) self.refresh_tree() def supports_trash(self): return False def mkdir(self): parent = self.get_selected_path() if parent is None: parent = self.current_focus else: if self.get_selected_kind() == "file": # dirname does the right thing even if parent is Linux path and runnning on Windows parent = os.path.dirname(parent) name = simpledialog.askstring( "New directory", "Enter name for new directory under\n%s" % parent ) if not name or not name.strip(): return self.perform_mkdir(parent, name.strip()) self.refresh_tree() def perform_delete(self, paths, description): raise NotImplementedError() def perform_move_to_trash(self, paths, description): raise NotImplementedError() def supports_directories(self): return True def perform_mkdir(self, parent_dir, name): raise NotImplementedError() def notify_missing_selection(self): messagebox.showerror("Nothing selected", "Select an item and try again!") class BaseLocalFileBrowser(BaseFileBrowser): def __init__(self, master, show_hidden_files=False, show_expand_buttons=True): super().__init__( master, show_hidden_files=show_hidden_files, show_expand_buttons=show_expand_buttons ) get_workbench().bind("WindowFocusIn", self.on_window_focus_in, True) get_workbench().bind("LocalFileOperation", self.on_local_file_operation, True) def destroy(self): super().destroy() get_workbench().unbind("WindowFocusIn", self.on_window_focus_in) get_workbench().unbind("LocalFileOperation", self.on_local_file_operation) def request_dirs_child_data(self, node_id, paths): self.cache_dirs_child_data(get_dirs_child_data(paths)) self.render_children_from_cache(node_id) def split_path(self, path): parts = super().split_path(path) if running_on_windows() and path.startswith("\\\\"): # Don't split a network name! sep = self.get_dir_separator() for i in reversed(range(len(parts))): prefix = sep.join(parts[: i + 1]) if os.path.ismount(prefix): return [prefix] + parts[i + 1 :] # Could not find the prefix corresponding to mount return [path] else: return parts def open_file(self, path): get_workbench().get_editor_notebook().show_file(path) def on_window_focus_in(self, event=None): self.refresh_tree() def on_local_file_operation(self, event): if event["operation"] in ["save", "delete"]: self.refresh_tree() self.select_path_if_visible(event["path"]) # TODO: select this file in tree? def request_fs_info(self, path): if path == "": self.notify_missing_selection() else: if not os.path.isdir(path): path = os.path.dirname(path) self.present_fs_info(shutil.disk_usage(path)._asdict()) def perform_delete(self, paths, description): # Deprecated. moving to trash should be used instead raise NotImplementedError() """ for path in sorted(paths, key=len, reverse=True): if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path) """ def perform_move_to_trash(self, paths, description): # TODO: do it with subprocess dialog import send2trash for path in paths: send2trash.send2trash(path) def perform_mkdir(self, parent_dir, name): os.mkdir(os.path.join(parent_dir, name), mode=0o700) def supports_trash(self): try: import send2trash # @UnusedImport return True except ImportError: return False class BaseRemoteFileBrowser(BaseFileBrowser): def __init__(self, master, show_hidden_files=False, show_expand_buttons=True): super().__init__( master, show_hidden_files=show_hidden_files, show_expand_buttons=show_expand_buttons ) self.dir_separator = "/" get_workbench().bind("get_dirs_child_data_response", self.update_dir_data, True) get_workbench().bind("get_fs_info_response", self.present_fs_info, True) get_workbench().bind("RemoteFileOperation", self.on_remote_file_operation, True) def destroy(self): super().destroy() get_workbench().unbind("get_dirs_child_data_response", self.update_dir_data) get_workbench().unbind("get_fs_info_response", self.present_fs_info) get_workbench().unbind("RemoteFileOperation", self.on_remote_file_operation) def get_root_text(self): runner = get_runner() if runner: return runner.get_node_label() return "Back-end" def request_dirs_child_data(self, node_id, paths): if get_runner(): get_runner().send_command( InlineCommand("get_dirs_child_data", node_id=node_id, paths=paths) ) def request_fs_info(self, path): if get_runner(): get_runner().send_command(InlineCommand("get_fs_info", path=path)) def get_dir_separator(self): return self.dir_separator def update_dir_data(self, msg): if msg.get("error"): self.show_error(msg["error"]) else: self.dir_separator = msg["dir_separator"] self.cache_dirs_child_data(msg["data"]) self.render_children_from_cache(msg["node_id"]) if self.path_to_highlight: self.select_path_if_visible(self.path_to_highlight) self.path_to_highlight = None def open_file(self, path): get_workbench().get_editor_notebook().show_remote_file(path) def supports_directories(self): runner = get_runner() if not runner: return False proxy = runner.get_backend_proxy() if not proxy: return False return proxy.supports_remote_directories() def on_remote_file_operation(self, event): path = event["path"] exists_in_cache = self.file_exists_in_cache(path) if ( event["operation"] == "save" and exists_in_cache or event["operation"] == "delete" and not exists_in_cache ): # No need to refresh return if "/" in path: parent = path[: path.rfind("/")] if not parent: parent = "/" else: parent = "" self.refresh_tree([parent]) self.path_to_highlight = path def perform_delete(self, paths, description): get_runner().send_command( InlineCommand("delete", paths=paths, blocking=True, description=description) ) def perform_mkdir(self, parent_dir, name): get_runner().send_command( InlineCommand("mkdir", path=parent_dir + self.get_dir_separator() + name) ) def supports_trash(self): return get_runner().get_backend_proxy().supports_trash() def request_focus_into(self, path): if not get_runner().ready_for_remote_file_operations(show_message=True): return False super().request_focus_into(path) if not get_runner().supports_remote_directories(): assert path == "" self.focus_into(path) elif self.current_focus == path: # refreshes self.focus_into(path) else: self.request_new_focus(path) def request_new_focus(self, path): # Overridden in active browser self.focus_into(path) def cmd_refresh_tree(self): if not get_runner().ready_for_remote_file_operations(show_message=True): return super().cmd_refresh_tree() class DialogRemoteFileBrowser(BaseRemoteFileBrowser): def __init__(self, master, dialog): super().__init__(master, show_expand_buttons=False) self.dialog = dialog self.tree["show"] = ("tree", "headings") self.tree.configure(displaycolumns=(5,)) self.tree.configure(height=10) def open_file(self, path): self.dialog.double_click_file(path) class BackendFileDialog(CommonDialog): def __init__(self, master, kind, initial_dir): super().__init__(master=master) self.result = None self.updating_selection = False self.kind = kind if kind == "open": self.title("Open from " + get_runner().get_node_label()) else: assert kind == "save" self.title("Save to " + get_runner().get_node_label()) background = ttk.Frame(self) background.grid(row=0, column=0, sticky="nsew") self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.browser = DialogRemoteFileBrowser(background, self) self.browser.grid(row=0, column=0, columnspan=4, sticky="nsew", pady=20, padx=20) self.browser.configure(borderwidth=1, relief="groove") self.browser.tree.configure(selectmode="browse") self.name_label = ttk.Label(background, text="File name:") self.name_label.grid(row=1, column=0, pady=(0, 20), padx=20, sticky="w") self.name_var = create_string_var("") self.name_entry = ttk.Entry( background, textvariable=self.name_var, state="normal" if kind == "save" else "disabled" ) self.name_entry.grid(row=1, column=1, pady=(0, 20), padx=(0, 20), sticky="we") self.name_entry.bind("", self.on_name_edit, True) self.ok_button = ttk.Button(background, text="OK", command=self.on_ok) self.ok_button.grid(row=1, column=2, pady=(0, 20), padx=(0, 20), sticky="e") self.cancel_button = ttk.Button(background, text="Cancel", command=self.on_cancel) self.cancel_button.grid(row=1, column=3, pady=(0, 20), padx=(0, 20), sticky="e") background.rowconfigure(0, weight=1) background.columnconfigure(1, weight=1) self.bind("", self.on_cancel, True) self.bind("", self.on_ok, True) self.protocol("WM_DELETE_WINDOW", self.on_cancel) self.tree_select_handler_id = self.browser.tree.bind( "<>", self.on_tree_select, True ) self.browser.request_focus_into(initial_dir) def on_ok(self, event=None): tree = self.browser.tree name = self.name_var.get() for node_id in tree.get_children(""): if name == tree.set(node_id, "name"): break else: node_id = None if node_id is not None: node_kind = tree.set(node_id, "kind") if node_kind != "file": messagebox.showerror(_("Error"), _("You need to select a file!")) return elif self.kind == "save": if not messagebox.askyesno( _("Overwrite?"), _("Do you want to overwrite '%s' ?") % name ): return parent_path = tree.set("", "path") if parent_path == "" or parent_path.endswith("/"): self.result = parent_path + name else: self.result = parent_path + "/" + name self.destroy() def on_cancel(self, event=None): self.result = None self.destroy() def on_tree_select(self, event=None): if self.updating_selection: return if self.browser.get_selected_kind() == "file": name = self.browser.get_selected_name() if name: self.name_var.set(name) def on_name_edit(self, event=None): self.updating_selection = True tree = self.browser.tree if self.tree_select_handler_id: tree.unbind("<>", self.tree_select_handler_id) self.tree_select_handler_id = None name = self.name_var.get() for node_id in tree.get_children(""): if name == tree.set(node_id, "name"): tree.selection_add(node_id) else: tree.selection_remove(node_id) self.updating_selection = False self.tree_select_handler_id = tree.bind("<>", self.on_tree_select, True) def double_click_file(self, path): assert path.endswith(self.name_var.get()) self.on_ok() class NodeChoiceDialog(CommonDialog): def __init__(self, master, prompt): super().__init__(master=master) self.result = None self.title(prompt) background = ttk.Frame(self) background.grid(row=0, column=0, sticky="nsew") self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) local_caption = get_local_files_root_text() remote_caption = get_runner().get_node_label() button_width = max(len(local_caption), len(remote_caption)) + 10 self.local_button = ttk.Button( background, text=" \n" + local_caption + "\n ", width=button_width, command=self.on_local, ) self.local_button.grid(row=0, column=0, pady=20, padx=20) self.remote_button = ttk.Button( background, text=" \n" + remote_caption + "\n ", width=button_width, command=self.on_remote, ) self.remote_button.grid(row=1, column=0, pady=(0, 20), padx=20) self.local_button.focus_set() self.bind("", self.on_cancel, True) self.bind("", self.on_return, True) self.bind("", self.on_down, True) self.bind("", self.on_up, True) self.protocol("WM_DELETE_WINDOW", self.on_cancel) def on_local(self, event=None): self.result = "local" self.destroy() def on_remote(self, event=None): self.result = "remote" self.destroy() def on_return(self, event=None): if self.focus_get() == self.local_button: return self.on_local(event) elif self.focus_get() == self.remote_button: return self.on_remote(event) def on_down(self, event=None): if self.focus_get() == self.local_button: self.remote_button.focus_set() def on_up(self, event=None): if self.focus_get() == self.remote_button: self.local_button.focus_set() def on_cancel(self, event=None): self.result = None self.destroy() def ask_backend_path(master, dialog_kind): proxy = get_runner().get_backend_proxy() if not proxy: return None assert proxy.supports_remote_files() dlg = BackendFileDialog(master, dialog_kind, proxy.get_cwd()) show_dialog(dlg, master) return dlg.result def choose_node_for_file_operations(master, prompt): if get_runner().supports_remote_files(): dlg = NodeChoiceDialog(master, prompt) show_dialog(dlg, master) if dlg.result == "remote" and not get_runner().ready_for_remote_file_operations( show_message=True ): return None return dlg.result else: return "local" def get_local_files_root_text(): global _LOCAL_FILES_ROOT_TEXT if not _LOCAL_FILES_ROOT_TEXT: # translation can't be done in module load time _LOCAL_FILES_ROOT_TEXT = _("This computer") return _LOCAL_FILES_ROOT_TEXT thonny-3.2.7/thonny/misc_utils.py0000644000175000017500000003672013611773167020144 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import os.path import platform import shlex import shutil import subprocess import sys import time from typing import Optional, Sequence, Tuple def delete_dir_try_hard(path: str, hardness: int = 5) -> None: # Deleting the folder on Windows is not so easy task # http://bugs.python.org/issue15496 for i in range(hardness): if os.path.exists(path): time.sleep(i * 0.5) shutil.rmtree(path, True) else: break if os.path.exists(path): # try once more but now without ignoring errors shutil.rmtree(path, False) def running_on_windows() -> bool: return platform.system() == "Windows" def running_on_mac_os() -> bool: return platform.system() == "Darwin" def running_on_linux() -> bool: return platform.system() == "Linux" def running_on_rpi() -> bool: return running_on_linux() and ( platform.uname().machine.lower().startswith("arm") or os.environ.get("DESKTOP_SESSION") == "LXDE-pi" ) def list_volumes(skip_letters=set()) -> Sequence[str]: "Adapted from https://github.com/ntoll/uflash/blob/master/uflash.py" if os.name == "posix": # 'posix' means we're on Linux or OSX (Mac). # Call the unix "mount" command to list the mounted volumes. mount_output = subprocess.check_output("mount").splitlines() return [x.split()[2].decode("utf-8") for x in mount_output] elif os.name == "nt": # 'nt' means we're on Windows. import ctypes # # In certain circumstances, volumes are allocated to USB # storage devices which cause a Windows popup to raise if their # volume contains no media. Wrapping the check in SetErrorMode # with SEM_FAILCRITICALERRORS (1) prevents this popup. # old_mode = ctypes.windll.kernel32.SetErrorMode(1) # @UndefinedVariable try: volumes = [] for disk in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": if disk in skip_letters: continue path = "{}:\\".format(disk) if os.path.exists(path): volumes.append(path) return volumes finally: ctypes.windll.kernel32.SetErrorMode(old_mode) # @UndefinedVariable else: # No support for unknown operating systems. raise NotImplementedError('OS "{}" not supported.'.format(os.name)) def get_win_volume_name(path: str) -> str: """ Each disk or external device connected to windows has an attribute called "volume name". This function returns the volume name for the given disk/device. Code from http://stackoverflow.com/a/12056414 """ import ctypes vol_name_buf = ctypes.create_unicode_buffer(1024) ctypes.windll.kernel32.GetVolumeInformationW( # @UndefinedVariable ctypes.c_wchar_p(path), vol_name_buf, ctypes.sizeof(vol_name_buf), None, None, None, None, 0 ) assert isinstance(vol_name_buf.value, str) return vol_name_buf.value def find_volumes_by_name(volume_name: str, skip_letters={"A"}) -> Sequence[str]: volumes = list_volumes(skip_letters=skip_letters) if os.name == "nt": return [ volume for volume in volumes if get_win_volume_name(volume).upper() == volume_name.upper() ] else: return [volume for volume in volumes if volume.endswith(volume_name)] def find_volume_by_name( volume_name: str, not_found_msg: Optional[str] = None, found_several_msg: Optional[str] = None ) -> Optional[str]: # Can't translate in the header as _ may not be available at import time if not_found_msg is None: not_found_msg = _("Could not find disk '%s'. Do you want to locate it yourself?") if found_several_msg is None: found_several_msg = _("Found several '%s' disks. Do you want to choose one yourself?") volumes = find_volumes_by_name(volume_name) if len(volumes) == 1: return volumes[0] else: if len(volumes) == 0: msg = not_found_msg % volume_name else: msg = found_several_msg % volume_name from tkinter.messagebox import askyesno from thonny.ui_utils import askdirectory import tkinter as tk if askyesno(_("Can't find suitable disk"), msg): path = askdirectory(master=tk._default_root) if path: return path return None def shorten_repr(original_repr: str, max_len: int = 1000) -> str: if len(original_repr) > max_len: return original_repr[: max_len - 1] + "…" else: return original_repr def get_python_version_string(version_info: Optional[Tuple] = None) -> str: if version_info is None: version_info = sys.version_info result = ".".join(map(str, version_info[:3])) if version_info[3] != "final": result += "-" + version_info[3] result += " (" + ("64" if sys.maxsize > 2 ** 32 else "32") + " bit)\n" return result def _win_get_used_memory(): # http://code.activestate.com/recipes/578513-get-memory-usage-of-windows-processes-using-getpro/ import ctypes from ctypes import wintypes GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess GetCurrentProcess.argtypes = [] GetCurrentProcess.restype = wintypes.HANDLE SIZE_T = ctypes.c_size_t class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure): _fields_ = [ ("cb", wintypes.DWORD), ("PageFaultCount", wintypes.DWORD), ("PeakWorkingSetSize", SIZE_T), ("WorkingSetSize", SIZE_T), ("QuotaPeakPagedPoolUsage", SIZE_T), ("QuotaPagedPoolUsage", SIZE_T), ("QuotaPeakNonPagedPoolUsage", SIZE_T), ("QuotaNonPagedPoolUsage", SIZE_T), ("PagefileUsage", SIZE_T), ("PeakPagefileUsage", SIZE_T), ("PrivateUsage", SIZE_T), ] GetProcessMemoryInfo = ctypes.windll.psapi.GetProcessMemoryInfo GetProcessMemoryInfo.argtypes = [ wintypes.HANDLE, ctypes.POINTER(PROCESS_MEMORY_COUNTERS_EX), wintypes.DWORD, ] GetProcessMemoryInfo.restype = wintypes.BOOL def get_current_process(): """Return handle to current process.""" return GetCurrentProcess() def get_memory_info(process=None): """Return Win32 process memory counters structure as a dict.""" if process is None: process = get_current_process() counters = PROCESS_MEMORY_COUNTERS_EX() ret = GetProcessMemoryInfo(process, ctypes.byref(counters), ctypes.sizeof(counters)) if not ret: raise ctypes.WinError() info = dict((name, getattr(counters, name)) for name, _ in counters._fields_) return info return get_memory_info()["PrivateUsage"] def _unix_get_used_memory(): # http://fa.bianp.net/blog/2013/different-ways-to-get-memory-consumption-or-lessons-learned-from-memory_profiler/ "TODO:" def construct_cmd_line(parts, safe_tokens=[]): def quote(s): if s in safe_tokens: return s else: return shlex.quote(s) return " ".join(map(quote, parts)) def parse_cmd_line(s): return shlex.split(s, posix=True) def levenshtein_distance(s1, s2): # https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#Python if len(s1) < len(s2): return levenshtein_distance(s2, s1) # len(s1) >= len(s2) if len(s2) == 0: return len(s1) previous_row = range(len(s2) + 1) for i, c1 in enumerate(s1): current_row = [i + 1] for j, c2 in enumerate(s2): insertions = ( previous_row[j + 1] + 1 ) # j+1 instead of j since previous_row and current_row are one character longer deletions = current_row[j] + 1 # than s2 substitutions = previous_row[j] + (c1 != c2) current_row.append(min(insertions, deletions, substitutions)) previous_row = current_row return previous_row[-1] def levenshtein_damerau_distance(s1, s2, maxDistance): # https://gist.github.com/giststhebearbear/4145811 # get smallest string so our rows are minimized s1, s2 = (s1, s2) if len(s1) <= len(s2) else (s2, s1) # set lengths l1, l2 = len(s1), len(s2) # We are simulatng an NM matrix where n is the longer string # and m is the shorter string. By doing this we can minimize # memory usage to O(M). # Since we are simulating the matrix we only maintain two rows # at a time the current row and the previous rows. # A move from the current cell looking at the cell before it indicates # consideration of an insert operation. # A move from the current cell looking at the cell above it indicates # consideration of a deletion # Both operations are cost 1 # A move from the current cell to the cell up and to the left indicates # an edit operation of 0 cost for a matching character and a 1 cost for # a non matching characters # no row has been previously computed yet, set empty row # Since this is also a Damerou-Levenshtein calculation transposition # costs will be taken into account. These look back 2 characters to # determine optimal cost based on a possible transposition # example: aei -> aie with levensthein has a cost of 2 # match a, change e->i change i->e => aie # Damarau-Levenshtein has a cost of 1 # match a, transpose ei to ie => aie transpositionRow = None prevRow = None # build first leven matrix row # The first row represents transformation from an empty string # to the shorter string making it static [0-n] # since this row is static we can set it as # curRow and start computation at the second row or index 1 curRow = [x for x in range(0, l1 + 1)] # use second length to loop through all the rows being built # we start at row one for rowNum in range(1, l2 + 1): # set transposition, previous, and current # because the rowNum always increments by one # we can use rowNum to set the value representing # the first column which is indicitive of transforming TO # the empty string from our longer string # transposition row maintains an extra row so that it is possible # for us to apply Damarou's formula transpositionRow, prevRow, curRow = prevRow, curRow, [rowNum] + [0] * l1 # consider if we have passed the max distance if all paths through # the transposition row are larger than the max we can stop calculating # distance and return the last element in that row and return the max if transpositionRow: if not any(cellValue < maxDistance for cellValue in transpositionRow): return maxDistance for colNum in range(1, l1 + 1): insertionCost = curRow[colNum - 1] + 1 deletionCost = prevRow[colNum] + 1 changeCost = prevRow[colNum - 1] + (0 if s1[colNum - 1] == s2[rowNum - 1] else 1) # set the cell value - min distance to reach this # position curRow[colNum] = min(insertionCost, deletionCost, changeCost) # test for a possible transposition optimization # check to see if we have at least 2 characters if 1 < rowNum <= colNum: # test for possible transposition if s1[colNum - 1] == s2[colNum - 2] and s2[colNum - 1] == s1[colNum - 2]: curRow[colNum] = min(curRow[colNum], transpositionRow[colNum - 2] + 1) # the last cell of the matrix is ALWAYS the shortest distance between the two strings return curRow[-1] def get_file_creation_date(path_to_file): """ Try to get the date that a file was created, falling back to when it was last modified if that isn't possible. See http://stackoverflow.com/a/39501288/1709587 for explanation. """ if platform.system() == "Windows": return os.path.getctime(path_to_file) else: stat = os.stat(path_to_file) try: return stat.st_birthtime except AttributeError: # We're probably on Linux. No easy way to get creation dates here, # so we'll settle for when its content was last modified. return stat.st_mtime _timer_time = 0 def start_time(text=""): global _timer_time print("RESET", text) _timer_time = time.time() def lap_time(text=""): global _timer_time new_time = time.time() print("LAP", text, round(new_time - _timer_time, 4)) _timer_time = time.time() class TimeHelper: def __init__(self, time_allowed): self.start_time = time.time() self.time_allowed = time_allowed @property def time_spent(self): return time.time() - self.start_time @property def time_left(self): return max(self.time_allowed - self.time_spent, 0) def copy_to_clipboard(data): if running_on_windows(): return _copy_to_windows_clipboard(data) elif running_on_mac_os(): command = ["pbcopy"] else: command = ["xsel", "-b", "-i"] env = dict(os.environ).copy() encoding = "utf-8" env["PYTHONIOENCODING"] = encoding if sys.version_info >= (3, 6): extra = {"encoding": encoding} else: extra = {} proc = subprocess.Popen( command, stdin=subprocess.PIPE, shell=False, env=env, universal_newlines=True, close_fds=True, **extra ) proc.communicate(input=data, timeout=0.1) def _copy_to_windows_clipboard(data): # https://bugs.python.org/file37366/test_clipboard_win.py import ctypes wcscpy = ctypes.cdll.msvcrt.wcscpy OpenClipboard = ctypes.windll.user32.OpenClipboard EmptyClipboard = ctypes.windll.user32.EmptyClipboard SetClipboardData = ctypes.windll.user32.SetClipboardData CloseClipboard = ctypes.windll.user32.CloseClipboard CF_UNICODETEXT = 13 GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc GlobalLock = ctypes.windll.kernel32.GlobalLock GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock GMEM_DDESHARE = 0x2000 OpenClipboard(None) EmptyClipboard() hCd = GlobalAlloc(GMEM_DDESHARE, 2 * (len(data) + 1)) pchData = GlobalLock(hCd) wcscpy(ctypes.c_wchar_p(pchData), data) GlobalUnlock(hCd) SetClipboardData(CF_UNICODETEXT, hCd) # ctypes.windll.user32.SetClipboardText(CF_UNICODETEXT, hCd) CloseClipboard() def sizeof_fmt(num, suffix="B"): """Readable file size :param num: Bytes value :type num: int :param suffix: Unit suffix (optionnal) default = B :type suffix: str :rtype: str """ # https://gist.github.com/cbwar/d2dfbc19b140bd599daccbe0fe925597 for unit in ["", "k", "M", "G", "T", "P", "E", "Z"]: if abs(num) < 1024.0: if unit == "": return "%d %s%s" % (num, unit, suffix) return "%.1f %s%s" % (num, unit, suffix) num /= 1024.0 return "%.1f%s%s" % (num, "Yi", suffix) def _get_known_folder(ID): # http://stackoverflow.com/a/3859336/261181 # http://www.installmate.com/support/im9/using/symbols/functions/csidls.htm import ctypes.wintypes SHGFP_TYPE_CURRENT = 0 buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) ctypes.windll.shell32.SHGetFolderPathW(0, ID, 0, SHGFP_TYPE_CURRENT, buf) assert buf.value return buf.value def get_roaming_appdata_dir(): return _get_known_folder(26) def get_local_appdata_dir(): return _get_known_folder(28) thonny-3.2.7/thonny/backend_launcher.py0000644000175000017500000000511213611773167021230 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- from __future__ import print_function """ This file is run by CPythonProxy (Why separate file for launching? I want to have clean global scope in toplevel __main__ module (because that's where user scripts run), but backend's global scope is far from clean. I could also do python -c "from backend import VM: VM().mainloop()", but looks like this gives relative __file__-s on imported modules.) """ if __name__ == "__main__": import sys import platform if platform.system() == "Darwin": import os try: os.getcwd() except Exception: print( "\nNB! Potential problems detected, see\nhttps://github.com/thonny/thonny/wiki/MacOSX#catalina\n", file=sys.stderr, ) if not sys.version_info > (3, 5): print( "Thonny only supports Python 3.5 and later.\n" + "Choose another interpreter from Tools => Options => Interpreter", file=sys.stderr, ) exit() import logging import os.path # remove script dir from path sys.path.pop(0) # import thonny relative to this script (not from current interpreter path) import importlib.util spec = importlib.util.spec_from_file_location( "thonny", os.path.join(os.path.dirname(__file__), "__init__.py") ) thonny = importlib.util.module_from_spec(spec) sys.modules["thonny"] = thonny assert spec.loader is not None spec.loader.exec_module(thonny) THONNY_USER_DIR = os.environ["THONNY_USER_DIR"] # set up logging logger = logging.getLogger("thonny") logger.propagate = False logFormatter = logging.Formatter("%(levelname)s: %(message)s") file_handler = logging.FileHandler( os.path.join(THONNY_USER_DIR, "backend.log"), encoding="UTF-8", mode="w" ) file_handler.setFormatter(logFormatter) file_handler.setLevel(logging.INFO) logger.addHandler(file_handler) # Don't litter user stderr with thonny logging # TODO: Can I somehow send the log to front-end's stderr? """ stream_handler = logging.StreamHandler(stream=sys.stderr) stream_handler.setLevel(logging.INFO); stream_handler.setFormatter(logFormatter) logger.addHandler(stream_handler) """ logger.setLevel(logging.INFO) import faulthandler fault_out = open(os.path.join(THONNY_USER_DIR, "backend_faults.log"), mode="w") faulthandler.enable(fault_out) # Disable blurry scaling in Windows thonny.set_dpi_aware() from thonny.backend import VM # @UnresolvedImport VM().mainloop() thonny-3.2.7/thonny/locale/0000755000175000017500000000000013611777205016643 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/pt_BR/0000755000175000017500000000000013611777205017651 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/pt_BR/LC_MESSAGES/0000755000175000017500000000000013611777205021436 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/pt_BR/LC_MESSAGES/thonny.mo0000644000175000017500000002561313611773167023324 0ustar annamaaannamaa00000000000000  *%> dnYpc r ! 7 &_   x 4 ? 'O w    % 7   ( C V ] x               # / 64 k       *6?Uzd  ?CP BI&Nu }   /J R!\~co 2 DZ;$(M`e5#i; `dx )6>u) 8C IWp 7Qksz.S 2+^ x"&:SZ r}9 * :  ! !:!I!]!(n! !!!!!W"o""":"="##0#6#F#]#m# ~#X##,# $ $$/$ ?$K$^$e$n$$!$$$)$%%)"%'L%it&& '' '' ''5' ()( ?(OJ((2:)1m))))*\+y+ Please check your spelling! You need to enter (probably needs admin privileges). Upgrade and running it with to locate and install the package file (usually with .whl, .tar.gz or .zip extension). (Increase font size. New packages will be also installed into this directory. Other locations must be managed by alternative means.About BirdseyeAbout ThonnyAllow only single Thonny instanceAlternative Python 3 interpreter or virtual environmentAlternatively, if you have an older pip installed, then you can install packages on the command line (Tools → Open system shell...)Are you sure you want to uninstall it?AssistantAuthorAuto-completeBack to current frameBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?BugtrackerCan't close yetCan't find package name from the list: Case sensitiveClick CloseCopyCould not find the package from PyPI.Could not find the package info from PyPI. Error code: CutDebug current script (birdseye)Debug mode (provides more detailed logs)Decrease font sizeDeviceDisable notification soundDocumentationDownEditEditorEnter string to be replaced.EventsExitExport usage logs...FileFilesFindFind & ReplaceFind package from PyPIFind:Font scaling modeFull screenHelpHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomepageIf you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER. InstallInstall from PyPI Install from local file Installed to: Installed version: Installing pip Installing pip, please wait ... InterpreterLanguageLatest stable versionLatest versionMade in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMaximize viewNext objectNotesObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOutlinePackages' directory PastePrevious objectProgram argumentsPyPI pagePygame Zero modeReally uninstall?Recommended maximum line length (Set to 0 to turn off margin line)RedoReopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRunRun cellRun cell and advanceRun selection or current lineSelect allShow line numbersStart by selecting the package from the left. SummaryTarget: The specified text was not found!This box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This dialog lists all available packages, but allows upgrading and uninstalling only packages from This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsToolsUndoUninstallUpUpgradeUpgrade or uninstall Use "Stop" command if you want to cancel debuggingVariablesVersion historyViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling. You must restart Thonny for language change to take effect.You seem to have problems with pip exact package nameherepip, a required module for managing packages is missing or too old for Thonny. If your system package manager doesn't provide recent pip (9.0.0 or later), then you can install newest version by downloading pip, a required module for managing packages is missing or too old. Downloading pip installer (about 1.5 MB), please wait ... user site packages virtual environment Project-Id-Version: Thonny Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2019-08-24 13:36+0300 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: pt_br Language-Team: pt_br Plural-Forms: nplurals=2; plural=(n > 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.7.0 Por favor, verifique a ortografia! É necessário inserir (provavelmente precisa de privilégios de administrador). Atualizar e executando-o com para localizar e instalar o arquivo do pacote (geralmente com extensão .whl, .tar.gz ou .zip).(Aumentar tamanho da fonte. Novos pacotes também serão instalados neste diretório. Outros locais devem ser gerenciados por meios alternativos. Sobre BirdseyeSobre ThonnyPermitir apenas uma ocorrência do ThonnyInterpretador Python 3 alternativo ou ambiente virtualAlternativamente, se você tem um pip mais antigo instalado, você pode instalar pacotes na linha de comando (Ferramentas → Abrir shell do sistema...)Tem certeza de que deseja desinstalá-lo?AssistenteAutorAutocompletarRetornar ao quadro atualO Birdseye é um depurador do Python que precisa ser instalado separadamente. Gostaria de abrir a página de ajuda e aprender mais?Rastrear BugsAinda não pode fecharNão é possível encontrar o nome do pacote na lista: Maiúsculas e minúsculasClique FecharCopiarNão foi possível encontrar o pacote do PyPI.Não foi possível encontrar as informações do pacote do PyPI. Erro de código: CortarDepurar script atual (Birdseye)Modo de depuração (fornece logs mais detalhados)Diminuir tamanho da fonteDispositivoDesativar som de notificaçãoDocumentaçãoBaixoEditarEditorInsira a string a ser substituídaEventosSairExportar logs de uso...ArquivoArquivosBuscarBuscar e SubstituirEncontrar pacote do PyPIBuscarModo de escala de fonteTela cheiaAjudaRealçar linha atual (requer reinicialização do editor)Realçar variáveis locaisRealçar nomes correspondentesRealçar parêntesesRealçar elementos de sintaxePágina inicialSe você não sabe de onde obter o pacote, provavelmente desejará pesquisar no Índice de Pacotes do Python. Comece digitando o nome do pacote na caixa de pesquisa acima e pressionando ENTER. InstalarInstalar a partir do PyPI Instalar do arquivo localInstalado em: Versão instalada: Instalando pip Instalando o pip, por favor, aguarde... InterpretadorIdiomaÚltima versão estávelÚltima versãoFeito na Universidade de Tartu na Estônia, com a ajuda da comunidade open-source, da Fundação Raspberry Pi e da Cybernetica ASAumentar visualizaçãoPróximo objetoNotasInspetor de objetosAbrir o Assistente quando houver avisos para o seu códigoAbrir o Assistente quando o programa travar com uma exceçãoEsboçoDiretório de pacotesColarObjeto anteriorArgumentos de programaPágina do PyPIModo Pygame ZeroDesinstalar?Comprimento máximo recomendado da linha (Defina como 0 para desligar a linha de margem)RefazerReabrir todos os arquivos da última sessãoSubstituirSub. todosSubstituir por:Sub.+BuscarReportar problemasRequerExecutarExecutar célulaExecutar célula e avançarExecutar seleção ou linha atualSelecionar tudoMostrar número de linhasComece selecionando o pacote da esquerda.SumárioAlvo: O texto especificado não foi encontrado!Esta caixa destina-se às suas notas de trabalho - instruções de atribuição, fragmentos de código etc. Tudo será salvo automaticamente e carregado quando você abrir o Thonny na próxima vez. Sinta-se à vontade para excluir este texto para criar espaço para suas próprias anotações.Este diálogo lista todos os pacotes disponíveis, mas permite atualizar e desinstalar apenas pacotes de Este programa não tem ABSOLUTAMENTE NENHUMA GARANTIA! É um software livre e você pode redistribuí-lo sob certas condições, para mais detalhes, acesse https://opensource.org/licenses/MITFerramentasDesfazerDesinstalarCimaAtualizarAtualizar ou desinstalar Utilize o comando "Parar" para cancelar a depuraçãoVariáveisHistórico da versãoVisualizarQual interpretador ou dispositivo o Thonny deveria usar para rodar seu código?Com o interpretador atual, você só pode navegar pelos pacotes aqui. Use 'Ferramentas → Abrir shell do sistema...' para instalar, atualizar ou desinstalar. Reinicie o Thonny para que o idioma seja alterado.Parece que você está tendo problemas com o pip o nome exato do pacote aquiO pip, um módulo necessário para gerenciar pacotes está ausente ou é muito antigo para o Thonny. Se o gerenciador de pacotes do sistema não fornecer o pip recente (9.0.0 ou posterior), você poderá instalar a versão mais recente fazendo o download O pip, um módulo necessário para gerenciar pacotes está ausente ou é muito antigo. Baixando o instalador do pip (cerca de 1,5 MB), por favor, aguarde... pacotes do local do usuárioambiente virtual thonny-3.2.7/thonny/locale/pt_BR/LC_MESSAGES/thonny.po0000644000175000017500000004200513611773167023321 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: pt-br\n" #: thonny/workbench.py:338 msgid "File" msgstr "Arquivo" #: thonny/workbench.py:339 msgid "Edit" msgstr "Editar" #: thonny/workbench.py:340 msgid "View" msgstr "Visualizar" #: thonny/workbench.py:341 msgid "Run" msgstr "Executar" #: thonny/workbench.py:342 msgid "Device" msgstr "Dispositivo" #: thonny/workbench.py:343 msgid "Tools" msgstr "Ferramentas" #: thonny/workbench.py:344 msgid "Help" msgstr "Ajuda" #: thonny/workbench.py:478 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Interpretador Python 3 alternativo ou ambiente virtual" #: thonny/workbench.py:486 msgid "A special virtual environment (deprecated)" msgstr "" #: thonny/workbench.py:523 msgid "Exit" msgstr "Sair" #: thonny/workbench.py:540 msgid "(Increase font size" msgstr "(Aumentar tamanho da fonte" #: thonny/workbench.py:550 msgid "Decrease font size" msgstr "Diminuir tamanho da fonte" #: thonny/workbench.py:562 msgid "Focus editor" msgstr "" #: thonny/workbench.py:571 msgid "Focus shell" msgstr "" #: thonny/workbench.py:582 msgid "Maximize view" msgstr "Aumentar visualização" #: thonny/workbench.py:594 msgid "Full screen" msgstr "Tela cheia" #: thonny/workbench.py:1195 msgid "Program arguments" msgstr "Argumentos de programa" #: thonny/plugins/about.py:24 thonny/plugins/about.py:160 msgid "About Thonny" msgstr "Sobre Thonny" #: thonny/plugins/about.py:80 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Feito na Universidade de Tartu na Estônia, com a ajuda da comunidade open-source, da Fundação Raspberry Pi e da Cybernetica AS" #: thonny/plugins/about.py:106 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Este programa não tem ABSOLUTAMENTE NENHUMA GARANTIA! É um software livre e você pode redistribuí-lo sob certas condições, para mais detalhes, acesse https://opensource.org/licenses/MIT" #: thonny/plugins/about.py:149 msgid "Version history" msgstr "Histórico da versão" #: thonny/plugins/about.py:156 msgid "Report problems" msgstr "Reportar problemas" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Abrir o Assistente quando o programa travar com uma exceção" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Abrir o Assistente quando houver avisos para o seu código" #: thonny/plugins/assistant_config_page.py:28 msgid "Perform selected Pylint checks" msgstr "" #: thonny/plugins/assistant_config_page.py:35 msgid "Perform MyPy checks" msgstr "" #: thonny/plugins/assistant_config_page.py:40 msgid "Disabled checks (one id per line)" msgstr "" #: thonny/plugins/assistant_config_page.py:80 msgid "Assistant" msgstr "Assistente" #: thonny/plugins/autocomplete.py:329 msgid "Auto-complete" msgstr "Autocompletar" #: thonny/plugins/backend_config_page.py:44 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Qual interpretador ou dispositivo o Thonny deveria usar para rodar seu código?" #: thonny/plugins/backend_config_page.py:128 msgid "Interpreter" msgstr "Interpretador" #: thonny/plugins/birdseye_frontend.py:30 msgid "About Birdseye" msgstr "Sobre Birdseye" #: thonny/plugins/birdseye_frontend.py:31 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "O Birdseye é um depurador do Python que precisa ser instalado separadamente.\n" "Gostaria de abrir a página de ajuda e aprender mais?" #: thonny/plugins/birdseye_frontend.py:55 msgid "Debug current script (birdseye)" msgstr "Depurar script atual (Birdseye)" #: thonny/plugins/cells.py:182 msgid "Run cell" msgstr "Executar célula" #: thonny/plugins/cells.py:192 msgid "Run cell and advance" msgstr "Executar célula e avançar" #: thonny/plugins/cells.py:202 msgid "Run selection or current line" msgstr "Executar seleção ou linha atual" #: thonny/plugins/commenting.py:113 msgid "Toggle comment" msgstr "" #: thonny/plugins/commenting.py:123 msgid "Comment out" msgstr "" #: thonny/plugins/commenting.py:133 msgid "Uncomment" msgstr "" #: thonny/plugins/common_editing_commands.py:32 msgid "Undo" msgstr "Desfazer" #: thonny/plugins/common_editing_commands.py:44 msgid "Redo" msgstr "Refazer" #: thonny/plugins/common_editing_commands.py:60 msgid "Cut" msgstr "Cortar" #: thonny/plugins/common_editing_commands.py:72 msgid "Copy" msgstr "Copiar" #: thonny/plugins/common_editing_commands.py:84 msgid "Paste" msgstr "Colar" #: thonny/plugins/common_editing_commands.py:96 thonny/plugins/debugger.py:123 msgid "Select all" msgstr "Selecionar tudo" #: thonny/plugins/debugger.py:114 msgid "Run to cursor" msgstr "" #: thonny/plugins/debugger.py:831 msgid "Can't close yet" msgstr "Ainda não pode fechar" #: thonny/plugins/debugger.py:832 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Utilize o comando \"Parar\" para cancelar a depuração" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Realçar nomes correspondentes" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Realçar variáveis locais" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Realçar parênteses" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Realçar elementos de sintaxe" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Realçar linha atual (requer reinicialização do editor)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Mostrar número de linhas" #: thonny/plugins/editor_config_page.py:50 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Comprimento máximo recomendado da linha\n" "(Defina como 0 para desligar a linha de margem)" #: thonny/plugins/editor_config_page.py:71 msgid "Editor" msgstr "Editor" #: thonny/plugins/event_logging.py:24 msgid "Export usage logs..." msgstr "Exportar logs de uso..." #: thonny/plugins/event_view.py:41 msgid "Events" msgstr "Eventos" #: thonny/plugins/files.py:113 msgid "Files" msgstr "Arquivos" #: thonny/plugins/find_replace.py:60 thonny/plugins/find_replace.py:422 msgid "Find & Replace" msgstr "Buscar e Substituir" #: thonny/plugins/find_replace.py:66 msgid "Find:" msgstr "Buscar" #: thonny/plugins/find_replace.py:81 msgid "Replace with:" msgstr "Substituir por:" #: thonny/plugins/find_replace.py:99 msgid "Case sensitive" msgstr "Maiúsculas e minúsculas" #: thonny/plugins/find_replace.py:106 msgid "Up" msgstr "Cima" #: thonny/plugins/find_replace.py:110 msgid "Down" msgstr "Baixo" #: thonny/plugins/find_replace.py:117 msgid "Find" msgstr "Buscar" #: thonny/plugins/find_replace.py:126 msgid "Replace" msgstr "Substituir" #: thonny/plugins/find_replace.py:133 msgid "Replace+Find" msgstr "Sub.+Buscar" #: thonny/plugins/find_replace.py:142 msgid "Replace all" msgstr "Sub. todos" #: thonny/plugins/find_replace.py:236 msgid "Enter string to be replaced." msgstr "Insira a string a ser substituída" #: thonny/plugins/find_replace.py:324 msgid "The specified text was not found!" msgstr "O texto especificado não foi encontrado!" #: thonny/plugins/general_config_page.py:14 msgid "Allow only single Thonny instance" msgstr "Permitir apenas uma ocorrência do Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Debug mode (provides more detailed logs)" msgstr "Modo de depuração (fornece logs mais detalhados)" #: thonny/plugins/general_config_page.py:26 msgid "Reopen all files from previous session" msgstr "Reabrir todos os arquivos da última sessão" #: thonny/plugins/general_config_page.py:32 msgid "Disable notification sound" msgstr "Desativar som de notificação" #: thonny/plugins/general_config_page.py:65 msgid "Font scaling mode" msgstr "Modo de escala de fonte" #: thonny/plugins/general_config_page.py:83 msgid "NB! Restart Thonny after changing these options\n" "in order to see the full effect" msgstr "" #: thonny/plugins/heap.py:39 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "" #: thonny/plugins/heap.py:89 msgid "Heap" msgstr "" #: thonny/plugins/language.py:13 thonny/plugins/language.py:39 msgid "Language" msgstr "Idioma" #: thonny/plugins/language.py:30 msgid "You must restart Thonny for language change to take effect." msgstr "Reinicie o Thonny para que o idioma seja alterado." #: thonny/plugins/notes.py:32 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Esta caixa destina-se às suas notas de trabalho - instruções de atribuição, fragmentos de código etc.\n" "\n" "Tudo será salvo automaticamente e carregado quando você abrir o Thonny na próxima vez.\n" "\n" "Sinta-se à vontade para excluir este texto para criar espaço para suas próprias anotações." #: thonny/plugins/notes.py:57 msgid "Notes" msgstr "Notas" #: thonny/plugins/object_inspector.py:110 msgid "Previous object" msgstr "Objeto anterior" #: thonny/plugins/object_inspector.py:113 msgid "Next object" msgstr "Próximo objeto" #: thonny/plugins/object_inspector.py:614 msgid "Object inspector" msgstr "Inspetor de objetos" #: thonny/plugins/outline.py:154 msgid "Outline" msgstr "Esboço" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Modo Pygame Zero" #: thonny/plugins/pip_gui.py:83 msgid "Find package from PyPI" msgstr "Encontrar pacote do PyPI" #: thonny/plugins/pip_gui.py:184 msgid " Upgrade " msgstr " Atualizar " #: thonny/plugins/pip_gui.py:191 msgid "Uninstall" msgstr "Desinstalar" #: thonny/plugins/pip_gui.py:206 msgid "Close" msgstr "Fechar" #: thonny/plugins/pip_gui.py:244 msgid "Installing pip\n" "\n" "" msgstr "Instalando pip \n" "" #: thonny/plugins/pip_gui.py:247 msgid "pip, a required module for managing packages is missing or too old.\n" "\n" "Downloading pip installer (about 1.5 MB), please wait ...\n" "" msgstr "O pip, um módulo necessário para gerenciar pacotes está ausente ou é muito antigo.\n" "\n" "Baixando o instalador do pip (cerca de 1,5 MB), por favor, aguarde...\n" "" #: thonny/plugins/pip_gui.py:255 msgid "Installing pip, please wait ...\n" "" msgstr "Instalando o pip, por favor, aguarde...\n" "" #: thonny/plugins/pip_gui.py:279 msgid "You seem to have problems with pip\n" "\n" "" msgstr "Parece que você está tendo problemas com o pip\n" "" #: thonny/plugins/pip_gui.py:283 msgid "pip, a required module for managing packages is missing or too old for Thonny.\n" "\n" "If your system package manager doesn't provide recent pip (9.0.0 or later), then you can install newest version by downloading " msgstr "O pip, um módulo necessário para gerenciar pacotes está ausente ou é muito antigo para o Thonny.\n" "\n" "Se o gerenciador de pacotes do sistema não fornecer o pip recente (9.0.0 ou posterior), você poderá instalar a versão mais recente fazendo o download " #: thonny/plugins/pip_gui.py:290 msgid " and running it with " msgstr " e executando-o com " #: thonny/plugins/pip_gui.py:292 msgid " (probably needs admin privileges).\n" "\n" "" msgstr " (provavelmente precisa de privilégios de administrador).\n" "" #: thonny/plugins/pip_gui.py:302 msgid "Alternatively, if you have an older pip installed, then you can install packages on the command line (Tools → Open system shell...)" msgstr "Alternativamente, se você tem um pip mais antigo instalado, você pode instalar pacotes na linha de comando (Ferramentas → Abrir shell do sistema...)" #: thonny/plugins/pip_gui.py:351 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.\n" "\n" "" msgstr "Com o interpretador atual, você só pode navegar pelos pacotes aqui.\n" "Use 'Ferramentas → Abrir shell do sistema...' para instalar, atualizar ou desinstalar.\n" "" #: thonny/plugins/pip_gui.py:357 msgid "Packages' directory\n" "" msgstr "Diretório de pacotes" #: thonny/plugins/pip_gui.py:363 msgid "Install from PyPI\n" "" msgstr "Instalar a partir do PyPI\n" "" #: thonny/plugins/pip_gui.py:366 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.\n" "\n" "" msgstr "Se você não sabe de onde obter o pacote, provavelmente desejará pesquisar no Índice de Pacotes do Python. Comece digitando o nome do pacote na caixa de pesquisa acima e pressionando ENTER.\n" "" #: thonny/plugins/pip_gui.py:372 msgid "Install from local file\n" "" msgstr "Instalar do arquivo local" #: thonny/plugins/pip_gui.py:374 msgid "Click " msgstr "Clique " #: thonny/plugins/pip_gui.py:375 msgid "here" msgstr "aqui" #: thonny/plugins/pip_gui.py:378 msgid " to locate and install the package file (usually with .whl, .tar.gz or .zip extension).\n" "\n" "" msgstr " para localizar e instalar o arquivo do pacote (geralmente com extensão .whl, .tar.gz ou .zip)." #: thonny/plugins/pip_gui.py:381 msgid "Upgrade or uninstall\n" "" msgstr "Atualizar ou desinstalar\n" "" #: thonny/plugins/pip_gui.py:383 msgid "Start by selecting the package from the left.\n" "\n" "" msgstr "Comece selecionando o pacote da esquerda." #: thonny/plugins/pip_gui.py:387 msgid "Target: " msgstr "Alvo: " #: thonny/plugins/pip_gui.py:390 msgid "virtual environment\n" "" msgstr "ambiente virtual\n" "" #: thonny/plugins/pip_gui.py:394 msgid "user site packages\n" "" msgstr "pacotes do local do usuário" #: thonny/plugins/pip_gui.py:399 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from " msgstr "Este diálogo lista todos os pacotes disponíveis, mas permite atualizar e desinstalar apenas pacotes de " #: thonny/plugins/pip_gui.py:407 msgid ". New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr ". Novos pacotes também serão instalados neste diretório. Outros locais devem ser gerenciados por meios alternativos.\n" "" #: thonny/plugins/pip_gui.py:430 msgid "Installed version: " msgstr "Versão instalada: " #: thonny/plugins/pip_gui.py:432 msgid "Installed to: " msgstr "Instalado em: " #: thonny/plugins/pip_gui.py:452 msgid "Upgrade" msgstr "Atualizar" #: thonny/plugins/pip_gui.py:457 msgid "Install" msgstr "Instalar" #: thonny/plugins/pip_gui.py:479 msgid "Could not find the package from PyPI." msgstr "Não foi possível encontrar o pacote do PyPI." #: thonny/plugins/pip_gui.py:482 msgid "\n" "Please check your spelling!" msgstr "\n" "Por favor, verifique a ortografia!" #: thonny/plugins/pip_gui.py:482 msgid "\n" "You need to enter " msgstr "\n" "É necessário inserir " #: thonny/plugins/pip_gui.py:483 msgid "exact package name" msgstr "o nome exato do pacote\n" "" #: thonny/plugins/pip_gui.py:488 msgid "Could not find the package info from PyPI. Error code: " msgstr "Não foi possível encontrar as informações do pacote do PyPI. Erro de código: \n" "" #: thonny/plugins/pip_gui.py:500 msgid "Latest stable version" msgstr "Última versão estável" #: thonny/plugins/pip_gui.py:502 msgid "Latest version" msgstr "Última versão" #: thonny/plugins/pip_gui.py:503 msgid "Summary" msgstr "Sumário" #: thonny/plugins/pip_gui.py:504 msgid "Author" msgstr "Autor" #: thonny/plugins/pip_gui.py:505 msgid "Homepage" msgstr "Página inicial" #: thonny/plugins/pip_gui.py:507 msgid "Bugtracker" msgstr "Rastrear Bugs" #: thonny/plugins/pip_gui.py:509 msgid "Documentation" msgstr "Documentação" #: thonny/plugins/pip_gui.py:511 msgid "PyPI page" msgstr "Página do PyPI" #: thonny/plugins/pip_gui.py:515 msgid "Requires" msgstr "Requer" #: thonny/plugins/pip_gui.py:553 msgid "Can't find package name from the list: " msgstr "Não é possível encontrar o nome do pacote na lista: " #: thonny/plugins/pip_gui.py:586 msgid "Really uninstall?" msgstr "Desinstalar?" #: thonny/plugins/pip_gui.py:590 msgid "Are you sure you want to uninstall it?" msgstr "Tem certeza de que deseja desinstalá-lo?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Retornar ao\n" "quadro atual" #: thonny/plugins/variables.py:142 msgid "Variables" msgstr "Variáveis" thonny-3.2.7/thonny/locale/en_US/0000755000175000017500000000000013611777205017654 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/en_US/LC_MESSAGES/0000755000175000017500000000000013611777205021441 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/en_US/LC_MESSAGES/thonny.mo0000644000175000017500000000070113611773167023316 0ustar annamaaannamaa00000000000000$,-Project-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2019-04-18 11:00+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: en_US Language-Team: en_US Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.7.0 thonny-3.2.7/thonny/locale/en_US/LC_MESSAGES/thonny.po0000644000175000017500000003177513611773167023340 0ustar annamaaannamaa00000000000000# English (United States) translations for PROJECT. # Copyright (C) 2019 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2019. # msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2019-04-18 11:00+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language: en_US\n" "Language-Team: en_US \n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.6.0\n" #: thonny/workbench.py:338 msgid "File" msgstr "" #: thonny/workbench.py:339 msgid "Edit" msgstr "" #: thonny/workbench.py:340 msgid "View" msgstr "" #: thonny/workbench.py:341 msgid "Run" msgstr "" #: thonny/workbench.py:342 msgid "Device" msgstr "" #: thonny/workbench.py:343 msgid "Tools" msgstr "" #: thonny/workbench.py:344 msgid "Help" msgstr "" #: thonny/workbench.py:478 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "" #: thonny/workbench.py:486 msgid "A special virtual environment (deprecated)" msgstr "" #: thonny/workbench.py:523 msgid "Exit" msgstr "" #: thonny/workbench.py:540 msgid "(Increase font size" msgstr "" #: thonny/workbench.py:550 msgid "Decrease font size" msgstr "" #: thonny/workbench.py:562 msgid "Focus editor" msgstr "" #: thonny/workbench.py:571 msgid "Focus shell" msgstr "" #: thonny/workbench.py:582 msgid "Maximize view" msgstr "" #: thonny/workbench.py:594 msgid "Full screen" msgstr "" #: thonny/workbench.py:1195 msgid "Program arguments" msgstr "" #: thonny/plugins/about.py:24 thonny/plugins/about.py:160 msgid "About Thonny" msgstr "" #: thonny/plugins/about.py:80 msgid "" "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "" #: thonny/plugins/about.py:106 msgid "" "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "" #: thonny/plugins/about.py:149 msgid "Version history" msgstr "" #: thonny/plugins/about.py:156 msgid "Report problems" msgstr "" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "" #: thonny/plugins/assistant_config_page.py:28 msgid "Perform selected Pylint checks" msgstr "" #: thonny/plugins/assistant_config_page.py:35 msgid "Perform MyPy checks" msgstr "" #: thonny/plugins/assistant_config_page.py:40 msgid "Disabled checks (one id per line)" msgstr "" #: thonny/plugins/assistant_config_page.py:80 msgid "Assistant" msgstr "" #: thonny/plugins/autocomplete.py:329 msgid "Auto-complete" msgstr "" #: thonny/plugins/backend_config_page.py:44 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "" #: thonny/plugins/backend_config_page.py:128 msgid "Interpreter" msgstr "" #: thonny/plugins/birdseye_frontend.py:30 msgid "About Birdseye" msgstr "" #: thonny/plugins/birdseye_frontend.py:31 msgid "" "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "" #: thonny/plugins/birdseye_frontend.py:55 msgid "Debug current script (birdseye)" msgstr "" #: thonny/plugins/cells.py:182 msgid "Run cell" msgstr "" #: thonny/plugins/cells.py:192 msgid "Run cell and advance" msgstr "" #: thonny/plugins/cells.py:202 msgid "Run selection or current line" msgstr "" #: thonny/plugins/commenting.py:113 msgid "Toggle comment" msgstr "" #: thonny/plugins/commenting.py:123 msgid "Comment out" msgstr "" #: thonny/plugins/commenting.py:133 msgid "Uncomment" msgstr "" #: thonny/plugins/common_editing_commands.py:32 msgid "Undo" msgstr "" #: thonny/plugins/common_editing_commands.py:44 msgid "Redo" msgstr "" #: thonny/plugins/common_editing_commands.py:60 msgid "Cut" msgstr "" #: thonny/plugins/common_editing_commands.py:72 msgid "Copy" msgstr "" #: thonny/plugins/common_editing_commands.py:84 msgid "Paste" msgstr "" #: thonny/plugins/common_editing_commands.py:96 thonny/plugins/debugger.py:123 msgid "Select all" msgstr "" #: thonny/plugins/debugger.py:114 msgid "Run to cursor" msgstr "" #: thonny/plugins/debugger.py:831 msgid "Can't close yet" msgstr "" #: thonny/plugins/debugger.py:832 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "" #: thonny/plugins/editor_config_page.py:50 msgid "" "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "" #: thonny/plugins/editor_config_page.py:71 msgid "Editor" msgstr "" #: thonny/plugins/event_logging.py:24 msgid "Export usage logs..." msgstr "" #: thonny/plugins/event_view.py:41 msgid "Events" msgstr "" #: thonny/plugins/files.py:113 msgid "Files" msgstr "" #: thonny/plugins/find_replace.py:60 thonny/plugins/find_replace.py:422 msgid "Find & Replace" msgstr "" #: thonny/plugins/find_replace.py:66 msgid "Find:" msgstr "" #: thonny/plugins/find_replace.py:81 msgid "Replace with:" msgstr "" #: thonny/plugins/find_replace.py:99 msgid "Case sensitive" msgstr "" #: thonny/plugins/find_replace.py:106 msgid "Up" msgstr "" #: thonny/plugins/find_replace.py:110 msgid "Down" msgstr "" #: thonny/plugins/find_replace.py:117 msgid "Find" msgstr "" #: thonny/plugins/find_replace.py:126 msgid "Replace" msgstr "" #: thonny/plugins/find_replace.py:133 msgid "Replace+Find" msgstr "" #: thonny/plugins/find_replace.py:142 msgid "Replace all" msgstr "" #: thonny/plugins/find_replace.py:236 msgid "Enter string to be replaced." msgstr "" #: thonny/plugins/find_replace.py:324 msgid "The specified text was not found!" msgstr "" #: thonny/plugins/general_config_page.py:14 msgid "Allow only single Thonny instance" msgstr "" #: thonny/plugins/general_config_page.py:20 msgid "Debug mode (provides more detailed logs)" msgstr "" #: thonny/plugins/general_config_page.py:26 msgid "Reopen all files from previous session" msgstr "" #: thonny/plugins/general_config_page.py:32 msgid "Disable notification sound" msgstr "" #: thonny/plugins/general_config_page.py:65 msgid "Font scaling mode" msgstr "" #: thonny/plugins/general_config_page.py:83 msgid "" "NB! Restart Thonny after changing these options\n" "in order to see the full effect" msgstr "" #: thonny/plugins/heap.py:39 msgid "" "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "" #: thonny/plugins/heap.py:89 msgid "Heap" msgstr "" #: thonny/plugins/language.py:13 thonny/plugins/language.py:39 msgid "Language" msgstr "" #: thonny/plugins/language.py:30 msgid "You must restart Thonny for language change to take effect." msgstr "" #: thonny/plugins/notes.py:32 msgid "" "This box is meant for your working notes -- assignment instructions, code" " snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny " "next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "" #: thonny/plugins/notes.py:57 msgid "Notes" msgstr "" #: thonny/plugins/object_inspector.py:110 msgid "Previous object" msgstr "" #: thonny/plugins/object_inspector.py:113 msgid "Next object" msgstr "" #: thonny/plugins/object_inspector.py:614 msgid "Object inspector" msgstr "" #: thonny/plugins/outline.py:154 msgid "Outline" msgstr "" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "" #: thonny/plugins/pip_gui.py:83 msgid "Find package from PyPI" msgstr "" #: thonny/plugins/pip_gui.py:184 msgid " Upgrade " msgstr "" #: thonny/plugins/pip_gui.py:191 msgid "Uninstall" msgstr "" #: thonny/plugins/pip_gui.py:206 msgid "Close" msgstr "" #: thonny/plugins/pip_gui.py:244 msgid "" "Installing pip\n" "\n" msgstr "" #: thonny/plugins/pip_gui.py:247 msgid "" "pip, a required module for managing packages is missing or too old.\n" "\n" "Downloading pip installer (about 1.5 MB), please wait ...\n" msgstr "" #: thonny/plugins/pip_gui.py:255 msgid "Installing pip, please wait ...\n" msgstr "" #: thonny/plugins/pip_gui.py:279 msgid "" "You seem to have problems with pip\n" "\n" msgstr "" #: thonny/plugins/pip_gui.py:283 msgid "" "pip, a required module for managing packages is missing or too old for " "Thonny.\n" "\n" "If your system package manager doesn't provide recent pip (9.0.0 or " "later), then you can install newest version by downloading " msgstr "" #: thonny/plugins/pip_gui.py:290 msgid " and running it with " msgstr "" #: thonny/plugins/pip_gui.py:292 msgid "" " (probably needs admin privileges).\n" "\n" msgstr "" #: thonny/plugins/pip_gui.py:302 msgid "" "Alternatively, if you have an older pip installed, then you can install " "packages on the command line (Tools → Open system shell...)" msgstr "" #: thonny/plugins/pip_gui.py:351 msgid "" "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or " "uninstalling.\n" "\n" msgstr "" #: thonny/plugins/pip_gui.py:357 msgid "Packages' directory\n" msgstr "" #: thonny/plugins/pip_gui.py:363 msgid "Install from PyPI\n" msgstr "" #: thonny/plugins/pip_gui.py:366 msgid "" "If you don't know where to get the package from, then most likely you'll " "want to search the Python Package Index. Start by entering the name of " "the package in the search box above and pressing ENTER.\n" "\n" msgstr "" #: thonny/plugins/pip_gui.py:372 msgid "Install from local file\n" msgstr "" #: thonny/plugins/pip_gui.py:374 msgid "Click " msgstr "" #: thonny/plugins/pip_gui.py:375 msgid "here" msgstr "" #: thonny/plugins/pip_gui.py:378 msgid "" " to locate and install the package file (usually with .whl, .tar.gz or " ".zip extension).\n" "\n" msgstr "" #: thonny/plugins/pip_gui.py:381 msgid "Upgrade or uninstall\n" msgstr "" #: thonny/plugins/pip_gui.py:383 msgid "" "Start by selecting the package from the left.\n" "\n" msgstr "" #: thonny/plugins/pip_gui.py:387 msgid "Target: " msgstr "" #: thonny/plugins/pip_gui.py:390 msgid "virtual environment\n" msgstr "" #: thonny/plugins/pip_gui.py:394 msgid "user site packages\n" msgstr "" #: thonny/plugins/pip_gui.py:399 msgid "" "This dialog lists all available packages, but allows upgrading and " "uninstalling only packages from " msgstr "" #: thonny/plugins/pip_gui.py:407 msgid "" ". New packages will be also installed into this directory. Other " "locations must be managed by alternative means." msgstr "" #: thonny/plugins/pip_gui.py:430 msgid "Installed version: " msgstr "" #: thonny/plugins/pip_gui.py:432 msgid "Installed to: " msgstr "" #: thonny/plugins/pip_gui.py:452 msgid "Upgrade" msgstr "" #: thonny/plugins/pip_gui.py:457 msgid "Install" msgstr "" #: thonny/plugins/pip_gui.py:479 msgid "Could not find the package from PyPI." msgstr "" #: thonny/plugins/pip_gui.py:482 msgid "" "\n" "Please check your spelling!" msgstr "" #: thonny/plugins/pip_gui.py:482 msgid "" "\n" "You need to enter " msgstr "" #: thonny/plugins/pip_gui.py:483 msgid "exact package name" msgstr "" #: thonny/plugins/pip_gui.py:488 msgid "Could not find the package info from PyPI. Error code: " msgstr "" #: thonny/plugins/pip_gui.py:500 msgid "Latest stable version" msgstr "" #: thonny/plugins/pip_gui.py:502 msgid "Latest version" msgstr "" #: thonny/plugins/pip_gui.py:503 msgid "Summary" msgstr "" #: thonny/plugins/pip_gui.py:504 msgid "Author" msgstr "" #: thonny/plugins/pip_gui.py:505 msgid "Homepage" msgstr "" #: thonny/plugins/pip_gui.py:507 msgid "Bugtracker" msgstr "" #: thonny/plugins/pip_gui.py:509 msgid "Documentation" msgstr "" #: thonny/plugins/pip_gui.py:511 msgid "PyPI page" msgstr "" #: thonny/plugins/pip_gui.py:515 msgid "Requires" msgstr "" #: thonny/plugins/pip_gui.py:553 msgid "Can't find package name from the list: " msgstr "" #: thonny/plugins/pip_gui.py:586 msgid "Really uninstall?" msgstr "" #: thonny/plugins/pip_gui.py:590 msgid "Are you sure you want to uninstall it?" msgstr "" #: thonny/plugins/variables.py:19 msgid "" "Back to\n" "current frame" msgstr "" #: thonny/plugins/variables.py:142 msgid "Variables" msgstr "" thonny-3.2.7/thonny/locale/fr_FR/0000755000175000017500000000000013611777205017641 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/fr_FR/LC_MESSAGES/0000755000175000017500000000000013611777205021426 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/fr_FR/LC_MESSAGES/thonny.mo0000644000175000017500000006660413611773167023321 0ustar annamaaannamaa00000000000000V ||}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/; ;;/d<F<0< ="=66=Mm=P=+ >p8>:>,> ??"? 3???X?{i??? @#@6A@&x@@@@@T@HAdA{AAAAA AA AA BZBBBCC)7CLaC*C)C&D$*DOD VD`D&|D)D'DGD=E']E EEEEE$E7E 2F8?F xF%F FRF G+G3GLGkGtG}GGGGGG G GGHH(/HXH`HxH HHH H H!HH!I'0IXIQJ bJ oJyJMJJJCJ7K!WKyK#KKK KKPK?LF#M jM#M MM!M'M@NZNlNN NNNKN O#O*OCOUO ]OhO |O7OOPQOR6bRRRRR4R&%SLSiSS SSSSAS9TATA UaLUUEvVhV%W-W=W WWWWUWUCX*X(X2X Y 7Y\XY YeY %Z0Z 7ZAZ IZUZuZT|ZZZZ!Z3[I[i[Jr[[[/[\ \ \*\A\Z\ m\ z\\\\$\\R\ =] G] R] ^]6j] ]]]]] ] ^ ^ ^#^:^P^,l^^-^ ^^__*_H_[_Bn_9__K `$U`z``F```a$a4)a^apaa aa&aaaabb"b+bBbURb8b+b c1cPd_d~3ee8efDf#g5g)Ggqgg,gg!ggIh Oh\h dhrh hhhhhh9i Wiaiwi iRii j#j7jk&!k0Hkyk~kkkkkBkkl,l7?lgwlYl9m Mmnm%d items(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)(restart Thonny after changing this)(used when clicking Debug toolbar button)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAdvanced install / upgrade / downgradeAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAllow stepping into libraries (ie. outside of main script directory)Alternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portBrowse the packagesBugtrackerCan't close yetCan't find package name from the list:Can't find suitable diskCancelCancel the process?Case sensitiveChange font sizeChange working directory to script directory on Run / DebugCircuitPython (generic)CircuitPython deviceClearClear shellClickClick CloseClose allClose othersComment outConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)ConfirmationConnect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find disk '%s'.Could not find disk '%s'. Do you want to locate it yourself?Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDeleteDeleting %sDesired versionDetailsDirectory propertiesDisable notification soundDisabled checks (one id per line)DisconnectDo you want to continue and locate the disk yourself?Do you want to overwrite '%s' ?Dock user windowsDocumentationDon't forget that main.py only works without embedded main script.Done!DownDownload to %sDownloading %s to %sEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFile propertiesFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus intoFocus shellFont scaling modeFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: fr %d éléments(Dans ce cas l'interpréteur de Thonny utilise le même interpréteur, afin que les deux boîtes de dialogue gèrent les mêmes paquets.)(redémarrez Thonny après avoir modifié ceci)(utilisé lors du clic sur le bouton Déboguer dans la barre d'outils)Un environnement virtuel spécifique (obsolète)À propos de BirdseyeÀ propos de ThonnyInstallation / Mise à jour / Rétrogradation avancéePermettre la complétion du code avec la touche de tabulation dans la consolePermettre la complétion du code avec la touche de tabulation dans les éditeursN'autoriser qu'une seule instance de ThonnyAutoriser l'entrée dans les bibliothèques en mode débogage (par ex. en dehors du dossier du script principal)Interpréteur Python 3 alternatif ou environnement virtuelÊtes-vous sur de vouloir le désinstaller ?AssistantAuteurAuto-complétionPrécédentRevenir au cadre courantDossier invalideBirdseye est un débogueur Python qui doit être installé séparément. Voulez-vous ouvrir l’aide pour en savoir plus ?Port de BirdseyeParcourir les paquetsSuivi des boguesImpossible de fermer pour l'instantImpossible de trouver le nom du paquet dans la liste :Impossible de trouver un disque valideAnnulerAnnuler le processus ?Sensible à la casseModifier la taille de la policeModifier le dossier de travail en dossier de script lors de l'exécution / débogageCircuitPython (générique)appareil CircuitPyhtonEffacerVider la consoleCliquezCliquez FermerTout fermerFermer les autresCommenterLa configuration a été mise à jour. Redémarrez Thonny pour commencer à travailler en mode normal. (Voir « Outils → Options → Général » si vous changez d'avis plus tard.)ConfirmationConnectez votre appareil à l'ordinateur et sélectionnez le port correspondant ci-dessousCopierCopier dans le presse-papiersCopieCopie de %s vers %sImpossible de trouver le disque « %s ».Impossible de trouver le dique « %s ». Voulez-vous le trouver vous-même ?Impossible de trouver le paquet dans PyPi.Impossible de trouver le paquet dans PyPICréer un nouvel environnement virtuelCréation de l'environnement virtuelCouperDéboguerDéboguer le script courantDéboguer le script courant (birdseye)Déboguer le script courant (plus rapide)Déboguer le script courant (plus joli)Mode de débogage (fournit des journaux de diagnostic plus détaillés)Diminuer la taille de la policeDésindenter les lignes sélectionnéesSupprimerSuppression de %sVersion souhaitéeDétailsPropriétés du dossierDésactiver les sons de notificationVérifications désactivées (un identifiant par ligne)DéconnecterVoulez-vous poursuivre et trouver le disque vous-même ?Voulez-vous écraser « %s » ?Ancrer les fenêtres de l'utilisateurDocumentationN'oubliez pas que main.py ne peut fonctionner que sans script principal intégré.Terminé !SuivantTéléchargement vers %sTéléchargement de %s vers %sÉditionÉditeurPolice de l'éditeurEntrez un nombre entierEntrez le texte à remplacer.ErreurCode d'erreur :Erreur :ÉvénementsExceptionQuitterQuitter ThonnyÉtendre dans la consoleExporter les journaux d’utilisation…FichierPropriétés du fichierFichiersRechercherRechercher et remplacerRechercher un paquet sur PyPIRechercher :MicrologicielPlacer le curseur dans l'éditeurAccentuer dansPlacer le curseur dans la consoleMode de mise à l'échelle de la policePour des raisons de performance, la console évite d'afficher les très longues lignes en entier (voir Outils => Options => Console). Vous pouvez interagir ici avec le texte original.Plusieurs disques « %s » trouvés. Voulez-vous en sélectionner un vous-même ?Plein écranGénéralAllocations mémoireLe suivi des allocations mémoire est activé. Fermez-le pour le désactiver.AideContenu de l'aideSurligner la ligne du curseur (nécessite de ré-ouvrir l'éditeur)Surligner les variables localesSurligner les noms correspondantsSurligner les parenthèsesSurligner les éléments de syntaxeAccueilPage d'accueilINSTALLERPolice de la consoleSi vous ne le trouvez pas, vous devriez d'abord installer un pilote USB correct.Si vous ne savez pas d'où vous pouvez obtenir le paquet, alors vous pouvez faire une recherche dans l'Index des Paquets Python. Commencez par entrer le nom du paquet dans le champ de recherche ci-dessus et appuyez sur ENTRÉE.Si vous le voulez vraiment, veuillez l'installer en ligne de commande.Augmenter la taille de la policeIndenter les lignes sélectionnéesInstallerInstaller depuis PyPIInstaller depuis un fichier localInstaller depuis un fichier d'exigencesInstaller la dernière version de MicroPython dans BBC micro:bitInstallée dans :Version installée :Installation…InterpréteurInterrompre l’exécutionEntrerConserver la fenêtre du terminal ouverte après la fin du processus PythonInterpréteurs connusLangueDernière version stableDernière versionChargerChargementEn trouver un autreEmplacement :Journaliser les évènements d'utilisation du programmeIl semble que vous êtes en train d'installer un paquet lié à Thonny. Si vous vouliez installer un plugin de Thonny, alors vous devriez sélectionner « Outils → Gérer les plugins… » Êtes-vous sûr de vouloir installer %s pour l'interpréteur ?Il semble que vous essayez d'installer un plugin de Thonny déprécié (il ne spécifie pas la version de Thonny requise). Si vous le voulez vraiment, veuillez l'installer en ligne de commande.Programmé à l'Université de Tartu, Estonie, avec l'aide de la communauté open-source, de la Fondation Raspberry Pi et de Cybernetica SASVeuillez vérifier que MicroPython a bien été installé dans votre micro:bit.Veuillez vérifier si le micro:bit est bien branché !Gérer les paquets pour %sGérer les paquets…Gérer les plugins…Agrandir la vueLongueur maximum de ligne avant de tronquer le texteNombre maximum de lignes à conserver.Peut ralentir le débogueur.MicroPython (générique)appareil MicroPyhtonModifié leDéplacer vers la corbeilleDéplacer vers la corbeilleDéplacement de %s vers %sRemarque : Tous les fichiers sur le micro:bit seront supprimés !Remarque : La fermeture automatique doit être activée dans les paramètres du terminal (Profils → Console → Lorsque la console se ferme)Remarque : De grandes valeurs peuvent réduire les performances !Remarque : Redémarrez Thonny après avoir modifié ces options !Remarque : Certains éléments de style ne seront modifiés qu'après le redémarrage de Thonny !Remarque : Il est possible qu'il y ait une autre version disponible qui soit compatible avec la version actuelle de Thonny. Cliquez sur le bouton « … » pour sélectionner la version à installer.Remarque : Thonny ne supporte que Python 3.5 et versions ultérieuresRemarque : Vous devez redémarrer Thonny après avoir installé / mis à jour / désinstallé un plugin.NouveauNouveau dossierLes nouveaux paquets seront également installés dans ce dossier. D'autres emplacements peuvent être gérés de façon différente.Objet suivantNotesOKInspecteur d'objetOuvrir l’assistant automatiquement lorsqu'il y a des avertissements pour votre codeOuvrir automatiquement l’assistant lorsqu’un programme plante avec une exception.Ouvrir le dossier de données de Thonny…Ouvrir le dossier programme de Thonny…Ouvrir et fermer la vue de la pile automatiquementOuvrir le relecteur…Ouvrir la console du système…Ouvrir la boîte de dialogue pour installer ou mettre à jour MicroPython sur votre appareilOuvrir…Ouvre la vue de la pile au premier appel et la ferme lorsque le programme revient au cadre principal.Options…SortirStructureSuivantÉcraser ?Remplacement du thème « %s »PaquetLe paquet « {} » est nécessaire pour installer ou désinstaller d'autres paquets.Dossier des paquetsCollerCheminEffectuer les vérifications MyPyEffectuer les vérifications Pylint sélectionnéesVeuillez vérifier la syntaxe !GrapheurLe Grapheur rend visuelles des séries de nombres affichées dans le ShellPortDébogueur favoriAfficher Python REPL après la fin du programmeAperçuObjet précédentImprimer…Arguments du programmeArguments du programme :Arbre du programmePropriétésPage PyPIMode Pygame ZeroInterpréteurs PythonQuitterVoulez-vous vraiment désinstaller ?Fichiers récentsLongueur maximale de ligne recommandée (définir à 0 pour désactiver la limite)RétablirActualiserMode normalRenommer…Réouvrir tous les fichiers de la session précédenteRemplacerRemplacer toutRemplacer par :Remplacer et rechercherSignaler un problèmeNécessiteExigences :ReprendreExécuterExécuter et déboguerExécuter / reprendreExécuter le script courantExécuter le script courant dans un terminalExécuter jusqu'au curseurExécution du script courant dans le terminalEnregistrerEnregistrer sous…Enregistrer une copie…EnregistrementVoir l'aide pour des détailsSélectionner toutTout sélectionnerSélectionner un dossier vide pour le nouvel environnement virtuelSélectionner un dossier existant ou en créer un nouveauSélectionner l'interpréteurLe dossier sélectionné n'est pas vide. Sélectionner un autre ou annuler.Envoyer le symbole EOF / RedémarrerConsoleAfficher le GrapheurAfficher les appels de fonction (cadres) dans des fenêtres séparéesAfficher les numéros de ligneTailleTexte tronqué (%d caractères)PileCommencez par sélectionner le paquet sur la gauche.Nœud précédentEntrer dans le nœudSortir du nœudNœud suivantArrêterArrêter/redémarrer l’interpréteurEspace de stockageRésuméPasser en mode normalThème de la syntaxeCible :TerminalÉmulation du terminalLa réponse estCe processus est toujours en cours d'exécution. Êtes-vous sûr de vouloir annuler ?Le même interpréteur qui exécute Thonny (par défaut)Le texte spécifié n'a pas été trouvé !Thème et policeCette section est prévue pour vos notes de travail : instructions d’affectation, fragments de code, ce que vous voulez. Tout sera sauvegardé automatiquement et chargé lorsque vous ouvrirez Thonny la prochaine fois. N’hésitez pas à effacer ce texte pour faire de la place pour vos propres notes.Cet ordinateurCette boîte de dialogue concerne la gestion des plugins de Thonny et leurs dépendances. Si vous souhaitez installer des paquets pour vos propres programmes, sélectionnez « Outils → Gérer les paquets… »Cette boîte de dialogue liste tous les paquets disponibles, mais n'autorise la mise à jour et la désinstallation que depuisCeci est un commentaireCe paquet nécessite une version différente de Thonny :Ce programme n'est fourni SANS AUCUNE GARANTIE QUELLE QU'ELLE SOIT Il s'agit d'un logiciel libre et vous pouvez le redistribuer sous certaines conditions. Voir https://opensource.org/licenses/MIT pour plus de détailsCet environnement virtuel est automatiquement maintenu par Thonny. Options de ThonnyPlugins de ThonnyPlugin pour Thonny sans aucun pré-requisCommenter/DécommenterOutilsEssayer de détecter le port automatiquementType d'interfaceFacteur d'échelle de l'interfaceThème de l'interfaceDécochez si vous souhaitez une expérience d'utilisation plus classique.DécommenterAnnulerDésinstallerExigences non satisfaitesPrécédentMettre à jourMettre à jour les dépendancesMettre à jour ou désinstallerTéléversement vers %sTéléversement de %s vers %sUtilisez la commande « Stop » pour annuler le débogageVariablesHistorique de versionVersion qui sera installée :AffichageQuel interpréteur ou appareil Thonny doit-il utiliser pour exécuter votre code ?Avec l'interpréteur courant vous ne pouvez parcourir que ces paquets. Utilisez « Outils → Ouvrir la console du système… » pour installer, mettre à jour ou désinstaller.Chargement…Enrouler le texte (peut être lent)Vous pouvez désormais fermer cette boîte de dialogue.Vous devez entrerVous devez sélectionner un fichier !Votre interpréteur n’est pas dans la liste ?Zoomtous les fichiersbla, blaoctetsle nom exact du moduleicirecherche du nom de votre appareil, « USB Serial » ou « UART »Emplacement de micro:bit :veuillez patienterexécutable pythonprend en charge les styles et les couleurs ANSI simplespour trouver et installer le fichier du paquet (généralement avec l'extension .whl, .tar.gz ou .zip).pour trouver le fichier requirements.txt et installer les paquets qui y sont spécifiés.chaîne_non_ferméepaquets de l'utilisateur du siteenvironnement virtuelthonny-3.2.7/thonny/locale/fr_FR/LC_MESSAGES/thonny.po0000644000175000017500000012317013611773167023314 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: fr\n" #: thonny/workbench.py:355 msgid "File" msgstr "Fichier" #: thonny/workbench.py:356 msgid "Edit" msgstr "Édition" #: thonny/workbench.py:357 msgid "View" msgstr "Affichage" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Exécuter" #: thonny/workbench.py:360 msgid "Tools" msgstr "Outils" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Aide" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Interpréteur Python 3 alternatif ou environnement virtuel" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Un environnement virtuel spécifique (obsolète)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Quitter" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Diminuer la taille de la police" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Placer le curseur dans l'éditeur" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Placer le curseur dans la console" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Agrandir la vue" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Plein écran" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Arguments du programme" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "À propos de Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Programmé à l'Université de Tartu, Estonie, avec l'aide de la communauté open-source, de la Fondation Raspberry Pi et de Cybernetica SAS" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Ce programme n'est fourni\n" "SANS AUCUNE GARANTIE QUELLE QU'ELLE SOIT \n" "Il s'agit d'un logiciel libre et vous pouvez le\n" "redistribuer sous certaines conditions.\n" "Voir https://opensource.org/licenses/MIT\n" "pour plus de détails" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Historique de version" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Signaler un problème" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Ouvrir automatiquement l’assistant lorsqu’un programme plante avec une exception." #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Ouvrir l’assistant automatiquement lorsqu'il y a des avertissements pour votre code" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Effectuer les vérifications Pylint sélectionnées" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Effectuer les vérifications MyPy" #. id ? code ? #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Vérifications désactivées (un identifiant par ligne)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Assistant" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Auto-complétion" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Quel interpréteur ou appareil Thonny doit-il utiliser pour exécuter votre code ?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Interpréteur" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "À propos de Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye est un débogueur Python qui doit être installé séparément.\n" "\n" "Voulez-vous ouvrir l’aide pour en savoir plus ?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Déboguer le script courant (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Commenter/Décommenter" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Commenter" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Décommenter" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Annuler" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Rétablir" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Couper" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Copier" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Coller" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Tout sélectionner" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Exécuter jusqu'au curseur" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Impossible de fermer pour l'instant" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Utilisez la commande « Stop » pour annuler le débogage" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Ancrer les fenêtres de l'utilisateur" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Surligner les noms correspondants" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Surligner les variables locales" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Surligner les parenthèses" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Surligner les éléments de syntaxe" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Surligner la ligne du curseur (nécessite de ré-ouvrir l'éditeur)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Permettre la complétion du code avec la touche de tabulation dans les éditeurs" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Permettre la complétion du code avec la touche de tabulation dans la console" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Afficher les numéros de ligne" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Longueur maximale de ligne recommandée\n" "(définir à 0 pour désactiver la limite)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Éditeur" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Exporter les journaux d’utilisation…" #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Événements" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Fichiers" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Rechercher et remplacer" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Rechercher :" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Remplacer par :" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Sensible à la casse" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Précédent" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Suivant" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Rechercher" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Remplacer" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Remplacer et rechercher" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Remplacer tout" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Entrez le texte à remplacer." #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "Le texte spécifié n'a pas été trouvé !" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "N'autoriser qu'une seule instance de Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Réouvrir tous les fichiers de la session précédente" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Désactiver les sons de notification" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Mode de mise à l'échelle de la police" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Le suivi des allocations mémoire est activé.\n" "Fermez-le pour le désactiver." #. Pile ? #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Allocations mémoire" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Langue" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Cette section est prévue pour vos notes de travail : instructions d’affectation, fragments de code, ce que vous voulez.\n" "\n" "Tout sera sauvegardé automatiquement et chargé lorsque vous ouvrirez Thonny la prochaine fois.\n" "\n" "N’hésitez pas à effacer ce texte pour faire de la place pour vos propres notes." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Notes" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Objet précédent" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Objet suivant" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Inspecteur d'objet" #. Vu qu'il s'agit d'une vue qui donne la structure du code (fonctions, classes etc), est-ce que "structure" ne serait pas mieux ? #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "Structure" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Mode Pygame Zero" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Rechercher un paquet sur PyPI" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Désinstaller" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Fermer" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Cliquez " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "ici" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Mettre à jour" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Installer" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Impossible de trouver le paquet dans PyPi." #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "le nom exact du module" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Dernière version stable" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Dernière version" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Résumé" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Auteur" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Page d'accueil" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Suivi des bogues" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Documentation" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "Page PyPI" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Nécessite" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Voulez-vous vraiment désinstaller ?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Êtes-vous sur de vouloir le désinstaller ?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Revenir au\n" "cadre courant" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Variables" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Cet ordinateur" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Actualiser" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Accentuer dans" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Erreur" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Vous devez sélectionner un fichier !" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Écraser ?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Voulez-vous écraser « %s » ?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Nouveau" #: thonny/code.py:526 msgid "Open..." msgstr "Ouvrir…" #: thonny/code.py:528 msgid "Load" msgstr "Charger" #: thonny/code.py:537 msgid "Recent files" msgstr "Fichiers récents" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Tout fermer" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Enregistrer" #: thonny/code.py:583 msgid "Save as..." msgstr "Enregistrer sous…" #: thonny/code.py:594 msgid "Save copy..." msgstr "Enregistrer une copie…" #: thonny/code.py:603 msgid "Rename..." msgstr "Renommer…" #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Options de Thonny" #: thonny/running.py:94 msgid "Run current script" msgstr "Exécuter le script courant" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Exécuter le script courant dans un terminal" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Arrêter/redémarrer l’interpréteur" #: thonny/running.py:139 msgid "Stop" msgstr "Arrêter" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Interrompre l’exécution" #: thonny/running.py:161 #, fuzzy msgid "Send EOF / Soft reboot" msgstr "Envoyer le symbole EOF / Redémarrer" #: thonny/running.py:172 msgid "Disconnect" msgstr "Déconnecter" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Interpréteurs connus" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Votre interpréteur n’est pas dans la liste ?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "En trouver un autre" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "exécutable python" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "Remarque : Thonny ne supporte que Python 3.5 et versions ultérieures" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Créer un nouvel environnement virtuel" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Sélectionner un dossier existant ou en créer un nouveau" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Interpréteurs Python" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "tous les fichiers" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Sélectionner un dossier vide pour le nouvel environnement virtuel" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Dossier invalide" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "Le dossier sélectionné n'est pas vide. Sélectionner un autre ou annuler." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Création de l'environnement virtuel" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Vider la console" #: thonny/shell.py:126 msgid "Plotter" msgstr "Grapheur" #: thonny/shell.py:245 msgid "Clear" msgstr "Effacer" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Afficher le Grapheur" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Pour des raisons de performance, la console évite d'afficher les très longues lignes en entier (voir Outils => Options => Console).\n" "Vous pouvez interagir ici avec le texte original." #: thonny/shell.py:1400 #, fuzzy msgid "Wrap text (may be slow)" msgstr "Enrouler le texte (peut être lent)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Copier dans le presse-papiers" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Étendre dans la console" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Texte tronqué (%d caractères)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Le Grapheur rend visuelles des séries de\n" "nombres affichées dans le Shell" #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Voir l'aide pour des détails" #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Fermer les autres" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Copie" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Copie de\n" " %s\n" "vers\n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Annuler" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "OK" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Annuler le processus ?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Ce processus est toujours en cours d'exécution.\n" "Êtes-vous sûr de vouloir annuler ?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Sélectionner tout" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Console" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Le même interpréteur qui exécute Thonny (par défaut)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Cet environnement virtuel est automatiquement maintenu par Thonny.\n" "\n" "" #: thonny/workbench.py:532 msgid "Location: " msgstr "Emplacement :" #: thonny/workbench.py:578 msgid "Options..." msgstr "Options…" #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Augmenter la taille de la police" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Modifier la taille de la police" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Zoom" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Quitter Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "Quitter" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "Remplacement du thème « %s »" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Arguments du programme :" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Mode normal" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "La configuration a été mise à jour. Redémarrez Thonny pour commencer à travailler en mode normal.\n" "\n" "(Voir « Outils → Options → Général » si vous changez d'avis plus tard.)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Arbre du programme" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Sélectionner l'interpréteur" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Reprendre" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Exécuter / reprendre" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Déboguer le script courant" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Déboguer" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Déboguer le script courant (plus joli)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Déboguer le script courant (plus rapide)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Nœud suivant" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "Suivant" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "Entrer dans le nœud" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "Entrer" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Sortir du nœud" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "Sortir" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Nœud précédent" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Précédent" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Pile" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Exception" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Journaliser les évènements d'utilisation du programme" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Mode de débogage (fournit des journaux de diagnostic plus détaillés)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "Type d'interface" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "Facteur d'échelle de l'interface" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "Remarque : Redémarrez Thonny après avoir modifié ces options !" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Général" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "INSTALLER" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Parcourir les paquets" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Avec l'interpréteur courant vous ne pouvez parcourir que ces paquets.\n" "Utilisez « Outils → Ouvrir la console du système… » pour installer, mettre à jour ou désinstaller." #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Dossier des paquets" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Installer depuis PyPI" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Si vous ne savez pas d'où vous pouvez obtenir le paquet, alors vous pouvez faire une recherche dans l'Index des Paquets Python. Commencez par entrer le nom du paquet dans le champ de recherche ci-dessus et appuyez sur ENTRÉE." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "pour trouver le fichier requirements.txt et installer les paquets qui y sont spécifiés." #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Cliquez" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "pour trouver et installer le fichier du paquet (généralement avec l'extension .whl, .tar.gz ou .zip)." #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Mettre à jour ou désinstaller" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Commencez par sélectionner le paquet sur la gauche." #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Cible :" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "environnement virtuel" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "paquets de l'utilisateur du site" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "Cette boîte de dialogue liste tous les paquets disponibles, mais n'autorise la mise à jour et la désinstallation que depuis" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Les nouveaux paquets seront également installés dans ce dossier. D'autres emplacements peuvent être gérés de façon différente." #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Version installée :" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Installée dans :" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Veuillez vérifier la syntaxe !" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "Vous devez entrer" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Impossible de trouver le paquet dans PyPI" #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Code d'erreur :" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Impossible de trouver le nom du paquet dans la liste :" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Le paquet « {} » est nécessaire pour installer ou désinstaller d'autres paquets." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Paquet" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Gérer les paquets pour %s" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Confirmation" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Il semble que vous êtes en train d'installer un paquet lié à Thonny. Si vous vouliez installer un plugin de Thonny, alors vous devriez sélectionner « Outils → Gérer les plugins… »\n" "\n" "Êtes-vous sûr de vouloir installer %s pour l'interpréteur ?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "Remarque : Il est possible qu'il y ait une autre version disponible qui soit compatible avec la version actuelle de Thonny. Cliquez sur le bouton « … » pour sélectionner la version à installer." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Plugin pour Thonny sans aucun pré-requis" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Il semble que vous essayez d'installer un plugin de Thonny déprécié (il ne spécifie pas la version de Thonny requise).\n" "\n" "Si vous le voulez vraiment, veuillez l'installer en ligne de commande." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Exigences non satisfaites" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "Ce paquet nécessite une version différente de Thonny :" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Si vous le voulez vraiment, veuillez l'installer en ligne de commande." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(Dans ce cas l'interpréteur de Thonny utilise le même interpréteur, afin que les deux boîtes de dialogue gèrent les mêmes paquets.)" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "Remarque : Vous devez redémarrer Thonny après avoir installé / mis à jour / désinstallé un plugin." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Plugins de Thonny" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Installation / Mise à jour / Rétrogradation avancée" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Version souhaitée" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Mettre à jour les dépendances" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Exigences :" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Erreur :" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Gérer les paquets…" #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Gérer les plugins…" #: thonny/plugins/replayer.py:354 #, fuzzy msgid "Open replayer..." msgstr "Ouvrir le relecteur…" #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Modifier le dossier de travail en dossier de script lors de l'exécution / débogage" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Afficher les appels de fonction (cadres) dans des fenêtres séparées" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "Décochez si vous souhaitez une expérience d'utilisation plus classique." #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "Ouvrir et fermer la vue de la pile automatiquement" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "Ouvre la vue de la pile au premier appel et la ferme lorsque le programme revient au cadre principal." #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "Autoriser l'entrée dans les bibliothèques en mode débogage (par ex. en dehors du dossier du script principal)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Peut ralentir le débogueur." #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Débogueur favori" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(utilisé lors du clic sur le bouton Déboguer dans la barre d'outils)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Port de Birdseye" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(redémarrez Thonny après avoir modifié ceci)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Exécuter et déboguer" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Émulation du terminal" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "prend en charge les styles et les couleurs ANSI simples" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Nombre maximum de lignes à conserver." #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "Remarque : De grandes valeurs peuvent réduire les performances !" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Longueur maximum de ligne avant de tronquer le texte" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Exécution du script courant dans le terminal" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Afficher Python REPL après la fin du programme" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Conserver la fenêtre du terminal ouverte après la fin du processus Python" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "Remarque : La fermeture automatique doit être activée dans les paramètres du terminal (Profils → Console → Lorsque la console se ferme)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Terminal" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "Thème de l'interface" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Thème de la syntaxe" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Police de l'éditeur" #. Ici IO désigne Input/Output soit Entrée/Sortie. Cela correspond à la police de la console (Shell). Il est donc plus approprié de traduire par "Police de la console" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "Police de la console" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Aperçu" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "Ceci est un commentaire" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "La réponse est" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "chaîne_non_fermée" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "bla, bla" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "Remarque : Certains éléments de style ne seront modifiés qu'après le redémarrage de Thonny !" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Entrez un nombre entier" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Thème et police" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Ouvrir le dossier programme de Thonny…" #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Ouvrir le dossier de données de Thonny…" #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Accueil" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Contenu de l'aide" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "appareil CircuitPyhton" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "appareil MicroPyhton" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Connectez votre appareil à l'ordinateur et sélectionnez le port correspondant ci-dessous" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "recherche du nom de votre appareil, « USB Serial » ou « UART »" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Si vous ne le trouvez pas, vous devriez d'abord installer un pilote USB correct." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Port" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Essayer de détecter le port automatiquement" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython (générique)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Imprimer…" #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Ouvrir la console du système…" #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Détails" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Installer depuis un fichier d'exigences" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Installer depuis un fichier local" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "Cette boîte de dialogue concerne la gestion des plugins de Thonny et leurs dépendances.\n" "Si vous souhaitez installer des paquets pour vos propres programmes, sélectionnez « Outils → Gérer les paquets… »" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (générique)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Indenter les lignes sélectionnées" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Désindenter les lignes sélectionnées" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Passer en mode normal" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "Veuillez vérifier que MicroPython a bien été installé dans votre micro:bit." #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "N'oubliez pas que main.py ne peut fonctionner que sans script principal intégré." #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "Installer la dernière version de MicroPython dans BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "Emplacement de micro:bit :" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Version qui sera installée :" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "veuillez patienter" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "Remarque : Tous les fichiers sur le micro:bit seront supprimés !" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Installation…" #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Terminé !" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Vous pouvez désormais fermer cette boîte de dialogue." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Micrologiciel" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "Ouvrir la boîte de dialogue pour installer ou mettre à jour MicroPython sur votre appareil" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "Impossible de trouver le disque « %s »." #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "Veuillez vérifier si le micro:bit est bien branché !" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Voulez-vous poursuivre et trouver le disque vous-même ?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "Impossible de trouver le dique « %s ». Voulez-vous le trouver vous-même ?" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Plusieurs disques « %s » trouvés. Voulez-vous en sélectionner un vous-même ?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Impossible de trouver un disque valide" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d éléments" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Déplacer vers la corbeille" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Déplacer vers la corbeille" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Supprimer" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Nouveau dossier" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Propriétés" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Espace de stockage" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "Chemin" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Propriétés du dossier" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Propriétés du fichier" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "octets" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "Taille" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Modifié le" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "Suppression de %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Déplacement de %s vers %s" #: thonny/code.py:203 msgid "Loading" msgstr "Chargement" #: thonny/code.py:297 msgid "Saving" msgstr "Enregistrement" #: thonny/running.py:1408 msgid "Working..." msgstr "Chargement…" #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Téléversement de %s vers %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Téléversement vers %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "Téléchargement de %s vers %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Téléchargement vers %s" thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/0000755000175000017500000000000013611777205021563 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/debuggers.rst0000644000175000017500000001142513611773167024272 0ustar annamaaannamaa00000000000000Utilisation des débogueurs ========================== Si vous voulez voir comment Python exécute votre programme pas-à-pas alors il faut le lancer en *mode de débogage* « joli » ou « vite fait ». On peut aussi le faire à l'aide d'`Œil d'oiseau (Birdseye) `_ et examiner les étapes d'exécution plus tard. Le mode « joli » ---------------- Ce mode est recommandé pour les néophytes. Commencez par sélectionner *Déboguer le script courant (joli)* depuis le menu *Lancer* ou en appuyant sur les touches Ctrl+F5 (`sous XFCE il faut utiliser Shift+Ctrl+F5 `__). Vous verrez que la première instruction du programme est mise en valeur et que rien d'autre ne se passe. Dans ce mode il faut notifier Thonny qu'on est prêt à laisser Python faire le pas suivant. Pour cela, vous avez deux option principales : * *Lancer → Sauter par dessus* (ou F6) pour faire de grands pas, c'est à dire qu'il exécute le code en évidence puis met en évidence la suite du code. * *Lancer → Sauter dedans* (ou F7) pour essayer de faire des pas plus petits. Si le code en évidence est composé de morceaux plus petits (déclaration ou instruction), alors la première est mis en valeur et Thonny attend votre commande suivante. Si on est arrivé à un composant du programme qui ne se décompose pas, (p. ex. un nom de variable), alors *Sauter dedans* se comporte comme *Sauter par dessus* c'est à dire qu'il exécute (ou évalue) le code. Si on a avancé pas-à-pas dans les profondeurs d'une fonction ou d'une expression et qu'on veut avancer plus vite, on peut alors utiliser *Lancer → Ressortir* qui exécute le code couramment mis en valeur et toutes les parties du programme sur le même niveau. Il y a une commande un peu similaire nommée *Reprendre*, qui lancera la commande sans s'arrêter à chaque pas jusqu'à ce qu'elle se termine (ou jusqu'au nouveau point d'arrêt, vois ci-dessous). Si par accident vous avez fait un trop grand pas et survolé une partie intéressante du code, on peut **défaire cette étape** en sélectionnant *Lancer → Un pas en arrière*. Thonny montrera l'état du programme tel qu'il était avant le dernier pas. Ensuite on peut continuer avec de petits pas et zoomer ce morceau de code. (Comment ça marche ? Même quand on réalise un grand pas, Thonny enregistre tous les états intermédiaires du programme, qu'il peut rejouer si on fait un pas en arrière.) Si on veut atteindre une portion spécifique du code, on peut aller plus vite en plaçant le curseur sur cette ligne et en sélectionnant *Lancer → Exécuter jusqu'au curseur*. Cela fait avancer Thonny automatiquement en mode pas-à-pas jusqu'à cette ligne. Vous pouvez reprendre la main à partir de là. Si vous avez activé les numéros de ligne dans l'éditeur (Outils → Options → Éditeur), alors on peut aussi utiliser des **points d'arrêt**. Quand on double-clique dans la marque gauche de l'éditeur près d'une ligne, un point apparaît. Alors, quand on lance le débogueur, il ne s'arrête pas avant la première ligne mais va jusqu'à la ligne marquée d'un point, qu'on nomme aussi un point d'arrêt. On peut placer autant de points d'arrêt dans le programme qu'il en faut. Les points d'arrêt peuvent être retirés en cliquant-double dessus. Le mode « vite fait » --------------------- Quand votre programme devient plus gros, on observe que le parcours en mode « joli » prend beaucoup de temps. C'est parce que les ornements (p. ex. la possibilité de faire de petits pas durant l'évaluation d'expressions et de revenir en arrière) nécessitent une machinerie lourde et lente. Avec *Débogage du script courant (vite)* on perd les ornements mais on peut avancer dans le programme beaucoup plus vite. On peut utiliser les mêmes commandes (sauf « Un pas en arrière » comme avec le débogueur en mode joli. C'est le style de débogage que la plupart des programmeurs professionnels utilisent d'habitude. Des styles différents pour la présentation de la pile d'appel ------------------------------------------------------------- Par défaut Thonny utilise des fenêtres empilées pour représenter la pile d'appels. Cela donne une bonne intuition du concept, mais ça devient encombrant à l'usage. C'est pourquoi, depuis la version 3.0 on peut choisir entre deux styles différents pour présenter la pile d'appels. Dans « Outils → Options → Débogueur » on peut passer à un style plus traditionnel avec une vue séparée pour présenter les trames d'appels. Notez que les deux styles sont utilisables, avec chacun des deux modes de débogage. L'œil d'oiseau (Birdseye) ------------------------- La commande *Débogage du script courant (Œil d'oiseau)* est expliquée dans une `page séparée `_ thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/debugging.rst0000644000175000017500000001355713611773167024266 0ustar annamaaannamaa00000000000000Les techniques de débogage ========================== Si votre programme ne fonctionne pas, pas de panique ! Vous avez plusieurs possibilités pour corriger la situation. Par exemple : * La faire corriger par quelqu'un d'autre ; * Changer *quelque chose* dans le code et réessayer ; * Approcher le problème en deux phases : 1) diagnostiquer le problème et 2) le réparer. Demander de l'aide peut être une très bonne idée, mais elle ne vous procurera pas cette douce sensation de réussite. De toute façon, c'est mieux de ne pas y recourir sans avoir d'abord tenté quelque chose vous-même. Si vos programmes sont petits, vous pourriez toucher le jackpot en changeant quelque chose au hasard et en recommençant (plusieurs fois), mais vous allez perdre même si vous gagnez, comme vous n'en aurez rien appris. Si vous voulez devenir bon en programmation, il vous faut vraiment approcher le problème de façon plus systématique. Entre autres choses, ça signifie que vous devez trouver la raison pour laquelle votre programme dysfonctionne avant d'essayer de le corriger. Le processus consistant à trouver la source du problème se nomme *débogage*. Tracer le flux du programme / penser en même temps que Python ------------------------------------------------------------- Le plus souvent votre programme n'est pas entièrement mauvais. Il peut y avoir une faute de frappe quelque part ou vous avez manqué ou mal compris quelque chose. *N.B. ! Ne prenez pas l'habitude de penser que Python vous a mal compris -- c'est une machine qui ne cherche pas à vous comprendre*. La clé du débogage c'est de trouver précisément où et quand vos conceptions du comportement du programme divergent du comportement réel. Si votre programme affiche une réponse finale fausse cela vous dit quelque chose au sujet du comportement du programme, mais ce n'est généralement pas assez pour localiser le problème précisément. Il faut aussi vérifier lesquelles des **étapes intermédiaires** sont en accord avec vos conceptions et lesquelles non. Une technique évidente (et très utile) est d'ajouter des **directives d'affichage en plus** dans le code, qui vous diront où en est Python et ce qu'il a fait jusque-là, par exemple : .. code:: print("amis avant la boucle-for", amis) N.B. ! Quelquefois il faut introduire de nouvelles variables et décomposer des expressions complexes en parties plus simples afin d'afficher des informations plus détaillées. Bien que le débogage à base d'affichages soit utilisé aussi par des professionnels (il leur arrive de l'appeler *logging*, journalisation), il y a une alternative, qui est plus confortable dans la plupart des cas. Elle s'appelle **avancer pas-à-pas dans le code** et c'est le pain béni de Thonny. Allez au chapitre `Utilisation des débogueurs `_ pour en apprendre plus. Revue du code ------------- Une autre technique utile est la revue de code. Cela revient à peu près à tracer le flux du programme, mais on le fait dans sa tête et on essaie de visualiser une figure plus grande au lieu de suivre des petits pas. Voyez chacune des expressions de votre code et essayez de comprendre son rôle et comment elle est reliée à votre tâche. Pour chaque **variable** demandez-vous : * Est-ce que le nom de la variable dit ce qu'elle fait ? Vaut-il mieux utiliser un nom au singulier ou au pluriel ? * Quel type de valeurs peut se trouver dans cette variable ? Chaînes, entiers, listes de chaînes, liste de flottants, ... ? * Quel est le rôle de cette variable ? est-elle prévue pour être mise à jour de façon répétée de façon à contenir quelque information utile ? est-elle prévue pour utiliser la même information à plusieurs endroits et éviter le copier-coller ? Quoi d'autre ? Pour chaque **boucle** demandez-vous : * Comment savez-vous que la boucle est nécessaire ? * Combien de fois le corps de la boucle doit-il être exécuté ? De quoi cela dépend-il ? * Quel code devrait être dans la boucle et quel code devrait être dehors ? * Que faut-il faire avant la boucle et que faut-il faire après ? Pour chaque **expression** complexe demandez-vous : * Dans quel ordre devraient se faire les étapes d'évaluation de cette expression ? Est-ce que Python fait ainsi ? En cas de doute, utilisez le débogueur ou introduisez des variables auxiliaires et décomposez l'expression en morceaux plus petits. * Quel type de valeur est censé sortir de cette expression ? Chaîne ? Liste de chaînes ? Il vous manque peut-être des parties importantes dans votre programme : * Votre tâche nécessite-t-elle de traiter des situations différente différemment ? Si oui, vous avez probablement besoin d'une construction conditionnelle (**if**) ; * Votre tâche nécessite-t-elle de faire quelque chose plusieurs fois ? Si oui, il vous faut probablement une boucle. Encore perdu ? -------------- « Trouvez-vous l'emplacement ou vos suppositions deviennent fausses » -- ceci est plus simple à dire qu'à faire. Dans le cas de programmes complexes c'est facile d'arriver à la situation où vous n'êtes plus du tout sûr de savoir ce que vous supposez ni pourquoi vous avez commencé ce fichu programme. Dans ce cas c'est utile de simplifier votre tâche autant que possible et d'essayer d'implémenter les problèmes plus simples en premier. Prenez un autre éditeur, et soit recommencez depuis le début, soit copiez le code existant en jetant tout ce qui n'est pas essentiel à votre problème. Par exemple, vous pouvez supposer que l'utilisateur est coopératif et saisit toujours de « bonnes » données. Si la tâche implique de faire quelque chose de façon répétitive, alors jetez la partie « répétitive », si la tâche implique une condition complexe pour faire quelque chose, rendez la condition plus simple, etc. Après avoir résolu le problème plus simple vous serez bien mieux équipé pour résoudre aussi la tâche d'origine aussi bien. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/birdseye.rst0000644000175000017500000000331313611773167024126 0ustar annamaaannamaa00000000000000L'œil d'oiseau (Birdseye) ========================= L'Œil d'oiseau est un débogueur Python vraiment *cool* créé par Alex Hall, qui enregistre les valeurs des expressions quand le programme fonctionne et vous laisse les explorer quand le programme se termine. Voir `https://birdseye.readthedocs.io `_ pour en savoir plus. L'Œil d'oiseau n'est pas installé par défaut, mais il est facile de l'installer via *Outils → Gérer les greffons*. Il faut installer la paquet nommé ``birdseye``. L'Œil d'oiseau fonctionne d'une façon différente des `débogueurs intégrés à Thonny `_. Quand on exécute son programme avec *Lancer → Débogage du script courant (Œil d'oiseau)*, l'exécution est un peut plus longue qu'à l'habitude, mais autrement le programme fonctionne exactement comme si on l'avait exécuté avec *Lancer le script courant*. Ça signifie que les points d'arrêt sont ignorés et qu'on ne peut pas se déplacer pas-à-pas dans le programme. Mais quand le programme se termine, Thonny ouvre une page web (servie localement par Œil d'oiseau), qui vous permet de creuser le processus d'exécution et d'apprendre comment ils résultats finaux ont été composés à partir des valeurs intermédiaires. N.B. ! Quand vous utilisez Œil d'oiseau dans Thonny il n'y a pas besoin d'importer ``birdseye.eye`` ou de l'utiliser pour décorer vos fonctions. Thonny exécute Œil d'oiseau d'une façon telle qu'il enregistre des informations pour toutes les fonctions. Le serveur local utilise le port 7777 par défaut. Si celui-ci est utilisé par une autre application, alors on peut configurer un autre port (Outils → Options → Débogueur) et redémarrer Thonny. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/flask.rst0000644000175000017500000000302613611773167023421 0ustar annamaaannamaa00000000000000Développement Web avec Flask ============================ `Flask `__ est une infrastructure populaire pour créer des applications web avec Python. Les tutoriels Flask indiquent de lancer les programmes Flask en tapant certaines commandes dans un Terminal, mais ça peut intimider certains débutants. Thonny essaie de rendre les choses plus faciles et permet de lancer les programmes Flask comme n'importe quel autre programme (avec un simple F5). S'il détecte que vous lancez un programme Flask, il le lance avec quelques lignes de code en plus, qui démarrent le serveur de développement avec les réglages qui vont bien. Détails ------- Thonny lancera le serveur de développement approximativement comme ceci : .. code:: os.environ["FLASK_ENV"] = "development" app.run(threaded=False, use_reloader=False, debug=False) ``threaded=False`` est utilisé car le débogueur de Thonny ne supporte que les programmes à un seul fil (thread), ``use_reloader=False`` est utilisé car `le rechargement automatique n'est pas fiable quand Flask est lancé ainsi `_ et ``debug=False`` est utilisé car cela semble causer moins d'erreurs "Address already in use". Si vous voulez un plus grand contrôle sur les réglages, alors il vous faut lancer la méthode ``run`` par vous-même, comme ceci, par exemple : .. code:: ... if __name__ == "__main__": app.run(port=5005, threaded=False, use_reloader=True, debug=True) Dans ce cas Thonny n'ajoutera rien à votre code. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/plotter.rst0000644000175000017500000000477413611773167024025 0ustar annamaaannamaa00000000000000Le grapheur =========== Le grapheur est un greffon pour le Shell, qui en extrait les nombres venus du programme et les affiche comme une courbe. Il peut être utile pour observer des données de capteurs en direct venant de périphériques ou même pour analyser des données statiques (si vous hésitez à utiliser des outils plus sérieux). Il est inspiré du `Mu Python editor `__. Vous pouvez l'ouvrir depuis le menu « Afficher » ou depuis le menu contextuel du Shell. Par exemple essayez le programme suivant (on peut l'arrêter avec Ctrl+C ou avec le bouton Arrêter/Relancer de la barre d'outils) : .. code:: from time import sleep from random import randint p1 = 0 while True: p1 += randint(-1, 1) p2 = randint(-10, 10) print("Marche aléatoire :", p1, " juste aléatoire:", p2) sleep(0.05) Quand on le lance avec le Grapheur ouvert, on voir un graphique en ligne avec deux courbes qui défilent. Chaque colonne du graphique correspond à une ligne dans le Shell. La colonne le plus à droite dans le graphique correspond toujours à la ligne visible en bas du Shell, même quand on arrête le programme et qu'on se déplace dans le texte du Shell. Le grapheur commence à tracer des courbes dès qu'il détecte au moins deux lignes consécutives contenant le même motif de nombres et de texte d'accompagnement. Les nombres sont représentés sous forme de courbes et le texte d'accompagnement devient la légende dans le coin en bas à droite du Grapheur. La vitesse de l'animation ------------------------- À moins que vous ne produisiez un nombre fixe de lignes, c'est une bonne idée d'éviter de noyer le Shell et le Grapheur sous les données. C'est pourquoi l'exemple ci-dessus fait une petite pause (``sleep(0.05)``) avant d'afficher la ligne suivante. Intervalle de l'axe-Y --------------------- Le Grapheur tente de détecter un intervalle adapté pour votre courbe sans qu'il soit nécessaire de le changer trop souvent. Pour cette raison, il augmente l'intervalle si besoin est, mais ne le diminue qu'au début d'une nouvelle série. Si certaines données extraordinaires rendent l'intervalle trop grand, on peut le rétrécir manuellement en attendant que les données trop grande sortent de la figure et en cliquant sur le Grapheur. Si vous voulez rendre l'intervalle plus grand (ou juste comparer vos valeurs à d'autres), il suffit simplement d'inclure une ou des constantes adéquates dans vos lignes de données, p.ex. : ``print(0, measure1, measure2, 100)``. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/program_arguments.rst0000644000175000017500000000241513611773167026056 0ustar annamaaannamaa00000000000000Lancer les programmes avec des arguments en ligne de commande ============================================================= Quand nous éditez *mon_programme.py* et pressez la touche F5, Thonny construit une commande magique ``%Run mon_program.py`` et l'envoie au shell, qui demande à la tâche de fond de Thonny de lancer ce script. Quand on utilise le shell et qu'on récupère la commande ``%Run`` (avec la flèche vers le haut), on peut y ajouter *des arguments en ligne de commande*. Par exemple on peut remplacer cette commande par ``%Run mon_programme.py argument1 argument2`` et appuyer sur Entrée. Quand on lance le programme ainsi, il est possible d'accéder aux arguments à l'aide de ``sys.argv``: .. code:: import sys print(sys.argv) Modifier les arguments en ligne de commande ------------------------------------------- S'il faut utiliser le même ensemble d'arguments plusieurs fois, ça peut devenir ennuyeux de reconstruire le ``%Run`` à la main. Dans ce cas, vous pouvez cocher **Arguments du programme** dans le **menu Afficher**. Cela ouvre un petit champ de saisie près des boutons de la barre d'outils. Ensuite, tout ce qu'on tape dans cette zone de saisie est ajouté au bout du ``%Run `` à chaque fois qu'on presse la touche F5. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/errors.rst0000644000175000017500000000447413611773167023645 0ustar annamaaannamaa00000000000000Comprendre les erreurs ====================== Si votre programme provoque des erreurs ou des résultats inadéquats ne tentez pas de réparer quoi que ce soit avant d'avoir compris le problème. On peut en lire plus dans `une autre page `__, ici vous ne trouverez qu'un rapide revue pour faciliter la mise en place des idées. Êtes-vous effaré ? ------------------ Il ne faut pas ! Les messages d'erreur sont faits pour aider. Si vous recevez un message d'erreur, ça ne veut pas dire que vous êtes mauvais. Et non, vous n'avez pas cassé l'ordinateur. Bien que les messages d'erreur puissent ressembler à un sac de nœuds à première vue, avec de la pratique il est possible d'en tirer des informations utiles. À quel emplacement du code a eu lieu l'erreur ? ----------------------------------------------- Les messages d'erreur dans Thonny ont des liens qui vous amènent à l'emplacement du code qui a causé l'erreur. Dans le cas de plusieurs liens, le dernier est généralement le plus pertinent. Si l'erreur est arrivée dans une fonction, alors le message a plusieurs liens. Essayez de cliquer sur ceux-ci un par une, du haut vers le bas, et vous verrez comment Python est arrivé à l'emplacement de l'erreur. Un tel ensemble de liens se nomme *la trace de la pile*. Que signifie l'erreur ? ----------------------- La dernière ligne du bloc d'erreur dit quel a été le problème pour Python. Quand vous essayez de comprendre le message, n'oubliez pas le contexte et essayez d'associer certaines parties du message avec l'emplacement lié dans le code. De temps en temps l'Assistant de Thonny peut expliquer l'erreur en termes plus simples, et parfois il faut effectuer une recherche sur Internet pour ce message (n'oubliez pas d'ajouter le mot-clé "Python" pour la recherche). Qu'y avait-il dans les variables au moment de l'erreur ? -------------------------------------------------------- Ouvrez la vue des variables et voyez par vous-même ! Si l'erreur s'est produite dans une fonction on peut voir les variables locales en cliquant les liens dans la trace de la pile. Comment le programme est-il arrivé dans cet état ? -------------------------------------------------- Voir `la page au sujet du débogage `_ or `la page au sujet de l'utilisation des débogueurs de Thonny `_. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/packages.rst0000644000175000017500000000561313611773167024103 0ustar annamaaannamaa00000000000000Installation de paquets de tierces parties ========================================== Thonny a deux options pour l'installation de paquets de tierces parties. Avec pip dans l'interface graphique ----------------------------------- Depuis le menu « Outils », sélectionnez « Gérer les paquets ... » et suivez les instructions. Avec pip en ligne de commande ----------------------------- #. Depuis le menu « Outils », sélectionnez « Ouvrir un Shell système ... ». Vous devriez avoir un nouveau terminal, qui présente le nom correct de la commande *pip* (normalement ``pip`` ou ``pip3``). Par la suite on supposera que le nom de la commande est ``pip``. #. Entrez ``pip install `` (p. ex. ``pip install pygame``) et tapez Entrée. Vous devriez voir *pip* qui télécharge et installe le paquet puis affiche son message de succès. #. Fermez le terminal (facultatif) #. Revenez à Thonny #. Réinitialisez l'interpréteur en sélectionnant « Arrêter/relancer » depuis le menu « Lancer » (ceci est nécessaire la première fois que vous faite l'installation pip) #. Commencez à utiliser la paquet. Utiliser des paquets Python scientifiques ========================================= La distribution Python qui vient avec Thonny ne contient pas de bibliothèques de programmation scientifique (p. ex. `NumPy `_ et `Matplotlib `_). Les versions récentes de la plupart des paquets Python scientifiques (p. ex. numpy, pandas et matplotlib) sont outillés pour les plate-formes populaires si bien que vous pouvez la plupart du temps les installer avec pip mais au cas où il y a des problèmes, vous pouvez utiliser Thonny avec une distribution Python séparée prévue pour le calcul scientifique (p. ex. `Anaconda `_, `Canopy `_ ou `Pyzo `_). Exemple: Utilisation d'Anaconda ------------------------------- Allez à https://www.continuum.io/downloads et téléchargez une distribution binaire appropriée pour votre plate-forme. La plupart du temps vous voudrez un installeur graphique et une version 64-bits (on peut avoir besoin d'une version 32-bits avec un très vieux système). **Notez que Thonny ne supporte que Python3, assurez-vous bien de choisir la version pour Python 3 d'Ananconda**. Installez-la et trouvez où il installe l'exécutable Python (*pythonw.exe* sous Windows et *python3* ou *python* sous Linux et Mac). Dans Thonny ouvrez « Outils » et sélectionnez « Options ... ». Dans le dialogue d'options ouvrez l'onglet « Interpréteur », cliquez « Sélectionner l'exécutable » et désignez l'emplacement de l'exécutable Python d'Anaconda. Après avoir fait ça, la prochaine fois que vous relancerez votre programme, il utilisera le Python d'Anaconda et toutes les bibliothèques installées là sont disponibles. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/shell.rst0000644000175000017500000000767213611773167023443 0ustar annamaaannamaa00000000000000Le Shell ======== Le Shell est le moyen principal pour lancer et communiquer avec votre programme. Il ressemble pour l'essentiel à la boucle REPL (Read-Evaluate-Print Loop) officielle de Python, mais il y a quelques différences et propriétés supplémentaires. Les commandes Python -------------------- Tout comme l'invite REPL officielle de Python, le Shell de Thonny accepte des expressions et des commandes Python, qu'elles soient sur une seule ligne ou sur plusieurs. Si on presse la touche Entrée, Thonny utilise quelques heuristiques pour prédire si on veut lancer la commande ou continuer à taper la commande sur la ligne suivante. Si vous voulez lancer la commande mais que Thonny vous offre une nouvelle ligne, vérifiez si vous avez oublié de refermer quelques parenthèses. Les commandes magiques ---------------------- Si on sélectionne "Lancer => Lancer le script courant" ou qu'on presse la touche F5, on voit que Thonny insère une commande commençant par ``%Run`` dans le Shell. Les commandes qui commencent par ``%`` sont appelées *commandes magiques* (tout comme dans `IPython `_ et elles réalisent certaines actionnes, qui ne peuvent pas (facilement) s'exprimer par des commandes Python. Les commandes magiques de Thonny ont d'habitude des commandes correspondantes dans le menu si bien qu'il est inutile de les écrire à la main. Les commandes système --------------------- Si on doit rapidement lancer une simple commande système il n'est pas nécessaire de démarrer un Terminal. Il suffit de préfixer la commande par ``!`` (p. ex. ``!pytest mon-script.py``) et de la saisir dans le Shell de Thonny. L'historique des commandes -------------------------- Si on veut relancer la même commande ou presque plusieurs fois, il n'est pas nécessaire de la retaper à chaque fois -- on utilisera la flèche vers le haut pour récupérer la commande précédente dans l'historique. Une nouvelle action sur la même touche récupère le commande précédente et ainsi de suite. On utilise la touche flèche vers le bas pour se déplacer dans l'historique en sens opposé. Sortie colorisée ---------------- Si votre Shell est en mode émulation de Terminal (voir Outils => Options => Shell), on peut utiliser des `codes ANSI `_ pour produire une sortie colorisée. Essayez l'exemple suivant : .. code:: print("\033[31m" + "Red" + "\033[m") print("\033[1;3;33;46m" + "Texte brillant et gras, italique, en jaune sur fond cyan" + "\033[m") Vous pouvez avoir envie d'utiliser un paquet comme `colorama `_ pour produire Les codes couleur. Réécrire par-dessus les lignes de sortie ---------------------------------------- Les bons émulateurs de terminal supportent des codes ANSI autorisant l'écriture à une position arbitraire sur l'écran du terminal. Le Shell de Thonny ne peut pas en faire autant, mais il supporte cependant quelques trucs et astuces. Essayez le programme suivant : .. code:: from time import sleep for i in range(100): print(i, "%", end="") sleep(0.05) print("\r", end="") print("Terminé !") Le truc est d'utiliser le caractère ``"\r"``, qui fait revenir le curseur de sortie au début de la ligne courante, si bien que les caractères suivants seront affichés en écrasant le texte précédent. Notez bien l'usage de ``print(..., end="")`` pour éviter de créer une nouvelle ligne. Le cousin de ``"\r"`` est ``"\b"``, qui déplace le curseur de sortie à gauche d'un caractère. Cela ne fait rien s'il est déjà à la première position de la ligne. Émettre un son -------------- Quand le Shell est en mode émulation de terminal, on peut faire sonner (ou émettre un tintement) en sortant un caractère ``"\a"``. Mettre en graphique une série de nombres ---------------------------------------- On peut visualiser les séries de nombres envoyées vers le Shell à l'aide du `Grapheur `_. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/modes.rst0000644000175000017500000000176113611773167023434 0ustar annamaaannamaa00000000000000Différents modes ================ *Outils → Options → Général* permet de régler l'interface utilisateur de Thonny selon un des trois modes différents. Mode ordinaire -------------- C'est le mode par défaut. Il n'y a pas grand-chose à en dire. Mode simple ----------- Dans ce mode les menus sont cachés et la vue des Variables est automatiquement ouverte. On peut utiliser un petit lien dans le coin en haut à droite pour revenir au mode ordinaire. Mode expert ----------- Ce mode ressemble beaucoup au mode ordinaire, mais offre quelques fonctionnalités de plus, utiles pour enseigner. * Le menu Afficher dispose d'un item *Plein écran* pour mettre Thonny en mode plein écran. * Quand on double-clique sur l'onglet d'un éditeur ou d'une vue, cela permet de la maximiser ; on peut revenir à la taille d'origine en double-cliquant l'onglet à nouveau. * Le menu des Outils gagne un item de plus *Ouvrir et rejouer ...* qui permet de rejouer les journaux d'action de l'utilisateur. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/index.rst0000644000175000017500000000141513611773167023430 0ustar annamaaannamaa00000000000000Sujets spécifiques ================== * `Utilisation des débogueurs `_ * `Utilisation des paquets de tierces parties `_ * `Ancrer les fenêtres utilisateurs `_ * `Support spécial pour les programmes Turtle `_ * `Spécifier des arguments de programme `_ * `Mode simple et mode expert `_ * `Le Shell `_ * `Le Grapheur `_ * `L'Œil d'oiseau (Birdseye) `_ * `Le développement web avec Flask `_ Sujets généraux =============== * `Gérer les erreurs `_ * `Conseils généraux pour le débogage `_ En Ligne ======== Vous trouverez plus d'information sur le wiki de Thonny : https://github.com/thonny/thonny/wiki. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/turtle.rst0000644000175000017500000000120613611773167023636 0ustar annamaaannamaa00000000000000Support spécial pour les programmes Turtle ========================================== Quand on développe des programmes avec le module ``turtle``, Thonny offre le support suivant : * On peut faire sans les appels de ``mainloop``, ``done`` ou ``exitonclick`` dans le script (Thonny s'occupera de garder la fenêtre Turtle interactive). Cela permet de créer des parts de son dessin à l'aide d'un script et de continuer à ajouter des propriétés à l'aide du shell. On peut aussi faire tout le dessin à partir du shell. * On peut `ancrer la fenêtre Turtle `_, afin qu'elle reste bien visibles tant qu'on travaille sur le script. thonny-3.2.7/thonny/locale/fr_FR/HELP_CONTENT/dock.rst0000644000175000017500000000237013611773167023242 0ustar annamaaannamaa00000000000000Ancrer les fenêtres utilisateur =============================== Quand on développe son programme Turtle (ou utilisant Tkinter), on peut vouloir regarder la fenêtre de l'essai précédent tout en réparant quelques lignes de code. Si on a des écrans de grande taille ou nombreux, ce n'est pas difficile de placer cette fenêtre près de celle de Thonny, mais au lancement suivant, le gestionnaire de fenêtre peut la replacer n'importe où et il faut remettre en place à nouveau les fenêtres. **Ancrer les fenêtres utilisateur** dans le **menu Lancer** est prévu pour vous aider dans cette situation. Si vous cochez cette option et que vous lancez votre programme Tkinter, Thonny réaliser la magie suivante : * Il se souvient des emplacements de vos fenêtres. Les fois suivantes il place les fenêtres à la même position. * Il fait en sorte que votre fenêtre reste au-dessus même si on clique sur la fenêtre Thonny pour commencer à modifier le code. En fait, après que la fenêtre Tkinter est apparue, Thonny met automatiquement le focus sur sa propre fenêtre si bien que vous pouvez continuer à éditer le code sans utiliser la souris. Quand on a fini, il suffit d'appuyer à nouveau sur F5 et l'ancienne fenêtre est remplacée par la nouvelle. thonny-3.2.7/thonny/locale/lt_LT/0000755000175000017500000000000013611777205017661 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/lt_LT/LC_MESSAGES/0000755000175000017500000000000013611777205021446 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/lt_LT/LC_MESSAGES/thonny.mo0000644000175000017500000006346513611773167023343 0ustar annamaaannamaa00000000000000V ||}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/; ;s;&L<5s<$< < <.<9=5Q=-=J=<>=> Y>d>m>~>>>>1?D?Z?j?*?? ???@P@j@@ @@ @ @ @@@ AA AZA B B 9BEB^B7yBB'B"BC 0C:CCC%^C&C%CACD$'DLD UD`DoDxDD:D D)D!E:E TEIbEEEEEE EEF."FQFXFgFoFxFFFF!FFFFFGG&G-GKG eGpGGG8iH HHHLH II9$I"^I!II IIIIILJaJ6KGKZKyKKKK1K LL !L-L>LRLEULLLLLLL LM$M5MNyNB O/cOOOO O:O+P@P\PrPPPPP(PP/Q2QKQ=R+RORFSMSf]SS SSSGSI?T#T$T1TU#UF>U UhU UV VV V'V Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: lt %d įrašų(Šiuo atveju Thonny tarnybinė dalis naudoja tą patį interpretatorių, abu dialogai valdo tuos pačius paketus.)(pakeitę paleiskite Thonny iš naujo)(naudojamas spustelint Tinkinti įrankinės mygtuką)Speciali virtuali aplinka (pasenusi)Apie BirdseyeApie ThonnyDetalus įdiegimas, atnaujinimas, pasendinimasLeisti kodo užbaigimą su tab klavišu komand. eilutėjeLeisti kodo užbaigimą su tab klavišu redaktoriuoseLeisti tik vieną paleistą Thonny vienu metuLeidžia įlipti į bibliotekas (t.y. už pagrindinio scenarijaus aplanko)Alternatyvus Python 3 interpretatorius arba virtuali aplinkaAr tikrai norite išdiegti?AsistentasAutoriusAuto-užbaigimasAtgalAtgal į esamą kadrąBlogas aplankasBirdseye yra Python tinkinimo programa, kuri turi būti įdiegta atskirai. Ar norite atverti pagalbos puslapį ir sužinoti daugiau?Birdseye prievadasPeržiūrėti paketusKlaidų sekimasDar negalima uždarytiSąraše nepavyko rasti paketo pavadinimo:Nepavyko rasti tinkamo diskoAtšauktiAtšaukti procesą?Skirti didžiąsias raidesPakeisti šrifto dydįPakeisti darbinį aplanką į scenarijų aplanką spustelint Paleisti / TinkintiCircuitPython (bendras)CircuitPython įrenginysIšvalytiIšvalyti komand. eilutęSpustelėkiteSpragtelti UždarytiUždaryti visusUždaryti kitusUžkomentuotiKonfigūracija atnaujinta. Perkraukite Thonny norėdami dirbti numatytame režime. (Žiūrėkite 'Įrankiai → Nustatymai → Bendra' jei apsigalvosite.)PatvirtinimasPrijunkite savo įrenginį prie kompiuterio ir pasirinkite atitinkamą prievadą apačiojeKopijuotiKopijuoti į iškarpinęKopijuojamaKopijuojama %s į %sNepavyko rasti disko '%s'.Nepavyko rasti disko '%s'. Ar norite surasti jį patys?Nepavyko rasti paketo PyPINepavyko rasti paketo informacijos PyPISukurti naują virtualią aplinkąKuriama virtuali aplinkaIškirptiTinkintiTinkinti esamą scenarijųTinkinti esamą scenarijų (Birdseye)Tinkinti esamą scenarijų (greičiau)Tinkinti esamą scenarijų (detaliau)Tinkinimo režimas (pateikia detalesnius diagnostinius išrašus)Sumažinti šriftąAtitraukti pasirinktas eilutes atgalIšrintiTrinama %sNorima versijaDetalėsAplanko nustatymaiišjungti pranešimų garsąIšjungti tikrinimai (vienas identifikatorius per eilutę)AtsijungtiAr norite tęsti ir surasti diską patys?Ar tikrai norite perrašyti '%s'?Prisegti vartotojo langusDokumentacijaNepamirškite, kad main.py veikia tik neįterpus pagrindinio scenarijaus.Baigta!ŽemynAtsisiųsti į %sAtsisiunčiama %s į %sKeistiRedaktoriusRedaktoriaus šriftasĮveskite skaičiųĮveskite tekstą, kuris turi būti pakeistas.KlaidaKlaidos kodas:Klaida:ĮvykiaiIšimtisIšeitiIšeiti iš ThonnyIšskleisti komand. eilutėjeEksportuoti panaudos žurnalą...FailasFailo nustatymaiFailaiRastiRasti ir pakeistiRasti PyPI paketąRasti:Programinė apratinė įrangaPereiti prie redaktoriausPereiti įPereiti prie komand. eilutėsTeksto dydžio keitimo režimasDėl greitaveikos komand. eilutė labai ilgų eilučių nerodo pilnai (žiūrėkite Įrankiai → Nustatymai → Komand. Eilutė). Čia jūs galite dirbti su originaliu teksto fragmentu.Rasti keli '%s' diskai. Ar norite pasirinkti vieną jų?Visas ekranasBendraKrūvaĮjungtas krūvos režimas. Uždarykite krūvos vaizdą norėdami išjungti.PagalbaPagalbos turinysParyškinti esamą eilutę (reikia perkrauti redaktorių)Paryškinti vietinius kintamuosiusParyškinti atitinkančius vardusParyškinti skliausteliusParyškinti sintaksės elementusNamaiPuslapisĮDIEGTIĮvesties-išvesties šriftasJei jo negalite rasti, gali reikėti pirma įdiegti tinkamą USB tvarkyklę.Jei nežinote iš kur gauti paketą greičiausia norėsite paieškoti jo Python Package Index. Pradėkite įvesdami paketo pavadinimą paieškos lauke ir spustelėdami ENTER.Jei vis dar jo norite, sudiekite iš komand. eilutės.Padidinti šriftąAtitraukti pasirinktas eilutesĮdiegtiSudiegti iš PyPISudiegti iš lokalaus failoSudiegti iš reikalavimų failoSudiegti vėliausią MicroPython į BBC micro:bitSudiegta į:Sudiegta versija:Diegiama...InterpretatoriusPertraukti veikimąĮPalikti terminalo langą atvirą po to kai pasibaigia Python procesasŽinomi interpretatoriaiKalbaVėliausia stabili versijaVėliausia versijaPakrautiKraunamaSurasti kitąVieta: Sekti programos panaudojimo įvykiusAtrodo, kad jūs bandote sudiegti su Thonny susijusį paketą. Jei norėjote sudiegti Thonny įskiepį, pasirinkite 'Įrankiai → Valdyti įskiepius...'. Ar tikrai norite sudiegti %s tarnybinei daliai?Atrodo, kad jūs bandote sudiegti pasenusį Thonny įskiepį (jis nenurodo reikalingos Thonny versijos). Jei vis dar jo norite, sudiekite jį iš komand. eilutės.Pagamintas Estijos Tartu universitete su pagalba iš atviro-kodo bendruomenės, Raspberry Pi Foundation ir Cybernetica ASĮsitikinkite, kad MicroPython buvo sudiegtas į jūsų micro:bit.Įsitikinkite, kad jūsų micro:bit prijungtas!Valdyti paketus %sValdyti paketus...Valdyti įskiepius...PadidintiDidžiausias eilutės fragmento ilgis prieš suspaudžiantDidžiausias paliekamas eilučių skaičiusGali sulėtinti tinkinimą.MicroPython (bendras)MicroPython įrenginysPakeistaPerkelti į ŠiukšlinęPerkelti į ŠiukšlesPerkeliama %s į %sNB! Visi failai micro:bit bus ištrinti!NB! Automatinis uždarymas turi būti įgalintas Terminalo nustatymuose (Profiliai → Komand. eilutė → Kai išeinama iš komand. eilutės)NB! Didelės reikšmės gali paveikti veikimą!NB! Perkraukite Thonny pakeitę šiuos nustatymus!NB! Kai kurie stiliaus elementai išvaizdą pakeičia tik perkrovus Thonny!NB! Gali būti kita versija, kuri palaiko esamą Thonny versiją. Spustelkite '...' mytuką ir pasirinkite versiją, kurią norite sudiegti.NB! Thonny palaiko Python 3.5 ir vėlesniusNB! Jums reikia perkrauti Thonny sudiegus, atnaujinus arba išdiegus įskiepį.NaujasNaujas aplankasNauji paketai taip pat bus sudiegti į šį aplanką. Kitos vietos turi būti valdomos kitais būdais.Kitas objektasUžrašaiGeraiObjektų peržiūraAtverti Asistentą automatiškai, kai jis turi perspėjimų jūsų kodeAtverti Asistentą automatiškai kai programa nustoja veikti su išimtimiAtverti Thonny duomenų aplanką...Atverti Thonny programos aplanką...Atverti ir uždaryti dėklo vaizdą automatiškaiAtverti kartotuvą...Atverti sistemos komand. eilutę...Atverti dialogą sudiegti ar atnaujinti MicroPython jūsų įrenginyjeAtverti...Atidaro dėklo vaizdą pirmo iškvietimo metu ir uždaro jį kai programa grįžta į pagrindinį kadrąNustatymai...IšApžvalgaViršPerrašyti?Perrašoma tema '%s'PaketasPaketas '{}' reikalingas norint sudiegti ir išdiegti kitus paketus.Paketų aplankasĮklijuotiKeliasAtlikti MyPy tikrinimusAtlikti pasirinktus Pylint tikrinimusPatikrinkite rašybą!BraižyklėBraižyklė parodo numerių seriją išspausdintą į komand. eilutęPrievadasPageidautinas tinkintuvasParodyti Python REPL pasibaigus programaiPeržiūraPraėjęs objektasSpausdinti...Programos argumentaiProgramos parametrai:Programos medisNustatymaiPyPI puslapisPygame Zero režimasPython interpretatoriaiIšeitiTikrai išdiegti?Paskutiniai atverti failaiRekomenduojamas ilgiausias eilutės ilgis (Nustatykite į 0 norėdami išjungti paraštės liniją)PakartotiAtnaujintiNumatytasis režimasPervardinti...Atverti visus failus iš paskutinės sesijosPakeistiPakeisti visusPakeisti su:Pakeisti + rastiPranešti apie problemasReikalaujaReikalauja:TęstiPaleistiPaleisti ir TinkintiPaleisti / tęstiPaleisti esamą scenarijųPaleisti esamą scenarijų terminalePaleisti iki žymeklioEsamas scenarijus leidžiamas terminaleIšsaugotiIšsaugoti kaip...Išsaugoti kopiją...SaugojamaDetalės pagalbojePasirinkti viskąPasirinkti viskąPasirinkite tuščią aplanką naujai virtualiai aplinkaiPasirinkti esamą, arba sukurti naują aplankąPasirinkite interpretatoriųPasirinktas aplankas nėra tuščias. Pasirinkite kitą arba atšaukite.Nusiųsti EOF / Minkštas perkrovimasKomand. eilutėRodyti braižyklęRodyti funkcijų iškvietimus (kadrus) atskiruose languoseRodyti eilučių numeriusDydisSuspaustas tekstas (%d ženklų)DėklasPradėkite pasirinkdami paketą kairėje.Eiti atgalLipti gilynIšliptiPerliptiSustabdytiSustabdyti/Perkrauti tarnybinį servisąSaugojimo vietaSuvestinėPerjungti į numatytą režimąSintaksės temaTaikinys:TerminalasTerminalo emuliacijaAtsakymas yraProcesas dar veikia. Ar tikrai norite atšaukti?Tas pats interpretatorius, kuris paleidžia Thonny (numatyta)Nurodytas tekstas nerastas!Tema ir šriftasŠis laukas skirtas jūsų darbiniams užrašams -- užduočiai, kodo iškarpoms, bet kam. Viskas automatiškai išsaugoma ir pakraunama kitą kartą atveriant Thonny. Laisvai galite ištrinti šį tekstą ir padaryti vietos savo užrašams.Šis kompiuterisŠis dialogas skirtas valdyti Thonny įskiepius ir jų priklausomybes. Jei norite diegti paketus savo programoms naudokite "Įrankiai → Valdyti paketus...'Šis dialogas išvardina visus prieinamus paketus, bet leidžia atnaujinti ar išdiegti paketus išČia komentarasŠis paketas reikalauja kitos Thonny versijos:Ši programa suteikiama BE JOKIOS GARANTIJOS! Ji yra laisva programinė įranga, ir jūs galite platinti ją tam tikromis sąlygomis, žiūrėkite https://opensource.org/licenses/MIT norėdami sužinoti daugiauŠi virtuali aplinka automatiškai valdoma Thonny. Thonny nustatymaiThonny įskiepiaiThonny įskiepis be reikalavimųPerjungti komentarąĮrankiaiBandyti aptikti prievadą automatiškaiVartotojo aplinkos režimasVartotojo aplinkos didinimo faktoriusVartotojo sąsajos temaNužymėkite norėdami tradicinės veiksenos.AtkomentuotiAnuliuotiIšdiegtiNetinkami reikalavimaiAukštynAtnaujintiAtnaujinti priklausomybesAtnaujinti ar išdiegtiĮkelti į %sĮkeliama %s į %sNaudokite "Stop" komandą norėdami atšaukti tinkinimąKintamiejiVersijų istorijaVersija, kurią norima sudiegti:VaizdasKurį interpretatorių ar įrenginį turėtų naudoti Thonny paleidžiant jūsų kodą?Su esamu interpretatoriumi jūs galite paketus naršyti tik čia. Naudokite 'Įrankiai → Atverti sistemos komand. eilutę...' norėdami įdiegti, atnaujinti ar išdiegti.Dirbama...Perkelti teksta (gali būti lėta)Galite uždaryti šį dialogo langą.Jums reikia įvestiBūtina pasirinkti failą!Jūsų interpretatoriaus nėra sąraše?Priartintivisi failaibla, blabaitųtikslus paketo pavadinimasčiaieškokite savo įrenginio pavadinimo, "USB Serial" arba "UART"micro:bit vieta:prašome palauktipython vykdomasis failaspalaiko pagrindinius ANSI-spalvų kodus ir stiliusnorėdami surasti ir sudiegti paketų failą (dažniausia su .whl, .tar.gz ar .zip trumpiniu).norėdami rasti requirements.txt reikalavimų failą ir sudiegti paketus aprašytus jame.neuzdaryta_eilutevartotojo paketaivirtuali aplinkthonny-3.2.7/thonny/locale/lt_LT/LC_MESSAGES/thonny.po0000755000175000017500000011735113611773167023343 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: lt\n" #: thonny/workbench.py:355 msgid "File" msgstr "Failas" #: thonny/workbench.py:356 msgid "Edit" msgstr "Keisti" #: thonny/workbench.py:357 msgid "View" msgstr "Vaizdas" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Paleisti" #: thonny/workbench.py:360 msgid "Tools" msgstr "Įrankiai" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Pagalba" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Alternatyvus Python 3 interpretatorius arba virtuali aplinka" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Speciali virtuali aplinka (pasenusi)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Išeiti" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Sumažinti šriftą" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Pereiti prie redaktoriaus" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Pereiti prie komand. eilutės" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Padidinti" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Visas ekranas" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Programos argumentai" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "Apie Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Pagamintas\n" "Estijos Tartu universitete\n" "su pagalba iš\n" "atviro-kodo bendruomenės,\n" "Raspberry Pi Foundation\n" "ir Cybernetica AS" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Ši programa suteikiama\n" "BE JOKIOS GARANTIJOS!\n" "Ji yra laisva programinė įranga, ir jūs galite\n" "platinti ją tam tikromis sąlygomis,\n" "žiūrėkite https://opensource.org/licenses/MIT\n" "norėdami sužinoti daugiau" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Versijų istorija" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Pranešti apie problemas" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Atverti Asistentą automatiškai kai programa nustoja veikti su išimtimi" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Atverti Asistentą automatiškai, kai jis turi perspėjimų jūsų kode" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Atlikti pasirinktus Pylint tikrinimus" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Atlikti MyPy tikrinimus" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Išjungti tikrinimai (vienas identifikatorius per eilutę)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Asistentas" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Auto-užbaigimas" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Kurį interpretatorių ar įrenginį turėtų naudoti Thonny paleidžiant jūsų kodą?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Interpretatorius" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "Apie Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye yra Python tinkinimo programa, kuri turi būti įdiegta atskirai.\n" "\n" "Ar norite atverti pagalbos puslapį ir sužinoti daugiau?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Tinkinti esamą scenarijų (Birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Perjungti komentarą" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Užkomentuoti" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Atkomentuoti" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Anuliuoti" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Pakartoti" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Iškirpti" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Kopijuoti" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Įklijuoti" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Pasirinkti viską" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Paleisti iki žymeklio" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Dar negalima uždaryti" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Naudokite \"Stop\" komandą norėdami atšaukti tinkinimą" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Prisegti vartotojo langus" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Paryškinti atitinkančius vardus" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Paryškinti vietinius kintamuosius" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Paryškinti skliaustelius" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Paryškinti sintaksės elementus" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Paryškinti esamą eilutę (reikia perkrauti redaktorių)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Leisti kodo užbaigimą su tab klavišu redaktoriuose" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Leisti kodo užbaigimą su tab klavišu komand. eilutėje" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Rodyti eilučių numerius" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Rekomenduojamas ilgiausias eilutės ilgis\n" "(Nustatykite į 0 norėdami išjungti paraštės liniją)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Redaktorius" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Eksportuoti panaudos žurnalą..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Įvykiai" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Failai" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Rasti ir pakeisti" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Rasti:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Pakeisti su:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Skirti didžiąsias raides" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Aukštyn" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Žemyn" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Rasti" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Pakeisti" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Pakeisti + rasti" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Pakeisti visus" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Įveskite tekstą, kuris turi būti pakeistas." #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "Nurodytas tekstas nerastas!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Leisti tik vieną paleistą Thonny vienu metu" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Atverti visus failus iš paskutinės sesijos" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "išjungti pranešimų garsą" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Teksto dydžio keitimo režimas" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Įjungtas krūvos režimas.\n" "Uždarykite krūvos vaizdą norėdami išjungti." #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Krūva" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Kalba" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Šis laukas skirtas jūsų darbiniams užrašams -- užduočiai, kodo iškarpoms, bet kam.\n" "\n" "Viskas automatiškai išsaugoma ir pakraunama kitą kartą atveriant Thonny.\n" "\n" "Laisvai galite ištrinti šį tekstą ir padaryti vietos savo užrašams." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Užrašai" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Praėjęs objektas" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Kitas objektas" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Objektų peržiūra" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "Apžvalga" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Pygame Zero režimas" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Rasti PyPI paketą" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Išdiegti" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Uždaryti" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Spragtelti " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "čia" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Atnaujinti" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Įdiegti" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Nepavyko rasti paketo PyPI" #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "tikslus paketo pavadinimas" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Vėliausia stabili versija" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Vėliausia versija" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Suvestinė" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Autorius" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Puslapis" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Klaidų sekimas" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Dokumentacija" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "PyPI puslapis" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Reikalauja" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Tikrai išdiegti?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Ar tikrai norite išdiegti?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Atgal į\n" "esamą kadrą" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Kintamieji" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Šis kompiuteris" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Atnaujinti" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Pereiti į" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Klaida" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Būtina pasirinkti failą!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Perrašyti?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Ar tikrai norite perrašyti '%s'?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Naujas" #: thonny/code.py:526 msgid "Open..." msgstr "Atverti..." #: thonny/code.py:528 msgid "Load" msgstr "Pakrauti" #: thonny/code.py:537 msgid "Recent files" msgstr "Paskutiniai atverti failai" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Uždaryti visus" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Išsaugoti" #: thonny/code.py:583 msgid "Save as..." msgstr "Išsaugoti kaip..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Išsaugoti kopiją..." #: thonny/code.py:603 msgid "Rename..." msgstr "Pervardinti..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Thonny nustatymai" #: thonny/running.py:94 msgid "Run current script" msgstr "Paleisti esamą scenarijų" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Paleisti esamą scenarijų terminale" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Sustabdyti/Perkrauti tarnybinį servisą" #: thonny/running.py:139 msgid "Stop" msgstr "Sustabdyti" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Pertraukti veikimą" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Nusiųsti EOF / Minkštas perkrovimas" #: thonny/running.py:172 msgid "Disconnect" msgstr "Atsijungti" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Žinomi interpretatoriai" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Jūsų interpretatoriaus nėra sąraše?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Surasti kitą" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "python vykdomasis failas" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "NB! Thonny palaiko Python 3.5 ir vėlesnius" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Sukurti naują virtualią aplinką" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Pasirinkti esamą, arba sukurti naują aplanką" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Python interpretatoriai" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "visi failai" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Pasirinkite tuščią aplanką naujai virtualiai aplinkai" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Blogas aplankas" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "Pasirinktas aplankas nėra tuščias.\n" "Pasirinkite kitą arba atšaukite." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Kuriama virtuali aplinka" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Išvalyti komand. eilutę" #: thonny/shell.py:126 msgid "Plotter" msgstr "Braižyklė" #: thonny/shell.py:245 msgid "Clear" msgstr "Išvalyti" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Rodyti braižyklę" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Dėl greitaveikos komand. eilutė labai ilgų eilučių nerodo pilnai (žiūrėkite Įrankiai → Nustatymai → Komand. Eilutė).\n" "Čia jūs galite dirbti su originaliu teksto fragmentu." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "Perkelti teksta (gali būti lėta)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Kopijuoti į iškarpinę" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Išskleisti komand. eilutėje" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Suspaustas tekstas (%d ženklų)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Braižyklė parodo numerių seriją\n" "išspausdintą į komand. eilutę" #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Detalės pagalboje" #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Uždaryti kitus" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Kopijuojama" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Kopijuojama\n" " %s\n" "į\n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Atšaukti" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "Gerai" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Atšaukti procesą?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Procesas dar veikia.\n" "Ar tikrai norite atšaukti?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Pasirinkti viską" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Komand. eilutė" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Tas pats interpretatorius, kuris paleidžia Thonny (numatyta)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Ši virtuali aplinka automatiškai valdoma Thonny.\n" "\n" "" #: thonny/workbench.py:532 msgid "Location: " msgstr "Vieta: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Nustatymai..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Padidinti šriftą" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Pakeisti šrifto dydį" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Priartinti" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Išeiti iš Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "Išeiti" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "Perrašoma tema '%s'" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Programos parametrai:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Numatytasis režimas" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "Konfigūracija atnaujinta. Perkraukite Thonny norėdami dirbti numatytame režime.\n" "\n" "(Žiūrėkite 'Įrankiai → Nustatymai → Bendra' jei apsigalvosite.)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Programos medis" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Pasirinkite interpretatorių" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Tęsti" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Paleisti / tęsti" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Tinkinti esamą scenarijų" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Tinkinti" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Tinkinti esamą scenarijų (detaliau)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Tinkinti esamą scenarijų (greičiau)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Perlipti" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "Virš" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "Lipti gilyn" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "Į" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Išlipti" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "Iš" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Eiti atgal" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Atgal" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Dėklas" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Išimtis" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Sekti programos panaudojimo įvykius" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Tinkinimo režimas (pateikia detalesnius diagnostinius išrašus)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "Vartotojo aplinkos režimas" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "Vartotojo aplinkos didinimo faktorius" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "NB! Perkraukite Thonny pakeitę šiuos nustatymus!" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Bendra" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "ĮDIEGTI" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Peržiūrėti paketus" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Su esamu interpretatoriumi jūs galite paketus naršyti tik čia. Naudokite 'Įrankiai → Atverti sistemos komand. eilutę...' norėdami įdiegti, atnaujinti ar išdiegti." #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Paketų aplankas" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Sudiegti iš PyPI" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Jei nežinote iš kur gauti paketą greičiausia norėsite paieškoti jo Python Package Index. Pradėkite įvesdami paketo pavadinimą paieškos lauke ir spustelėdami ENTER." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "norėdami rasti requirements.txt reikalavimų failą ir sudiegti paketus aprašytus jame." #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Spustelėkite" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "norėdami surasti ir sudiegti paketų failą (dažniausia su .whl, .tar.gz ar .zip trumpiniu)." #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Atnaujinti ar išdiegti" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Pradėkite pasirinkdami paketą kairėje." #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Taikinys:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "virtuali aplink" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "vartotojo paketai" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "Šis dialogas išvardina visus prieinamus paketus, bet leidžia atnaujinti ar išdiegti paketus iš" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Nauji paketai taip pat bus sudiegti į šį aplanką. Kitos vietos turi būti valdomos kitais būdais." #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Sudiegta versija:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Sudiegta į:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Patikrinkite rašybą!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "Jums reikia įvesti" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Nepavyko rasti paketo informacijos PyPI" #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Klaidos kodas:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Sąraše nepavyko rasti paketo pavadinimo:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Paketas '{}' reikalingas norint sudiegti ir išdiegti kitus paketus." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Paketas" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Valdyti paketus %s" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Patvirtinimas" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Atrodo, kad jūs bandote sudiegti su Thonny susijusį paketą. Jei norėjote sudiegti Thonny įskiepį, pasirinkite 'Įrankiai → Valdyti įskiepius...'.\n" "\n" "Ar tikrai norite sudiegti %s tarnybinei daliai?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "NB! Gali būti kita versija, kuri palaiko esamą Thonny versiją. Spustelkite '...' mytuką ir pasirinkite versiją, kurią norite sudiegti." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Thonny įskiepis be reikalavimų" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Atrodo, kad jūs bandote sudiegti pasenusį Thonny įskiepį (jis nenurodo reikalingos Thonny versijos).\n" "\n" "Jei vis dar jo norite, sudiekite jį iš komand. eilutės." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Netinkami reikalavimai" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "Šis paketas reikalauja kitos Thonny versijos:" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Jei vis dar jo norite, sudiekite iš komand. eilutės." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(Šiuo atveju Thonny tarnybinė dalis naudoja tą patį interpretatorių, abu dialogai valdo tuos pačius paketus.)" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "NB! Jums reikia perkrauti Thonny sudiegus, atnaujinus arba išdiegus įskiepį." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Thonny įskiepiai" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Detalus įdiegimas, atnaujinimas, pasendinimas" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Norima versija" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Atnaujinti priklausomybes" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Reikalauja:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Klaida:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Valdyti paketus..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Valdyti įskiepius..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "Atverti kartotuvą..." #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Pakeisti darbinį aplanką į scenarijų aplanką spustelint Paleisti / Tinkinti" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Rodyti funkcijų iškvietimus (kadrus) atskiruose languose" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "Nužymėkite norėdami tradicinės veiksenos." #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "Atverti ir uždaryti dėklo vaizdą automatiškai" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "Atidaro dėklo vaizdą pirmo iškvietimo metu ir uždaro jį kai programa grįžta į pagrindinį kadrą" #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "Leidžia įlipti į bibliotekas (t.y. už pagrindinio scenarijaus aplanko)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Gali sulėtinti tinkinimą." #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Pageidautinas tinkintuvas" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(naudojamas spustelint Tinkinti įrankinės mygtuką)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Birdseye prievadas" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(pakeitę paleiskite Thonny iš naujo)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Paleisti ir Tinkinti" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Terminalo emuliacija" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "palaiko pagrindinius ANSI-spalvų kodus ir stilius" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Didžiausias paliekamas eilučių skaičius" #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "NB! Didelės reikšmės gali paveikti veikimą!" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Didžiausias eilutės fragmento ilgis prieš suspaudžiant" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Esamas scenarijus leidžiamas terminale" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Parodyti Python REPL pasibaigus programai" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Palikti terminalo langą atvirą po to kai pasibaigia Python procesas" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "NB! Automatinis uždarymas turi būti įgalintas Terminalo nustatymuose (Profiliai → Komand. eilutė → Kai išeinama iš komand. eilutės)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Terminalas" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "Vartotojo sąsajos tema" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Sintaksės tema" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Redaktoriaus šriftas" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "Įvesties-išvesties šriftas" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Peržiūra" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "Čia komentaras" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "Atsakymas yra" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "neuzdaryta_eilute" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "bla, bla" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "NB! Kai kurie stiliaus elementai išvaizdą pakeičia tik perkrovus Thonny!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Įveskite skaičių" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Tema ir šriftas" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Atverti Thonny programos aplanką..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Atverti Thonny duomenų aplanką..." #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Namai" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Pagalbos turinys" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "CircuitPython įrenginys" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "MicroPython įrenginys" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Prijunkite savo įrenginį prie kompiuterio ir pasirinkite atitinkamą prievadą apačioje" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "ieškokite savo įrenginio pavadinimo, \"USB Serial\" arba \"UART\"" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Jei jo negalite rasti, gali reikėti pirma įdiegti tinkamą USB tvarkyklę." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Prievadas" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Bandyti aptikti prievadą automatiškai" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython (bendras)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Spausdinti..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Atverti sistemos komand. eilutę..." #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Detalės" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Sudiegti iš reikalavimų failo" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Sudiegti iš lokalaus failo" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "Šis dialogas skirtas valdyti Thonny įskiepius ir jų priklausomybes.\n" "Jei norite diegti paketus savo programoms naudokite \"Įrankiai → Valdyti paketus...'" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (bendras)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Atitraukti pasirinktas eilutes" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Atitraukti pasirinktas eilutes atgal" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Perjungti į\n" "numatytą\n" "režimą" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "Įsitikinkite, kad MicroPython buvo sudiegtas į jūsų micro:bit." #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "Nepamirškite, kad main.py veikia tik neįterpus pagrindinio scenarijaus." #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "Sudiegti vėliausią MicroPython į BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "micro:bit vieta:" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Versija, kurią norima sudiegti:" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "prašome palaukti" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "NB! Visi failai micro:bit bus ištrinti!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Diegiama..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Baigta!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Galite uždaryti šį dialogo langą." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Programinė apratinė įranga" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "Atverti dialogą sudiegti ar atnaujinti MicroPython jūsų įrenginyje" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "Nepavyko rasti disko '%s'." #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "Įsitikinkite, kad jūsų micro:bit prijungtas!" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Ar norite tęsti ir surasti diską patys?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "Nepavyko rasti disko '%s'. Ar norite surasti jį patys?" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Rasti keli '%s' diskai. Ar norite pasirinkti vieną jų?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Nepavyko rasti tinkamo disko" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d įrašų" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Perkelti į Šiukšlinę" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Perkelti į Šiukšles" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Išrinti" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Naujas aplankas" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Nustatymai" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Saugojimo vieta" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "Kelias" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Aplanko nustatymai" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Failo nustatymai" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "baitų" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "Dydis" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Pakeista" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "Trinama %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Perkeliama %s į %s" #: thonny/code.py:203 msgid "Loading" msgstr "Kraunama" #: thonny/code.py:297 msgid "Saving" msgstr "Saugojama" #: thonny/running.py:1408 msgid "Working..." msgstr "Dirbama..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Įkeliama %s į %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Įkelti į %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "Atsisiunčiama %s į %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Atsisiųsti į %s" thonny-3.2.7/thonny/locale/pl_PL/0000755000175000017500000000000013611777205017651 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/pl_PL/LC_MESSAGES/0000755000175000017500000000000013611777205021436 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/pl_PL/LC_MESSAGES/thonny.mo0000644000175000017500000006152313611773167023324 0ustar annamaaannamaa00000000000000P ]&$)* &+A-m!7& & -;@ Vxd   &AZau;  # - :F G27IQf<%*-JNTi3 ! (4DLa |5 B@FKZot {   *05D[a j w => |0 6 * C Y s x   F C!!! ""'"?"+^" """ """3"#&#/#E#T#Y#a# p#{##i$z%;%(%%&&& 9&1G& y&&&&&& & '+'nE','0'<(O(-(U)g) k)ny) ))))?*CN*****F*8+ @+K+O+W+ \+g+~+H+++++,!,=,:E,,,&,,,,,, - - -'-8-L-Q- c-Bp--- - -&-- . . .-.=. F.P.W. [. g.t.. .".. . ... / /2'//Z//:/// /0030E0J0h0-n0 0 00 000 000 111(1 ;1>I101!1 11 2b2J3/\33@F444"444 4455 "5,5 15;5S5V5^5s5 5525 5556D6X6 66 7*7<7#W7{7 7 7777177 78%8V=8I888999v9$8:?]:/: ::::.&;7U;*;;;;<<!<4<;<U<f< <==3=*P='{= ====I=@>X> r>|>>>>>> >> ?E??? ?@!@8?@$x@2@@!@AAA#7A#[A!AJAAB%B ,B9B KBWB"oBB:BBB CJCcCkCtCCCCCC&CC DD D#D ,D6DEDXDoDtDDDDDDDDDDE0E6E 4FAFIFFPFFFDFFGG1GNG ]G kGuGcGG8HHI I'I9IVI2rIIII III?I>JQJXJrJJ JJ J$JJKzmLGL.0M_M{MM M<M(MN=NUN mN{NNN7N}N<lO2OXO5P4P_PRQ WQvdQQQQQN RHZR R"RRRSSoSwSSSS SSSRS TT#T,T?T\TpT7xTTT,TTTUU*U>UNU ]UiUzUUUUSUV V #V0V4AVvV~VVVV VVVVVVW#WAW,TWWWW WWWW8W2.XaX8uXXXX3XY,Y4YTY%YYY YY Y Y"YY YY ZZ Z)Z JZ9Z$ZZZ [\\&\\F] ]]]^ 0^#;^_^$g^^ ^^ ^^^ ^^^_%_?9_y____W_ ` ` `*`a-a'BajaoaaaaaDaabb)4b_^bQbc c=c%d items(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)(restart Thonny after changing this)(used when clicking Debug toolbar button)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAdvanced install / upgrade / downgradeAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAlternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portBrowse the packagesBugtrackerCan't close yetCan't find package name from the list:Can't find suitable diskCancelCancel the process?Case sensitiveChange font sizeChange working directory to script directory on Run / DebugCircuitPython (generic)CircuitPython deviceClearClear shellClickClick CloseClose allClose othersComment outConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)ConfirmationConnect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find disk '%s'.Could not find disk '%s'. Do you want to locate it yourself?Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDeleteDeleting %sDesired versionDetailsDirectory propertiesDisable notification soundDisconnectDo you want to continue and locate the disk yourself?Do you want to overwrite '%s' ?Dock user windowsDocumentationDon't forget that main.py only works without embedded main script.Done!DownDownload to %sDownloading %s to %sEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFile propertiesFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus intoFocus shellFont scaling modeFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: pl %d elementóœ(W tym przypadku Thonny używa tego samego interpretera, więc oba okna dialogowe zarządzają tymi samymi pakietami).(uruchom ponownie Thonny po zmianie)(używane po kliknięciu przycisku paska narzędzi debugowania)Dedykowane środowisko wirtualne (nie zalecane)O BirdseyeO programie ThonnyZaawansowana instalacja / aktualizacja / obniżenie wersjiAllow code completion with Tab-key in powłoceZezwól na uzupełnianie kodu klawiszem Tab w edytorachZezwalaj tylko na jedną instancję ThonnyAlternatywny interpreter Python 3 lub środowisko wirtualneCzy na pewano odinstalować? AsystentAutorAuto-uzupełnianieWsteczWróć do aktualnej ramkiBłędny katalogBirdseye to debugger języka Python, który należy zainstalować oddzielnie. Czy chcesz otworzyć stronę pomocy i dowiedzieć się więcej?Port BirdseyePrzeglądaj pakietySystem śledzenia błędówNie można jeszcze zamknąćNie mogę znaleźć nazwy pakietu z listy:Nie mogę znaleźć odpowiedniego dyskuZatrzymajZatrzymać proces?Uwzględniaj wielkość literZmień rozmiar czcionkiZmień katalog roboczy na katalog skryptów po wybraniu Uruchom / DebugujCircuitPython (generic)Urządzenie CircuitPythonWyczyśćWyczyść powłokęKliknijKlik ZamknijZamknij wszystkieZamknij pozostałeZakomentujKonfiguracja została zaktualizowana. Uruchom ponownie Thonny, aby rozpocząć pracę w trybie zwykłym. (Zobacz 'Narzędzia → Opcje → Ogólne', jeśli później zmienisz zdanie).PotwierdzeniePodłącz urządzenie do komputera i wybierz odpowiedni port poniżejKopiujSkopiuj do schowkaKopiowanieKopying %s do %sNie można odnaleźć dysku '%s'.Nie znaleziono dysku '%s'. Czy chcesz zlokalizować sam?Nie można znaleźć pakietu z PyPI.Nie można znaleźć informacji o pakiecie z PyPI.Stwórz środowisko wirtualneTworzenie środowiska wirtualnegoWytnijDebugujDebuguj aktualny skryptDebuguj bieżący skrypt (birdseye)Debuguj bieżący skrypt (szybciej)Debuguj bieżący skrypt (lepiej)Tryb debugowanie (zapewnia bardziej szczegółowe dzienniki diagnostyczne)Zmniejsz rozmiar czcionkiUsuń wcięcie wybranych liniiSkasujKasowanie %sPożądana wersjaSzczegółyWłaściwości kataloguWyłącz powiadomienia dźwiękoweOdłączCzy chcesz kontynuować i zlokalizować dysk samodzielnie?Czy chcesz nadpisać '%s' ?Zadokuj okna użytkownikDokumentacjaNie zapominaj, że main.py działa tylko bez osadzonego skryptu głównegoGotowe!Do dołuPobieranie do %sPObieranie %s do %sEdytujEdytorCzcionka edytoraWprowadź liczbę całkowitąWpisz napis, który chcesz zastąpić.BłądKod błędu:Błąd:ZdarzeniaWyjątekWyjśćieZamknij ThonnyRozwiń w powłoceEksportuj dzienniki...PlikWłaściwości plikuPlikiZnajdźZnajdź i zastąpZnajdź pakiet z PyPiZnajdź:FirmwarePrzenieś fokus na edytorUstwa fokus naPrzenieś fokus na powłokęTryb skalowania czcionekZe względu na wydajność, powłoka unika wyświetlania bardzo długich linii w całości (patrz Narzędzia → Opcje → Powłoka). Tutaj możesz wchodzić w interakcję z oryginalnym fragmentem tekstu.Znaleziono kilka dysków '%s'. Czy chcesz sam wybrać?Pełny ekranOgólneStertaTryb sterty jest włączony. Zamknij widok sterty, aby go wyłączyć.PomocPomocPodświetl bieżącą linię (wymaga ponownego uruchomienia edytora)Podświetl zmienne lokalnePodświetl pasujące nazwyPodświetl nawiasyPodświetl elementy składniKatalog domowyStrona domowa INSTALL Czcionka We/WyJeśli nie możesz go znaleźć, być może najpierw musisz zainstalować odpowiedni sterownik USB.Jeśli nie wiesz, skąd wziąć pakiet, najprawdopodobniej będziesz chciał przeszukać Indeks pakietów Pythona. Zacznij od wpisania nazwy pakietu w polu wyszukiwania powyżej i wciśnięcia ENTER.Jeśli nadal tego chcesz, zainstaluj z wiersza poleceń.Zwiększ rozmiar czcionkiWcięcie wybranych liniiZainstalujZainstaluj z PyPiZainstaluj z pliku lokalnegoZainstaluj z pliku wymagańZainstaluj najnowszą MicroPython na BBC micro:bitZainstalowane w:Zainstalowana wersja:Instalowanie ...InterpreterPrzerwij wykonanieWPozostaw okno terminala otwarte po zakończeniu procesu PythonaZnane interpreteryJęzykNajnowsza stabilna wersjaNajnowasz wersjaZaładujŁadowanieZlokalizuj kolejnyLokalizacja: Rejestruj zdarzenia użycia programuWygląda na to, że instalujesz pakiet związany z Thonny. Jeśli chcesz zainstalować wtyczkę Thonny, powinieneś zamiast tego wybierz „Narzędzia → Zarządzaj wtyczkami ...” Czy na pewno chcesz zainstalować %s?Wygląda na to, że próbujesz zainstalować przestarzałą wtyczkę Thonny (nie określa wymaganej wersji Thonny). Jeśli nadal tego chcesz, zainstaluj ją z wiersza poleceń.Stworzone na University of Tartu, Estonia, z pomocą społeczności open source, Fundacja Raspberry Pi oraz Cybernetica ASUpewnij się, że MicroPython został zainstalowany na twoim micro:bit.Upewnij się, że masz podłączony micro:bit!Zarządzaj pakietami dla %sZarządzaj pakietami...Zarządzaj wtyczkami...ZmaksymalizujMaksymalna długość fragmentów linii przed ściśnięciemMaksymalna liczba wierszy do zachowania.Może spowolnić debugowanie. MicroPython (generic) Urządzenie MicroPythonZmodyfikowanePrzenieś do KoszaPrzenieś do KoszaPrzesuwanie %s do %sUwaga! Wszystkie pliki na micro:bit zostaną usunięte!Uwaga! Automatyczne zamykanie musi być włączone w ustawieniach terminalu (Profile → Powłoka → Po wyjściu z powłoki)Uwaga! Duże wartości mogą powodować słabą wydajność!NB! Uruchom ponownie Thonny po zmianie tych opcji!Uwaga! Niektóre elementy stylu zmieniają się dopiero po ponownym uruchomieniu Thonny!NB! Może być dostępna inna wersja zgodna z bieżącą wersją Thonny. Kliknij przycisk '...', aby wybrać wersję do zainstalowania.Uwaga! Thonny obsługuje tylko Python 3.5 lub nowszyUwaga! Musisz ponownie uruchomić Thonny po instalacji / aktualizacji / odinstalowaniu wtyczki.NowyNowy katalogNowe pakiety zostaną również zainstalowane w tym katalogu. Inne lokalizacje muszą być zarządzane w inny sposób.Następny obiektNotatkiOKInspektor obiektówOtwórz asystenta automatycznie, gdy pojawi się ostrzeżenie dla Twojego koduOtwórz asystenta automatycznie, gdy program ulegnie awarii z wyjątkiemOtwórz folder danych Thonny ...Otwórz folder programu Thonny ...Otwórz replayer...Otwórz powłokę systemową...Otwórz okno dialogowe instalacji lub aktualizacji MicroPython na swoim urządzeniuOtwórzOpcje...PozaZarysPonadNadpisac?Nadpisuję temat '%s'PakietPakiet „{}” jest wymagany do instalowania i odinstalowywania innych pakietów.Katalog pakietówWklejScieżkaWykonaj testy MyPyWykonaj wybrane testy PylintSprawdź pisownię!PlotterPloter wizualizuje serię liczb wydrukowane w powłoce.PortPreferowany debugerPokaż REPL Pythona po zakończeniu programuPodglądPoprzedni obiektDrukujArgumenty programuArgumenty programu:Drzewo programuWłaściwościPakiet PyPiTryb Pygame ZeroInterpretery PythonZakończNaprawdę odinstalowaćOstatnie plikiZalecana maksymalna długość linii (Ustaw na 0, aby wyłączyć linię marginesu)PonówOdświeżTryb zwykłyZmień nazwę...Otwórz ponownie wszystkie pliki z poprzedniej sesjiZastąpZastąś wszystkieZastąp przez:Zastąp+ZnajdźZgłoś problemyWymaganiaWymaga:WznówUruchomUruchom i debugujUruchon / wznówUruchom aktualny skryptUruchom aktualny skrypt w terminaluUruchom do kursoraUruchamianie bieżącego skryptu w terminaluZapiszZapisz jako...Zapisz kopię...ZapisywanieSprawdź informacje w pomocy.Wybierz wszystkieWybierz wszystkoWybierz pusty katalog dla nowego środowiska wirtualnegoWybierz istniejący lub utwórz nowy pusty katalogWybierz interpreterWybrany katalog nie jest pusty. Wybierz inny lub anuluj.Wyślij EOF / Miękki restartPowłokaPokaż Plotter Pokaż wywołania funkcji (ramki) w osobnych oknachPokaż numery liniRozmiarŚciśnięty tekst (%d znaków)StosZacznij od wybrania pakietu od lewej.CofnijWejdź doWyjdźZrób krokZatrzymajZatrzymaj/Uruchom ponownie backendPrzestrzeń dyskowaPodsumowaniePrzełącz na regularny trybStyl składniCel:TerminalEmulacja terminalaOdpowiedź toProces jest nadal uruchomiony. Czy na pewno chcesz zatrzymać?Ten sam interpreter, który uruchamia Thonny (domyślnie)Podany tekst nie został znaleziony!Tematy i czcionkaTo pole jest przeznaczone do notatek roboczych - instrukcj do zadań, fragmentów kodu i innych. Wszystko zostanie zapisane automatycznie i załadowane, gdy następnym razem otworzysz Thonny. Usuń ten tekst, aby zrobić miejsce na własne notatki.Ten komputerTo okno dialogowe zawiera listę wszystkich dostępnych pakietów, ale umożliwia aktualizację i odinstalowywanie tylko pakietów zTo jest komentarzTen pakiet wymaga innej wersji Thonny:Ten program wydawany jest ABSOLUTNIE BEZ ŻADNEJ GWARANCJI! To jest wolne oprogramowanie i mile widziane jest dalsze rozpowszechnianie go na podobnych warunkach, patrz https://opensource.org/licenses/MIT po szczegółyTo wirtualne środowisko jest automatycznie zarządzane przez Thonny. Opcje Thonny Wytczki ThonnyWtyczka Thonny bez wymagańPrzełącz komentarzNarzędziaSpróbuj wykryć port automatycznieTryb UIWspółczynnik skalowania interfejsuWyglądOdkomentujCofnijOdinstalujNiewłaściwe wymaganiaW góręUaktualnijZależności aktualizacjiAktualizuja lub odinstalujPrzesyłanie do %sWysyłanie %s do %sUżyj polecenia „Stop”, jeśli chcesz anulować debugowanieZmiennaHistoria wersjiWersja do zainstalowania:PodglądZ jakiego interpretera lub urządzenia Thonny powinien korzystać do uruchamiania kodu?Przy obecnym interpreterze możesz przeglądać tylko paczki tutaj. Użyj „Narzędzia → Otwórz powłokę systemową ...”, aby zainstalować, zaktualizować lub odinstalować.Pracuję...Zawijaj tekst (może być wolny)Możesz teraz zamknąć to okno dialogowe.Musisz wprowadzićMusisz wybrać plik!Twojego interpretera nie ma na liście?Zoomwszystkie plikicośtam, cośtambajtydokładna nazwa pakietututajwyszukaj nazwę swojego urządzenia, „USB Serial” lub „UART”lokalizacja micro:bit:proszę czekajplik binarny pythonaobsługuje podstawowe kolory i style ANSIaby zlokalizować i zainstalować plik pakietu (zwykle z rozszerzeniem .whl, .tar.gz lub .zip).aby zlokalizować plik requirements.txt i zainstalować określone w nim pakiety.unclosed_stringlokalne pakiety urzytkownikawirtualne środowiskothonny-3.2.7/thonny/locale/pl_PL/LC_MESSAGES/thonny.po0000644000175000017500000011646413611773167023334 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: pl\n" #: thonny/workbench.py:355 msgid "File" msgstr "Plik" #: thonny/workbench.py:356 msgid "Edit" msgstr "Edytuj" #: thonny/workbench.py:357 msgid "View" msgstr "Podgląd" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Uruchom" #: thonny/workbench.py:360 msgid "Tools" msgstr "Narzędzia" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Pomoc" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Alternatywny interpreter Python 3 lub środowisko wirtualne" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Dedykowane środowisko wirtualne (nie zalecane)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Wyjśćie" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Zmniejsz rozmiar czcionki" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Przenieś fokus na edytor" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Przenieś fokus na powłokę" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Zmaksymalizuj" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Pełny ekran" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Argumenty programu" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "O programie Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Stworzone na\n" "University of Tartu, Estonia,\n" "z pomocą\n" "społeczności open source,\n" "Fundacja Raspberry Pi\n" "oraz Cybernetica AS" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Ten program wydawany jest\n" "ABSOLUTNIE BEZ ŻADNEJ GWARANCJI!\n" "To jest wolne oprogramowanie i mile widziane jest\n" "dalsze rozpowszechnianie go na podobnych warunkach, patrz\n" "https://opensource.org/licenses/MIT\n" "po szczegóły" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Historia wersji" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Zgłoś problemy" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Otwórz asystenta automatycznie, gdy program ulegnie awarii z wyjątkiem" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Otwórz asystenta automatycznie, gdy pojawi się ostrzeżenie dla Twojego kodu" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Wykonaj wybrane testy Pylint" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Wykonaj testy MyPy" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Asystent" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Auto-uzupełnianie" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Z jakiego interpretera lub urządzenia Thonny powinien korzystać do uruchamiania kodu?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Interpreter" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "O Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye to debugger języka Python, który należy zainstalować oddzielnie.\n" "\n" "Czy chcesz otworzyć stronę pomocy i dowiedzieć się więcej?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Debuguj bieżący skrypt (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Przełącz komentarz" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Zakomentuj" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Odkomentuj" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Cofnij" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Ponów" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Wytnij" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Kopiuj" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Wklej" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Wybierz wszystko" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Uruchom do kursora" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Nie można jeszcze zamknąć" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Użyj polecenia „Stop”, jeśli chcesz anulować debugowanie" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Zadokuj okna użytkownik" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Podświetl pasujące nazwy" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Podświetl zmienne lokalne" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Podświetl nawiasy" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Podświetl elementy składni" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Podświetl bieżącą linię (wymaga ponownego uruchomienia edytora)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Zezwól na uzupełnianie kodu klawiszem Tab w edytorach" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Allow code completion with Tab-key in powłoce" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Pokaż numery lini" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Zalecana maksymalna długość linii\n" "(Ustaw na 0, aby wyłączyć linię marginesu)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Edytor" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Eksportuj dzienniki..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Zdarzenia" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Pliki" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Znajdź i zastąp" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Znajdź:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Zastąp przez:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Uwzględniaj wielkość liter" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "W górę" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Do dołu" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Znajdź" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Zastąp" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Zastąp+Znajdź" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Zastąś wszystkie" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Wpisz napis, który chcesz zastąpić." #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "Podany tekst nie został znaleziony!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Zezwalaj tylko na jedną instancję Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Otwórz ponownie wszystkie pliki z poprzedniej sesji" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Wyłącz powiadomienia dźwiękowe" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Tryb skalowania czcionek" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Tryb sterty jest włączony.\n" "Zamknij widok sterty, aby go wyłączyć." #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Sterta" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Język" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "To pole jest przeznaczone do notatek roboczych - instrukcj do zadań, fragmentów kodu i innych.\n" "\n" "Wszystko zostanie zapisane automatycznie i załadowane, gdy następnym razem otworzysz Thonny.\n" "\n" "Usuń ten tekst, aby zrobić miejsce na własne notatki." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Notatki" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Poprzedni obiekt" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Następny obiekt" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Inspektor obiektów" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "Zarys" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Tryb Pygame Zero" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Znajdź pakiet z PyPi" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Odinstaluj" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Zamknij" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Klik " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "tutaj" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Uaktualnij" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Zainstaluj" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Nie można znaleźć pakietu z PyPI." #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "dokładna nazwa pakietu" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Najnowsza stabilna wersja" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Najnowasz wersja" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Podsumowanie" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Autor" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Strona domowa" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "System śledzenia błędów" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Dokumentacja" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "Pakiet PyPi" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Wymagania" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Naprawdę odinstalować" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Czy na pewano odinstalować? " #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Wróć do\n" "aktualnej ramki" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Zmienna" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Ten komputer" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Odśwież" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Ustwa fokus na" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Błąd" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Musisz wybrać plik!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Nadpisac?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Czy chcesz nadpisać '%s' ?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Nowy" #: thonny/code.py:526 msgid "Open..." msgstr "Otwórz" #: thonny/code.py:528 msgid "Load" msgstr "Załaduj" #: thonny/code.py:537 msgid "Recent files" msgstr "Ostatnie pliki" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Zamknij wszystkie" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Zapisz" #: thonny/code.py:583 msgid "Save as..." msgstr "Zapisz jako..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Zapisz kopię..." #: thonny/code.py:603 msgid "Rename..." msgstr "Zmień nazwę..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Opcje Thonny " #: thonny/running.py:94 msgid "Run current script" msgstr "Uruchom aktualny skrypt" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Uruchom aktualny skrypt w terminalu" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Zatrzymaj/Uruchom ponownie backend" #: thonny/running.py:139 msgid "Stop" msgstr "Zatrzymaj" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Przerwij wykonanie" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Wyślij EOF / Miękki restart" #: thonny/running.py:172 msgid "Disconnect" msgstr "Odłącz" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Znane interpretery" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Twojego interpretera nie ma na liście?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Zlokalizuj kolejny" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "plik binarny pythona" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "Uwaga! Thonny obsługuje tylko Python 3.5 lub nowszy" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Stwórz środowisko wirtualne" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Wybierz istniejący lub utwórz nowy pusty katalog" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Interpretery Python" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "wszystkie pliki" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Wybierz pusty katalog dla nowego środowiska wirtualnego" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Błędny katalog" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "Wybrany katalog nie jest pusty.\n" "Wybierz inny lub anuluj." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Tworzenie środowiska wirtualnego" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Wyczyść powłokę" #: thonny/shell.py:126 msgid "Plotter" msgstr "Plotter" #: thonny/shell.py:245 msgid "Clear" msgstr "Wyczyść" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Pokaż Plotter " #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Ze względu na wydajność, powłoka unika wyświetlania bardzo długich linii w całości (patrz Narzędzia → Opcje → Powłoka).\n" "Tutaj możesz wchodzić w interakcję z oryginalnym fragmentem tekstu." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "Zawijaj tekst (może być wolny)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Skopiuj do schowka" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Rozwiń w powłoce" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Ściśnięty tekst (%d znaków)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Ploter wizualizuje serię\n" "liczb wydrukowane w powłoce." #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Sprawdź informacje w pomocy." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Zamknij pozostałe" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Kopiowanie" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Kopying\n" " %s\n" "do\n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Zatrzymaj" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "OK" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Zatrzymać proces?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Proces jest nadal uruchomiony.\n" "Czy na pewno chcesz zatrzymać?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Wybierz wszystkie" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Powłoka" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Ten sam interpreter, który uruchamia Thonny (domyślnie)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "To wirtualne środowisko jest automatycznie zarządzane przez Thonny.\n" "" #: thonny/workbench.py:532 msgid "Location: " msgstr "Lokalizacja: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Opcje..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Zwiększ rozmiar czcionki" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Zmień rozmiar czcionki" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Zoom" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Zamknij Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "Zakończ" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "Nadpisuję temat '%s'" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Argumenty programu:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Tryb zwykły" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "Konfiguracja została zaktualizowana. Uruchom ponownie Thonny, aby rozpocząć pracę w trybie zwykłym.\n" "\n" "(Zobacz 'Narzędzia → Opcje → Ogólne', jeśli później zmienisz zdanie)." #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Drzewo programu" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Wybierz interpreter" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Wznów" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Uruchon / wznów" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Debuguj aktualny skrypt" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Debuguj" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Debuguj bieżący skrypt (lepiej)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Debuguj bieżący skrypt (szybciej)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Zrób krok" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "Ponad" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "Wejdź do" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "W" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Wyjdź" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "Poza" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Cofnij" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Wstecz" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Stos" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Wyjątek" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Rejestruj zdarzenia użycia programu" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Tryb debugowanie (zapewnia bardziej szczegółowe dzienniki diagnostyczne)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "Tryb UI" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "Współczynnik skalowania interfejsu" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "NB! Uruchom ponownie Thonny po zmianie tych opcji!" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Ogólne" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "\n" "INSTALL\n" "" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Przeglądaj pakiety" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Przy obecnym interpreterze możesz przeglądać tylko paczki tutaj.\n" "Użyj „Narzędzia → Otwórz powłokę systemową ...”, aby zainstalować, zaktualizować lub odinstalować." #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Katalog pakietów" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Zainstaluj z PyPi" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Jeśli nie wiesz, skąd wziąć pakiet, najprawdopodobniej będziesz chciał przeszukać Indeks pakietów Pythona. Zacznij od wpisania nazwy pakietu w polu wyszukiwania powyżej i wciśnięcia ENTER." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "aby zlokalizować plik requirements.txt i zainstalować określone w nim pakiety." #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Kliknij" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "aby zlokalizować i zainstalować plik pakietu (zwykle z rozszerzeniem .whl, .tar.gz lub .zip)." #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Aktualizuja lub odinstaluj" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Zacznij od wybrania pakietu od lewej." #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Cel:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "wirtualne środowisko" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "lokalne pakiety urzytkownika" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "To okno dialogowe zawiera listę wszystkich dostępnych pakietów, ale umożliwia aktualizację i odinstalowywanie tylko pakietów z" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Nowe pakiety zostaną również zainstalowane w tym katalogu. Inne lokalizacje muszą być zarządzane w inny sposób." #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Zainstalowana wersja:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Zainstalowane w:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Sprawdź pisownię!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "Musisz wprowadzić" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Nie można znaleźć informacji o pakiecie z PyPI." #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Kod błędu:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Nie mogę znaleźć nazwy pakietu z listy:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Pakiet „{}” jest wymagany do instalowania i odinstalowywania innych pakietów." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Pakiet" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Zarządzaj pakietami dla %s" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Potwierdzenie" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Wygląda na to, że instalujesz pakiet związany z Thonny.\n" "Jeśli chcesz zainstalować wtyczkę Thonny, powinieneś\n" "zamiast tego wybierz „Narzędzia → Zarządzaj wtyczkami ...”\n" "\n" "Czy na pewno chcesz zainstalować %s?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "NB! Może być dostępna inna wersja zgodna z bieżącą wersją Thonny. Kliknij przycisk '...', aby wybrać wersję do zainstalowania." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Wtyczka Thonny bez wymagań" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Wygląda na to, że próbujesz zainstalować przestarzałą wtyczkę\n" "Thonny (nie określa wymaganej wersji Thonny).\n" "\n" "Jeśli nadal tego chcesz, zainstaluj ją z wiersza poleceń." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Niewłaściwe wymagania" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "Ten pakiet wymaga innej wersji Thonny:" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Jeśli nadal tego chcesz, zainstaluj z wiersza poleceń." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(W tym przypadku Thonny używa tego samego interpretera, więc oba okna dialogowe zarządzają tymi samymi pakietami)." #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "Uwaga! Musisz ponownie uruchomić Thonny po instalacji / aktualizacji / odinstalowaniu wtyczki." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Wytczki Thonny" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Zaawansowana instalacja / aktualizacja / obniżenie wersji" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Pożądana wersja" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Zależności aktualizacji" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Wymaga:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Błąd:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Zarządzaj pakietami..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Zarządzaj wtyczkami..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "Otwórz replayer..." #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Zmień katalog roboczy na katalog skryptów po wybraniu Uruchom / Debuguj" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Pokaż wywołania funkcji (ramki) w osobnych oknach" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "" #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "" #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Może spowolnić debugowanie." #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Preferowany debuger" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(używane po kliknięciu przycisku paska narzędzi debugowania)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Port Birdseye" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(uruchom ponownie Thonny po zmianie)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Uruchom i debuguj" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Emulacja terminala" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "obsługuje podstawowe kolory i style ANSI" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Maksymalna liczba wierszy do zachowania." #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "Uwaga! Duże wartości mogą powodować słabą wydajność!" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Maksymalna długość fragmentów linii przed ściśnięciem" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Uruchamianie bieżącego skryptu w terminalu" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Pokaż REPL Pythona po zakończeniu programu" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Pozostaw okno terminala otwarte po zakończeniu procesu Pythona" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "Uwaga! Automatyczne zamykanie musi być włączone w ustawieniach terminalu\n" "(Profile → Powłoka → Po wyjściu z powłoki)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Terminal" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "Wygląd" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Styl składni" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Czcionka edytora" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "Czcionka We/Wy" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Podgląd" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "To jest komentarz" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "Odpowiedź to" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "unclosed_string" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "cośtam, cośtam" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "Uwaga! Niektóre elementy stylu zmieniają się dopiero po ponownym uruchomieniu Thonny!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Wprowadź liczbę całkowitą" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Tematy i czcionka" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Otwórz folder programu Thonny ..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Otwórz folder danych Thonny ..." #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Katalog domowy" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Pomoc" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "Urządzenie CircuitPython" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "Urządzenie MicroPython" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Podłącz urządzenie do komputera i wybierz odpowiedni port poniżej" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "wyszukaj nazwę swojego urządzenia, „USB Serial” lub „UART”" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Jeśli nie możesz go znaleźć, być może najpierw musisz zainstalować odpowiedni sterownik USB." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Port" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Spróbuj wykryć port automatycznie" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr " MicroPython (generic) " #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Drukuj" #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Otwórz powłokę systemową..." #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Szczegóły" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Zainstaluj z pliku wymagań" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Zainstaluj z pliku lokalnego" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (generic)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Wcięcie wybranych linii" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Usuń wcięcie wybranych linii" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Przełącz na\n" "regularny\n" "tryb" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "Upewnij się, że MicroPython został zainstalowany na twoim micro:bit." #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "Nie zapominaj, że main.py działa tylko bez osadzonego skryptu głównego" #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "Zainstaluj najnowszą MicroPython na BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "lokalizacja micro:bit:" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Wersja do zainstalowania:" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "proszę czekaj" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "Uwaga! Wszystkie pliki na micro:bit zostaną usunięte!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Instalowanie ..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Gotowe!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Możesz teraz zamknąć to okno dialogowe." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Firmware" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "Otwórz okno dialogowe instalacji lub aktualizacji MicroPython na swoim urządzeniu" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "Nie można odnaleźć dysku '%s'." #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "Upewnij się, że masz podłączony micro:bit!" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Czy chcesz kontynuować i zlokalizować dysk samodzielnie?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "Nie znaleziono dysku '%s'. Czy chcesz zlokalizować sam?" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Znaleziono kilka dysków '%s'. Czy chcesz sam wybrać?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Nie mogę znaleźć odpowiedniego dysku" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d elementóœ" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Przenieś do Kosza" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Przenieś do Kosza" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Skasuj" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Nowy katalog" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Właściwości" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Przestrzeń dyskowa" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "Scieżka" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Właściwości katalogu" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Właściwości pliku" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "bajty" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "Rozmiar" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Zmodyfikowane" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "Kasowanie %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Przesuwanie %s do %s" #: thonny/code.py:203 msgid "Loading" msgstr "Ładowanie" #: thonny/code.py:297 msgid "Saving" msgstr "Zapisywanie" #: thonny/running.py:1408 msgid "Working..." msgstr "Pracuję..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Wysyłanie %s do %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Przesyłanie do %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "PObieranie %s do %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Pobieranie do %s" thonny-3.2.7/thonny/locale/update_pot.bat0000644000175000017500000000013613611773167021502 0ustar annamaaannamaa00000000000000cd ..\.. C:\Py3\Scripts\pybabel extract thonny/ --output-file thonny/locale/thonny.pot pausethonny-3.2.7/thonny/locale/compile_mo.bat0000644000175000017500000000011513611773167021456 0ustar annamaaannamaa00000000000000cd ..\.. C:\Py3\Scripts\pybabel compile -d thonny/locale/ -D thonny pause thonny-3.2.7/thonny/locale/nl_NL/0000755000175000017500000000000013611777205017645 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/nl_NL/LC_MESSAGES/0000755000175000017500000000000013611777205021432 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/nl_NL/LC_MESSAGES/thonny.mo0000644000175000017500000006154513611773167023324 0ustar annamaaannamaa00000000000000@ ]${)* &+8-d!D7&1 Xb iw| x ' ;F&V}; %: @LRY _ i v G&ns<%*Ji34G]mu! 5 %B3v|    ',27F]c l y =@ ~0 6,E[uzFC   !!)!A!+`! !!! !!!3!"("1"G"V"[" j"u""c#z$;$($$ % % 3%1A% s%%%%+%n&,s&0&<&'-'U'&(n*( ((((?(C(C)^)'|)))F)*T* n*y*}** ***H**++++J+f+:n+++&+++, ,, ., ;,E,V,j,o, ,B,,, , ,&,- $- 0- >-K-[- d-n-u- y- --- -"-- - .. (. 3.2>./q..:../ /0/J/\/z/-/ / // ///// 00#0,0 ?0>M000!0 00 11b22/353@304?4"O4r44 444404 45 55-50585M52b5 5555D566666#7*7 /7 97D7W71\77 77%7V7I=88888u[9296:*;: f: t:.:.:0:&;B6;6y;-; ;;;< < $<1<<< <<*< &= G=Q=g={=6=== =>>>> &>2>B>Q> >Q ? \?f?|?(??6?$ @-2@!`@!@@@@@@ A9'AaA |AAAA-A A) B4BPB hBDuBB BBBBB C(C -C7C =C IC VC`CqCCC CCCCCC CC D&D9D@D-E=EFELKEE E<EEFF-F GF TF `F lF^zFFFGGH 'H3H!KH'mH3HHHH II&IC)ImIIIIII I#IIJ~K>L.\LLLLL3L#M;MYMpM2MM8EN9~NLNO1OaO7Pw=PPPPPHPL,QyQ#Q,QQQWRhRrpR RR RRSS,SP3S SSS'SSS>S9T?T2QT T T TTT T TTU UU3UPEU U U U U0U U VV !V.V=VEV NV XVbVwVV#VV*V WW W1WPW`W0pW3WWAW-XEX KX<YXXXX6XYYY $Y.Y6Y VY"cYYYYYYEY4Z$DZiZ|Z }[[}E\\,\]B] ^&^6^V^ h^*u^^^^I^ __*_9_O_V_^_w_7_ ____X`[``&aDaUa&uaaaaaa,aab b)8babb`b%c5cSc(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)(restart Thonny after changing this)(used when clicking Debug toolbar button)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAdvanced install / upgrade / downgradeAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAllow stepping into libraries (ie. outside of main script directory)Alternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portBrowse the packagesBugtrackerCan't close yetCan't find package name from the list:Can't find suitable diskCancelCancel the process?Case sensitiveChange font sizeChange working directory to script directory on Run / DebugCircuitPython (generic)CircuitPython deviceClearClear shellClickClick CloseClose allClose othersComment outConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)ConfirmationConnect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find disk '%s'.Could not find disk '%s'. Do you want to locate it yourself?Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDesired versionDetailsDisable notification soundDisabled checks (one id per line)DisconnectDo you want to continue and locate the disk yourself?Do you want to overwrite '%s' ?Dock user windowsDocumentationDon't forget that main.py only works without embedded main script.Done!DownEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus intoFocus shellFont scaling modeFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...See Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: nl (In dit geval gebruikt Thonny's back-end dezelfde interpreter, dus beide dialoogvensters beheren dezelfde pakketten.)(start Thonny opnieuw nadat je dit hebt gewijzigd)(gebruikt bij het klikken op de werkbalkknop Debuggen)Een speciale virtuele omgeving (verouderd)Over BirdseyeOver ThonnyGeavanceerde installatie / upgrade / downgradeCode aanvullen toestaan met Tab-toets in ShellCode aanvullen toestaan met Tab-toets in editorsSta slechts één Thonny-instantie toeStappen in bibliotheken toestaan (d.w.z. buiten de hoofdscriptmap)Alternatieve Python 3-interpreter of virtuele omgevingWeet je zeker dat je het wilt deïnstalleren?AssistentAuteurAutomatisch aanvullenTerugTerug naar huidige frameOnjuiste mapBirdseye is een Python-debugger die afzonderlijk moet worden geïnstalleerd. Wil je de helppagina openen en meer te weten komen?Birdseye-poortBlader door de pakkettenBugtrackerKan nog niet sluitenKan de pakketnaam niet vinden in de lijst:Kan geen geschikte schijf vindenAnnulerenHet proces annuleren?HoofdlettergevoeligVerander lettergrootteWijzig werkmap naar scriptmap bij Uitvoeren / DebuggenCircuitPython (generiek)CircuitPython-apparaatLeegmakenShell leegmakenKlikKlik SluitenSluit allesAnderen sluitenCommentaar aanConfiguratie is bijgewerkt. Start Thonny opnieuw om te beginnen met werken in de normale modus. (Zie 'Extra → Opties → Algemeen' als je later van gedachten verandert.)BevestigingSluit je apparaat aan op de computer en selecteer de bijbehorende poort hieronderKopiërenKopieer naar klembordBezig met kopiërenBezig met kopiëren   % s naar   % sKon schijf '%s' niet vinden.Kon schijf '%s' niet vinden. Wil je het zelf opzoeken?Kan het pakket van PyPI niet vinden.Kan de pakketinformatie van PyPI niet vinden.Maak een nieuwe virtuele omgevingBezig met maken virtuele omgevingKnippenDebuggenDebug huidige scriptDebug huidige script (birdseye)Debug huidige script (sneller)Debug huidige script (mooier)Debugmodus (biedt meer gedetailleerde diagnostische logs)Verminder de lettergrootteGeselecteerde lijnen uitspringenGewenste versieDetailsSchakel meldingsgeluid uitUitgeschakelde controles (één ID per regel)LoskoppelenWil je doorgaan en zelf de schijf zoeken?Wil je '% s' overschrijven?Dock gebruikersvenstersDocumentatieVergeet niet dat main.py alleen werkt zonder ingesloten hoofdscript.Klaar!Naar benedenBewerkenEditorEditor lettertypeVoer een geheel getal inVoer de te vervangen reeks in.FoutFoutcode:Fout:EvenementenUitzonderingAfsluitenThonny afsluitenUitvouwen in ShellGebruikslogs exporteren ...BestandBestandenVindenZoeken & VervangenZoek pakket van PyPIVind:firmwareFocus editorFocus inFocus shellModus voor het schalen van lettertypenOm prestatieredenen vermijdt Shell dat hele lange lijnen volledig worden weergegeven (zie Extra => Opties => Shell). Hier kun je het originele tekstfragment bekijken en wijzigen.Verschillende '%s' schijven gevonden. Wil je er zelf een kiezen?Volledig schermAlgemeenHeapHeap-modus is ingeschakeld. Sluit de Heap-weergave om deze uit te schakelen.HelpHelp-inhoudMarkeer huidige regel (vereist opnieuw openen van de editor)Markeer lokale variabelenMarkeer overeenkomende namenMarkeer haakjesMarkeer syntaxiselementenStartlocatieStartpaginaINSTALLERENIO-lettertypeAls je het niet kunt vinden, moet je mogelijk eerst het juiste USB-stuurprogramma installeren.Als je niet weet waar je het pakket kunt krijgen, wil je waarschijnlijk de Python-pakketindex doorzoeken. Begin door de naam van het pakket in het bovenstaande zoekvak in te voeren en op ENTER te drukken.Als je het nog steeds wilt, installeer het dan vanaf de opdrachtregel.Vergroot de lettergrootteGeselecteerde lijnen inspringenInstallerenInstalleren vanuit PyPIInstalleren vanuit lokaal bestandInstalleren vanuit het vereistenbestandInstalleer de nieuwste MicroPython op BBC micro:bitGeïnstalleerd op:Geïnstalleerde versie:Installeren ...InterpreterOnderbreek uitvoeringInHoud het terminalvenster open nadat het Python-proces is beëindigdBekende interpretersTaalLaatste stabiele versieLaatste versieLadenZoek een andereLocatie: Log programmagebruik gebeurtenissenHet lijkt erop dat je een Thonny-gerelateerd pakket installeert. Als je een Thonny-plug-in bedoelde te installeren, zou je 'Tools → Plug-ins beheren ...' moeten kiezen. Weet je zeker dat je %s wilt installeren voor de back-end?Het lijkt erop dat je een verouderde Thonny plug-in probeert te installeren (het specificeert geen vereiste Thonny-versie). Als je het nog steeds wilt, installeer het dan vanaf de opdrachtregel.Gemaakt in Universiteit van Tartu, Estland, met de hulp van open-source gemeenschap, Raspberry Pi Foundation en Cybernetica ASZorg ervoor dat MicroPython op je micro:bit is geïnstalleerd.Zorg ervoor dat je micro:bit hebt aangesloten!Beheer pakketten voor %sPakketten beheren...Plug-ins beheren...Maximaliseer weergaveMaximale lengte van lijnfragmenten voor het knijpenMaximaal aantal te behouden regels.Kan debuggen langzamer maken.MicroPython (generiek)MicroPython-apparaatNB! Alle bestanden op micro:bit worden verwijderd!NB! Automatisch sluiten moet worden ingeschakeld in de instellingen van Terminal (Profielen → Shell → Wanneer de shell wordt afgesloten)NB! Grote waarden kunnen slechte prestaties veroorzaken!NB! Start Thonny opnieuw na het wijzigen van deze opties!NB! Sommige stijlelementen veranderen pas nadat Thonny opnieuw is opgestart!NB! Er is mogelijk een andere versie beschikbaar die compatibel is met de huidige Thonny-versie. Klik op de knop '...' om de te installeren versie te kiezen.NB! Thonny ondersteunt alleen Python 3.5 en hogerNB! Je moet Thonny opnieuw opstarten na het installeren / upgraden / verwijderen van een plug-in.NieuwNieuwe pakketten worden ook in deze map geïnstalleerd. Andere locaties moeten op alternatieve manieren worden beheerd.Volgende objectNotitiesOKObject inspecteurOpen Assistent automatisch wanneer het waarschuwingen voor je code heeftOpen Assistent automatisch wanneer het programma crasht met een uitzonderingThonny-gegevensmap openen ...Open de programmamap van Thonny ...Stapelweergave automatisch openen en sluitenOpen afspeler...Open systeem shell ...Open het dialoogvenster voor het installeren of upgraden van MicroPython op je apparaatOpen...Opent de stapelweergave bij het eerste gesprek en sluit deze wanneer het programma terugkeert naar het hoofdframe.Opties ...UitHoofdlijnenOverOverschrijven?Thema '% s' overschrijvenPakketPakket '{}' is vereist voor het installeren en verwijderen van andere pakketten.Pakketten mapPlakkenVoer MyPy-controles uitVoer geselecteerde Pylint-controles uitControleer je spelling!PlotterPlotter visualiseert series van nummers gedrukt naar de Shell.PoortGewenste debuggerPresenteer Python REPL na afloop van het programmaVoorbeeldVorige objectAfdrukken...Programma argumentenProgramma argumenten:ProgrammaboomPyPI-paginaPygame Zero modusPython-interpretersAfsluitenEcht deïnstalleren?Recente bestandenAanbevolen maximale regellengte (Stel in op 0 om de margeregel uit te schakelen)Opnieuw doenVerversenNormale modusHernoemen...Open alle bestanden van de vorige sessie opnieuwVervangenVervang allesVervangen door:Vervang+VindMeld problemenVereistVereist:HervattenUitvoerenUitvoeren & DebuggenUitvoeren / hervattenVoer huidige script uitVoer huidige script in terminal uitUitvoeren tot cursorActief script wordt uitgevoerd in terminalOpslaanOpslaan als...Kopie opslaan...Zie Help voor meer informatie.Selecteer allesSelecteer allesSelecteer lege map voor nieuwe virtuele omgevingSelecteer een bestaande of maak een nieuwe lege mapSelecteer interpreterGeselecteerde map is niet leeg. Selecteer een andere of annuleer.Stuur EOF / Soft rebootShellPlotter tonenFunctieoproepen (frames) weergeven in afzonderlijke venstersToon regelnummersIngedrukte tekst (% d tekens)StapelBegin door het pakket aan de linkerkant te selecteren.Stap achteruitStap inStap uitStap overStoppenStoppen/Opnieuw starten backendSamenvattingOverschakelen naar standaard modusSyntaxis themaDoelwit:TerminalTerminal-emulatieHet antwoord isHet proces loopt nog steeds. Weet je zeker dat je dit wilt annuleren?Dezelfde interpreter die Thonny uitvoert (standaard)De opgegeven tekst is niet gevonden!Thema & LettertypeDit vak is bedoeld voor je werknotities -- toewijzingsinstructies, codefragmenten, wat dan ook. Alles wordt automatisch opgeslagen en geladen wanneer je de volgende keer Thonny opent. Verwijder deze tekst gerust om ruimte te maken voor je eigen notities.Deze computerDit dialoogvenster is voor het beheer van Thonny-plug-ins en hun afhankelijkheden. Als je pakketten voor je eigen programma's wilt installeren, kies je 'Extra → Pakketten beheren ...'In dit dialoogvenster worden alle beschikbare pakketten weergegeven, maar kun je alleen pakketten upgraden en verwijderen vanDit is een opmerkingDit pakket vereist een andere Thonny-versie:Dit programma wordt geleverd met ABSOLUUT GEEN GARANTIE! Het is gratis software en u bent van welkom om het te herdistribueren onder bepaalde voorwaarden, zie https://opensource.org/licenses/MIT voor detailsDeze virtuele omgeving wordt automatisch onderhouden door Thonny. Thonny optiesThonny plug-insThonny plug-in zonder vereistenWissel commentaarHulpmiddelenProbeer de poort automatisch te detecterenUI-modusUI-schaalfactorUI-themaSchakel het selectievakje uit als je een meer traditionele ervaring wilt.Commentaar uitOngedaan makenDeïnstallerenOngeschikte vereistenOmhoogUpgradeUpgrade afhankelijkhedenUpgrade of verwijderGebruik de opdracht "Stop" als je debuggen wilt stoppenVariabelenVersiegeschiedenisTe installeren versie:WeergaveWelke interpreter of welk apparaat moet Thonny gebruiken voor het uitvoeren van je code?Met de huidige interpreter kun je hier alleen door de pakketten bladeren. Gebruik 'Tools → Open systeem shell ...' voor het installeren, upgraden of verwijderen.Tekst omloop (mogelijk traag)Je kunt dit dialoogvenster nu sluiten.Je moet invullenJe moet een bestand selecteren!Staat je interpreter niet in de lijst?Zoomalle bestandenbla, blaexacte pakketnaamhierzoek je apparaatnaam, "USB Serial" of "UART"micro:bit locatie:even geduld aubpython programmabestandondersteunt basis ANSI-kleuren en stijlenom het pakketbestand te zoeken en te installeren (meestal met de extensie .whl, .tar.gz of .zip).om het bestand requirements.txt te vinden en de daarin gespecificeerde pakketten te installeren.unclosed_stringpakketten van gebruikerssitesvirtuele omgevingthonny-3.2.7/thonny/locale/nl_NL/LC_MESSAGES/thonny.po0000644000175000017500000011664713611773167023333 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: nl\n" #: thonny/workbench.py:355 msgid "File" msgstr "Bestand" #: thonny/workbench.py:356 msgid "Edit" msgstr "Bewerken" #: thonny/workbench.py:357 msgid "View" msgstr "Weergave" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Uitvoeren" #: thonny/workbench.py:360 msgid "Tools" msgstr "Hulpmiddelen" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Help" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Alternatieve Python 3-interpreter of virtuele omgeving" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Een speciale virtuele omgeving (verouderd)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Afsluiten" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Verminder de lettergrootte" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Focus editor" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Focus shell" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Maximaliseer weergave" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Volledig scherm" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Programma argumenten" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "Over Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Gemaakt in\n" "Universiteit van Tartu, Estland,\n" "met de hulp van\n" "open-source gemeenschap,\n" "Raspberry Pi Foundation\n" "en Cybernetica AS" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Dit programma wordt geleverd met\n" "ABSOLUUT GEEN GARANTIE!\n" "Het is gratis software en u bent van welkom om het te herdistribueren onder bepaalde voorwaarden, zie\n" "https://opensource.org/licenses/MIT\n" "voor details" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Versiegeschiedenis" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Meld problemen" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Open Assistent automatisch wanneer het programma crasht met een uitzondering" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Open Assistent automatisch wanneer het waarschuwingen voor je code heeft" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Voer geselecteerde Pylint-controles uit" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Voer MyPy-controles uit" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Uitgeschakelde controles (één ID per regel)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Assistent" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Automatisch aanvullen" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Welke interpreter of welk apparaat moet Thonny gebruiken voor het uitvoeren van je code?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Interpreter" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "Over Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye is een Python-debugger die afzonderlijk moet worden geïnstalleerd.\n" "\n" "Wil je de helppagina openen en meer te weten komen?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Debug huidige script (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Wissel commentaar" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Commentaar aan" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Commentaar uit" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Ongedaan maken" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Opnieuw doen" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Knippen" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Kopiëren" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Plakken" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Selecteer alles" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Uitvoeren tot cursor" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Kan nog niet sluiten" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Gebruik de opdracht \"Stop\" als je debuggen wilt stoppen" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Dock gebruikersvensters" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Markeer overeenkomende namen" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Markeer lokale variabelen" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Markeer haakjes" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Markeer syntaxiselementen" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Markeer huidige regel (vereist opnieuw openen van de editor)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Code aanvullen toestaan met Tab-toets in editors" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Code aanvullen toestaan met Tab-toets in Shell" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Toon regelnummers" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Aanbevolen maximale regellengte\n" "(Stel in op 0 om de margeregel uit te schakelen)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Editor" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Gebruikslogs exporteren ..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Evenementen" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Bestanden" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Zoeken & Vervangen" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Vind:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Vervangen door:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Hoofdlettergevoelig" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Omhoog" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Naar beneden" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Vinden" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Vervangen" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Vervang+Vind" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Vervang alles" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Voer de te vervangen reeks in." #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "De opgegeven tekst is niet gevonden!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Sta slechts één Thonny-instantie toe" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Open alle bestanden van de vorige sessie opnieuw" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Schakel meldingsgeluid uit" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Modus voor het schalen van lettertypen" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Heap-modus is ingeschakeld.\n" "Sluit de Heap-weergave om deze uit te schakelen." #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Heap" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Taal" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Dit vak is bedoeld voor je werknotities -- toewijzingsinstructies, codefragmenten, wat dan ook.\n" "\n" "Alles wordt automatisch opgeslagen en geladen wanneer je de volgende keer Thonny opent.\n" "\n" "Verwijder deze tekst gerust om ruimte te maken voor je eigen notities." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Notities" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Vorige object" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Volgende object" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Object inspecteur" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "Hoofdlijnen" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Pygame Zero modus" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Zoek pakket van PyPI" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Deïnstalleren" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Sluiten" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Klik " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "hier" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Upgrade" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Installeren" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Kan het pakket van PyPI niet vinden." #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "exacte pakketnaam" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Laatste stabiele versie" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Laatste versie" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Samenvatting" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Auteur" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Startpagina" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Bugtracker" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Documentatie" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "PyPI-pagina" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Vereist" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Echt deïnstalleren?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Weet je zeker dat je het wilt deïnstalleren?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Terug naar\n" "huidige frame" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Variabelen" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Deze computer" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Verversen" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Focus in" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Fout" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Je moet een bestand selecteren!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Overschrijven?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Wil je '% s' overschrijven?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Nieuw" #: thonny/code.py:526 msgid "Open..." msgstr "Open..." #: thonny/code.py:528 msgid "Load" msgstr "Laden" #: thonny/code.py:537 msgid "Recent files" msgstr "Recente bestanden" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Sluit alles" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Opslaan" #: thonny/code.py:583 msgid "Save as..." msgstr "Opslaan als..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Kopie opslaan..." #: thonny/code.py:603 msgid "Rename..." msgstr "Hernoemen..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Thonny opties" #: thonny/running.py:94 msgid "Run current script" msgstr "Voer huidige script uit" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Voer huidige script in terminal uit" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Stoppen/Opnieuw starten backend" #: thonny/running.py:139 msgid "Stop" msgstr "Stoppen" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Onderbreek uitvoering" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Stuur EOF / Soft reboot" #: thonny/running.py:172 msgid "Disconnect" msgstr "Loskoppelen" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Bekende interpreters" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Staat je interpreter niet in de lijst?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Zoek een andere" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "python programmabestand" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "NB! Thonny ondersteunt alleen Python 3.5 en hoger" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Maak een nieuwe virtuele omgeving" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Selecteer een bestaande of maak een nieuwe lege map" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Python-interpreters" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "alle bestanden" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Selecteer lege map voor nieuwe virtuele omgeving" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Onjuiste map" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "Geselecteerde map is niet leeg.\n" "Selecteer een andere of annuleer." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Bezig met maken virtuele omgeving" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Shell leegmaken" #: thonny/shell.py:126 msgid "Plotter" msgstr "Plotter" #: thonny/shell.py:245 msgid "Clear" msgstr "Leegmaken" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Plotter tonen" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Om prestatieredenen vermijdt Shell dat hele lange lijnen volledig worden weergegeven (zie Extra => Opties => Shell).\n" "Hier kun je het originele tekstfragment bekijken en wijzigen." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "Tekst omloop (mogelijk traag)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Kopieer naar klembord" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Uitvouwen in Shell" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Ingedrukte tekst (% d tekens)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Plotter visualiseert series van\n" "nummers gedrukt naar de Shell." #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Zie Help voor meer informatie." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Anderen sluiten" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Bezig met kopiëren" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Bezig met kopiëren\n" "  % s\n" "naar\n" "  % s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Annuleren" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "OK" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Het proces annuleren?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Het proces loopt nog steeds.\n" "Weet je zeker dat je dit wilt annuleren?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Selecteer alles" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Shell" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Dezelfde interpreter die Thonny uitvoert (standaard)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Deze virtuele omgeving wordt automatisch onderhouden door Thonny.\n" "" #: thonny/workbench.py:532 msgid "Location: " msgstr "Locatie: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Opties ..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Vergroot de lettergrootte" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Verander lettergrootte" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Zoom" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Thonny afsluiten" #: thonny/workbench.py:663 msgid "Quit" msgstr "Afsluiten" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "Thema '% s' overschrijven" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Programma argumenten:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Normale modus" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "Configuratie is bijgewerkt. Start Thonny opnieuw om te beginnen met werken in de normale modus.\n" "\n" "(Zie 'Extra → Opties → Algemeen' als je later van gedachten verandert.)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Programmaboom" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Selecteer interpreter" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Hervatten" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Uitvoeren / hervatten" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Debug huidige script" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Debuggen" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Debug huidige script (mooier)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Debug huidige script (sneller)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Stap over" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "Over" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "Stap in" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "In" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Stap uit" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "Uit" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Stap achteruit" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Terug" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Stapel" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Uitzondering" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Log programmagebruik gebeurtenissen" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Debugmodus (biedt meer gedetailleerde diagnostische logs)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "UI-modus" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "UI-schaalfactor" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "NB! Start Thonny opnieuw na het wijzigen van deze opties!" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Algemeen" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "INSTALLEREN" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Blader door de pakketten" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Met de huidige interpreter kun je hier alleen door de pakketten bladeren.\n" "Gebruik 'Tools → Open systeem shell ...' voor het installeren, upgraden of verwijderen." #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Pakketten map" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Installeren vanuit PyPI" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Als je niet weet waar je het pakket kunt krijgen, wil je waarschijnlijk de Python-pakketindex doorzoeken. Begin door de naam van het pakket in het bovenstaande zoekvak in te voeren en op ENTER te drukken." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "om het bestand requirements.txt te vinden en de daarin gespecificeerde pakketten te installeren." #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Klik" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "om het pakketbestand te zoeken en te installeren (meestal met de extensie .whl, .tar.gz of .zip)." #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Upgrade of verwijder" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Begin door het pakket aan de linkerkant te selecteren." #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Doelwit:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "virtuele omgeving" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "pakketten van gebruikerssites" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "In dit dialoogvenster worden alle beschikbare pakketten weergegeven, maar kun je alleen pakketten upgraden en verwijderen van" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Nieuwe pakketten worden ook in deze map geïnstalleerd. Andere locaties moeten op alternatieve manieren worden beheerd." #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Geïnstalleerde versie:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Geïnstalleerd op:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Controleer je spelling!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "Je moet invullen" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Kan de pakketinformatie van PyPI niet vinden." #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Foutcode:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Kan de pakketnaam niet vinden in de lijst:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Pakket '{}' is vereist voor het installeren en verwijderen van andere pakketten." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Pakket" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Beheer pakketten voor %s" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Bevestiging" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Het lijkt erop dat je een Thonny-gerelateerd pakket installeert.\n" "Als je een Thonny-plug-in bedoelde te installeren, zou je 'Tools → Plug-ins beheren ...' moeten kiezen.\n" "\n" "Weet je zeker dat je %s wilt installeren voor de back-end?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "NB! Er is mogelijk een andere versie beschikbaar die compatibel is met de huidige Thonny-versie. Klik op de knop '...' om de te installeren versie te kiezen." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Thonny plug-in zonder vereisten" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Het lijkt erop dat je een verouderde Thonny plug-in probeert te installeren\n" "(het specificeert geen vereiste Thonny-versie).\n" "\n" "Als je het nog steeds wilt, installeer het dan vanaf de opdrachtregel." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Ongeschikte vereisten" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "Dit pakket vereist een andere Thonny-versie:" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Als je het nog steeds wilt, installeer het dan vanaf de opdrachtregel." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(In dit geval gebruikt Thonny's back-end dezelfde interpreter, dus beide dialoogvensters beheren dezelfde pakketten.)" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "NB! Je moet Thonny opnieuw opstarten na het installeren / upgraden / verwijderen van een plug-in." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Thonny plug-ins" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Geavanceerde installatie / upgrade / downgrade" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Gewenste versie" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Upgrade afhankelijkheden" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Vereist:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Fout:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Pakketten beheren..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Plug-ins beheren..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "Open afspeler..." #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Wijzig werkmap naar scriptmap bij Uitvoeren / Debuggen" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Functieoproepen (frames) weergeven in afzonderlijke vensters" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "Schakel het selectievakje uit als je een meer traditionele ervaring wilt." #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "Stapelweergave automatisch openen en sluiten" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "Opent de stapelweergave bij het eerste gesprek en sluit deze wanneer het programma terugkeert naar het hoofdframe." #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "Stappen in bibliotheken toestaan (d.w.z. buiten de hoofdscriptmap)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Kan debuggen langzamer maken." #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Gewenste debugger" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(gebruikt bij het klikken op de werkbalkknop Debuggen)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Birdseye-poort" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(start Thonny opnieuw nadat je dit hebt gewijzigd)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Uitvoeren & Debuggen" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Terminal-emulatie" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "ondersteunt basis ANSI-kleuren en stijlen" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Maximaal aantal te behouden regels." #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "NB! Grote waarden kunnen slechte prestaties veroorzaken!" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Maximale lengte van lijnfragmenten voor het knijpen" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Actief script wordt uitgevoerd in terminal" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Presenteer Python REPL na afloop van het programma" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Houd het terminalvenster open nadat het Python-proces is beëindigd" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "NB! Automatisch sluiten moet worden ingeschakeld in de instellingen van Terminal\n" "(Profielen → Shell → Wanneer de shell wordt afgesloten)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Terminal" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "UI-thema" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Syntaxis thema" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Editor lettertype" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "IO-lettertype" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Voorbeeld" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "Dit is een opmerking" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "Het antwoord is" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "unclosed_string" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "bla, bla" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "NB! Sommige stijlelementen veranderen pas nadat Thonny opnieuw is opgestart!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Voer een geheel getal in" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Thema & Lettertype" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Open de programmamap van Thonny ..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Thonny-gegevensmap openen ..." #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Startlocatie" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Help-inhoud" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "CircuitPython-apparaat" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "MicroPython-apparaat" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Sluit je apparaat aan op de computer en selecteer de bijbehorende poort hieronder" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "zoek je apparaatnaam, \"USB Serial\" of \"UART\"" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Als je het niet kunt vinden, moet je mogelijk eerst het juiste USB-stuurprogramma installeren." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Poort" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Probeer de poort automatisch te detecteren" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython (generiek)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Afdrukken..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Open systeem shell ..." #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Details" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Installeren vanuit het vereistenbestand" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Installeren vanuit lokaal bestand" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "Dit dialoogvenster is voor het beheer van Thonny-plug-ins en hun afhankelijkheden.\n" "Als je pakketten voor je eigen programma's wilt installeren, kies je 'Extra → Pakketten beheren ...'" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (generiek)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Geselecteerde lijnen inspringen" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Geselecteerde lijnen uitspringen" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Overschakelen naar\n" "standaard\n" "modus" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "Zorg ervoor dat MicroPython op je micro:bit is geïnstalleerd." #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "Vergeet niet dat main.py alleen werkt zonder ingesloten hoofdscript." #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "Installeer de nieuwste MicroPython op BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "micro:bit locatie:" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Te installeren versie:" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "even geduld aub" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "NB! Alle bestanden op micro:bit worden verwijderd!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Installeren ..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Klaar!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Je kunt dit dialoogvenster nu sluiten." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "firmware" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "Open het dialoogvenster voor het installeren of upgraden van MicroPython op je apparaat" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "Kon schijf '%s' niet vinden." #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "Zorg ervoor dat je micro:bit hebt aangesloten!" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Wil je doorgaan en zelf de schijf zoeken?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "Kon schijf '%s' niet vinden. Wil je het zelf opzoeken?" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Verschillende '%s' schijven gevonden. Wil je er zelf een kiezen?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Kan geen geschikte schijf vinden" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "" #: thonny/code.py:203 msgid "Loading" msgstr "" #: thonny/code.py:297 msgid "Saving" msgstr "" #: thonny/running.py:1408 msgid "Working..." msgstr "" #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "" thonny-3.2.7/thonny/locale/uk_UA/0000755000175000017500000000000013611777205017647 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/uk_UA/LC_MESSAGES/0000755000175000017500000000000013611777205021434 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/uk_UA/LC_MESSAGES/thonny.mo0000644000175000017500000010350613611773167023320 0ustar annamaaannamaa00000000000000V ||}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/;; ;><V/=^== =O>kS>m>U-??_@Ap@@ @@ @:@'1AYA B2BRB*eB;BBBC "C(CC(lCoCD D?D!PDrD{DDDDD4DF}5FF$FF!G0$GfUG4GNGC@H:HHH2H=IAVI?IaI*:J=eJJJJJ'J.KENKKNK.K4+L`L[yLLLL# M 1M>MOMmM-MMMM MM NN(+NATNN!N N N"NN O(O&9O`O$tO2OVOd#QQQQiQ$R5RsOR6R>R.9S@hS SSS9S%TTU,^V?VVV7V37WDkWW$WW X%'XMXrPX)XX.Y0YLYcY|YYLY{Y$x[\V]C ^/M^(}^*^^Z^OA_8_ __`*`(D`m`C``yaX%b~~bb6cddddeee"eejpf4f)gY:g g5ggphhMicifi oizi(i iyiBj`jqj)zj9j?j kd+kkHkPk%3l Yl zl#l$lllmm#1m Um`mmm0nCnRnpnVnnno"%o,Houo ooo,o)o0pFDp$pDppqq>q<Sqqqnqe-r)rkrL)svss^s.t 3t5@tvt6tt t ttt= uJuguAxu6u uu# v0vxFvWv2wJw`wJy.cyzM{Bc{E{g|T}n}3})}}C}=;~4y~~i~6Sf- )$#7k[ ǀԀ* ()ՁN5`*E':L["dV#& *0E[:Ć7)%d items(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)(restart Thonny after changing this)(used when clicking Debug toolbar button)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAdvanced install / upgrade / downgradeAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAllow stepping into libraries (ie. outside of main script directory)Alternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portBrowse the packagesBugtrackerCan't close yetCan't find package name from the list:Can't find suitable diskCancelCancel the process?Case sensitiveChange font sizeChange working directory to script directory on Run / DebugCircuitPython (generic)CircuitPython deviceClearClear shellClickClick CloseClose allClose othersComment outConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)ConfirmationConnect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find disk '%s'.Could not find disk '%s'. Do you want to locate it yourself?Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDeleteDeleting %sDesired versionDetailsDirectory propertiesDisable notification soundDisabled checks (one id per line)DisconnectDo you want to continue and locate the disk yourself?Do you want to overwrite '%s' ?Dock user windowsDocumentationDon't forget that main.py only works without embedded main script.Done!DownDownload to %sDownloading %s to %sEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFile propertiesFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus intoFocus shellFont scaling modeFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: uk %d елементів(В цьому випадку бэкенд Thonny буде використовувати той же інтерпретатор, таким чином обидва способа будуть управляти одним й тим же набором пакетів.)(перезапустіть Thonny після цих змін)(використовується при кліку кнопки Налагодити)Особливе віртуальне середовище (не рекомендується)Про BirdseyeПро ThonnyПросунуте встановлення / оновлення / відкатДозволити використання «Tab» для автозавершення в оболонціДозволити використання «Tab» для автозавершення в редакторіДозволити запускати тільки один екземпляр ThonnyДозволити перехід до біблиотек (тобто до модулі за межами каталога програми)Інший інтерпретатор Python 3 або віртуальне середовищеВи впевнені, що бажаєте видалити це?АсистентАвторАвтозавершенняНазадПовернутися до поточного вікнаНеправильний каталогBirdseye — це налагоджувач Python, який потребує окремого встановлення. Відкрити сторінку допомоги для подробиць?Порт BirdseyeПерегляд пакетівБагтрекерПоки неможливо закритиІм'я пакету не знайдено в списку:Не вдалося знайти диск, що підходитьСкасуватиСкасувати процес?З урахування регіструЗмінити розмір шрифтаЗмініть робочий каталог для програми в Запуск / НалагодженняCircuitPython (общий)Пристрій CircuitPythonОчиститиОчистити оболонкуКлікКлацнути ЗакритиЗакрити всеЗакрити іншіЗакоментуватиКонфігурація була оновлена. Перезапустіть Thonny для роботы в звичайному режимі. (Зайдіть в «Інструменти → Параметри → Загальні», якщо ви забажаєте змінити своє рішення)ПідтвердженняПідключіть пристрій до комп'ютера та оберіть відповідний порт нижчеСкопіюватиКопіювати до буфераКопіюванняКопіювання %s в %sНе вдалось знайти диск «%s»Не вдалось знайти диск «%s». Бажаєте вибрати його вручну?Не вдалося знайти пакет в PyPI Пошук цього пакету в PyPI не дав результатів.Створити нове віртуальне середовищеСтворити віртуальне середовищеВирізатиНалагодитиНалагодити поточний скриптНалагодити поточний скрипт (birdseye)Налагодити поточний скрипт (швидше)Налагодити поточний скрипт (краще)Режим налагодження (надає більш докладну інформацію)Зменшити розмір шрифтаЗменшити відступ вибраних рядківВидалитиВидалення %sБажана версіяПодробиціВластивості каталогуВимкнути звук сповіщенняВимкнути перевірки (один код на рядок)ВідключитисяБажаєте продовжити та вибрати диск вручну?Бажаєте перезаписати '%s' ?Закріпити вікно користувачаДокументаціяНе забудьте, що main.py працює без вбудованого main-script.Зроблено!ВнизЗавантажити в %sЗавантаження %s до %sПравкаРедакторШрифт редактораВведіть числоВведіть рядок для заміниПомилкаКод помилки:Помилка:ПодіїВиключенняВихідВийти з ThonnyРозгорнути в оболонціЕкспортувати журнал використання...ФайлВластивості файлуФайлиЗнайтиЗнайти та замінитиЗайти пакет в PyPIЗнайти:ПрошивкаПерейти до редактораПерейти доПерейти до оболонкиРежим масштабування шрифтаЧерез продуктивність оболонка уникає відображення дуже довгих рядків повністю (дивиться Інструменти => Параметри => Оболонка). Тут ви можете взаємодіяти з оригінальним фрагментом тексту.Знайдено кілька «%s» дисків. Бажаєте вибрати один з них?Повний екранЗагальніКупаРежим купи ввімкнений. Закрийте вікно купи для вимкнення.ДопомогаЗміст довідкиПідсвічувати поточний рядок (необхідний перезапуск редактора)Підсвічувати локальні змінніПідсвічувати імена, що збігаютьсяПідсвічувати парні дужкиПідсвічувати синтаксичні елементиДодомуДомашня сторінкаВСТАНОВИТИШрифт вікна введення-виведенняЯкщо ви не можете знайти його, спробуйте спочатку встановити відповідний драйвер USB.Якщо ви не знаєте, де взяти пакет, тоді, скоріше за все, вам слід пошукати в Python Package Index. Почніть з введення імені пакета у вікні пошуку вище та натисніть ENTER.Якщо ви дійсно цього бажаєте, тоді встановіть пакет з командного рядка.Збільшити розмір шрифтаЗбільшити відступ вибраних рядківІнсталюватиВстановити з PyPIВстановити з локального файлуВстановити з файлу requirements.txtВстановіть останній MicroPython на BBC micro:bitВстановлено в:Встановлена версія:Встановлення...ІнтерпретаторПерервати виконанняВЗалишати вікно терминалу відкритим після завершення програмиВідомі інтерпретаториМова (Language)Остання стабільна версіяОстання версіяЗавантажитиЗавантаженняЗнайти іншийРозташування: Записувати виконання програми до журналуСхоже, ви бажаєте встановити пакет, що стосується Thonny. Якщо ви бажаєте встановити плагин для Thonny, тоді використовуйте «Інструменти → Управління плагинами...» Ви впевнені, що бажаєте встановити %s для бэкенду?Схоже, ви бажаєте встановити стару версію плагину для Thonny (в ній не вказана версія Thonny). Якщо ви дійсно цього бажаєте, тоді встановіть плагин з командного рядка.Розроблено в Тартуському университеті, Естонія, за участю співтовариства вільного програмного забезпечення, фонду розробки Raspbery Pi та компанії Cybernetica Впевніться, що MicroPython встановлений на ваш micro:bit.Впевніться, що ваш micro:bit підключений!Управління пакетами для %sУправління пакетами...Управління плагинами...РазгорнутиМаксимальна довжина рядку, що підлягає стисканнюМаксимальна кількість рядків, що лишаютьсяМоже уповільнити налагоджувачMicroPython (загальний)Пристрій MicroPythonЗміненийПеремістити до КорзиниПеремістити до МусоруПеренесення %s в %sNB! Всі файли на micro:bit будуть видаленв!NB! Автоматичне закриття повинно бути ввімкнено в налаштуваннях терминалу (Профілі → Оболонка → При виході з оболонки)NB! Великі значення можуть призвести до погіршення продуктивності!NB! Перезапустіть Thonny після зміни цих параметрів!NB! Деякі елементи оформлення зміняться тільки після перезапуску Thonny!NB! Може бути доступна інша версія, сумісна з поточною версією Thonny. Клацніть кнопку «...» щоб обрати версію для встановлення.NB! Thonny підтримує Python 3.5 та вищеNB! Треба перезапустити Thonny після встановлення, оновлення або видалення плагину.НовеНовий каталогНові пакети також будуть встановлені в цей каталог. Для інших цілей каталоги необхідно налаштувати.наступний об'єкаПриміткиOKІнспектор об'єктівАвтоматично відкривати вікно Асистента при виявлені попереджень в вашій програміАвтоматично відкривати вікно Асистента при збої програмиВідкрити каталог даних Thonny...Відкрити каталог Thonny...Автоматично відкривати та закривати вікна стекуВідкрити повтор...Відкрити системну оболонку...Відкрити вікно для встановлення або оновлення MicroPython на вашому пристроїВідкрити...Відкриває вікно стеку при першому виклику та закриває його, коли програма повертається до зовнішнього блоку.Параметри...ЗПланЧерезПерезаписати?Перезаписати тему «%s»ПакетПакет «{}» необхідний для встановлення та видалення інших пакетів.Каталог апкетівВставитиШляхВиконати перевірки MyPy Виконати вибрані перевірки PylintПеревірте правильність написання!ПлотерПлоттер показує серії чисел, що надруковані в оболонціПортНалагоджувач, якому надається перевагаПерейти до Python REPL після завершення програмиПопередній переглядПопередній об'єктДрук...Аргументи програмиПараметри програми:Дерево програмиВласитвостіСторінка PyPIРежим Pygame ZeroІнтерпретатори PythonВийтиДійсно видалити?Нещодавні файлиРекомендована максимальна довжина рядка (вкажіть 0 для вимкнення границь рядка)ПовторитиОновитиЗвичайний режимПерейменувати...Знову відкрити всі файли з попереднього сеансуЗамінитиЗамінити всеЗамінити на:Знайти та замінитиПовідомити про проблемуЗалежностіТреба:ПродовжитиВиконатиЗапустити та налагодитиЗапустити / продовжитиЗапустити поточний скриптЗапустити поточний скрипт в терміналіВиконати до курсораЗапуск поточної програми в терминаліЗберегтиЗберегти як...Зберегти копію...ЗберіганняДивіться Допомогу для подробиць.Вибрати всеВиділити всеОбрати порожній каталог для нового віртуального середовищаВиберіть каталог, що існує, або створіть новий порожнійОберіть інтерпретаторВибраний каталог не порожній. Вибрати інший або скасувати.Надіслати EOF / програмне перезавантаженняОболонкаПоказати ПлотерПоказувати виклики функцій (фрейми) в різних вікнахПоказувати номери рядківрозмірПропущений текст (%d символів)СтекПочніть з вибору пакету зліваКрок назадЗайтиВийтиПерестрибнутиЗупинитиЗупинити та перезапустити бекендМісце в сховищіЗведенняПеремикнутися до звичайного режимуТема підсвітлення синтаксисуЦіль:ТерміналЕмуляція терміналуВідповідю єПроцес все ще виконується. Ви впевнені, що бажаєте скасувати його?Той же інтерпретатор, що й у Thonny (за замовчанням)Вказаний текст не знайдено!Тема & шрифтЦе вікно можна використовувати для ваших робочих приміток — значень, прикладів коду, чого завгодно. Все, що ви тут напишете, буде автоматично зберігатися та завантажуватися при перезапуску Thonny. Цей текст можна сміливо видалити та почати писати свої власні примітки.Цей комп'ютерЦе вікно для управління плагинами та залежностями Thonny. Якщо ви бажаєте встановити пакети для ваших програм, тоді перейдіть до «Інструменти → Управління пакетами...»В цьому вікні перелічені всі доступні пакети, але доступні для оновлення та видалення тільки пакети зЦе коментарЦей пакет потребує іншої версії Thonny:Ця програма надається без будь-яких гарантійних зобов'язань Це вільне програмне забезпечення і ви можете вільно розповсюджувати його на умовах ліцензії МІТ https://opensource.org/licenses/MIT Це віртуальне середовище автоматично підтримується ThonnyПараметри ThonnyПлагини ThonnyПлагини Thonny без залежностейПеремикнути коментаріІнстументиСпробувати виявити порт автоматичноРежим інтерфейсу користувача (ІК)Коефіцієнт масштабування ІКТема інтерфейсуЗніміть відмітку якщо ви бажаєте більш традиційний стильРазкоментуватиСкасуватиДеінсталюватиНевідповідні залежностіВгоруОновитиОновлення залежностейОновити чи видалитиВивантажити до %sВивантаження %s до %sДля завершення налагодження використовуйте команду "Стоп"ЗмінніІсторія версійВерсія до встановленняВиглядЯкий інтерпретатор або який пристрій повинен використовувати Thonny для запуску вашої програми?Ви можете тільки переглядати пакети з цим інтерпретатором. Використовуйте 'Інструменти → Відкрити системну оболонку...' для встановлення, оновлення та видалення.Обробка...Переносити рядки (може уповільнити роботу)Зараз можна закрити це вікно.Необхідно ввестиВам треба вибрати файл!Ваш інтерпретатор відсутній у списку?Наблизитивсі файлибла, блабайтточна назва пакетутутзнайдіть им'я вашого пристрою, «USB Serial» або «UART»Розташування micro:bit:зачекайте будь ласкавиконуваний модуль pythonпідтримує основні ANSI-кольори та стилідля вказання та встановлення пакета з файлу (звичайно з розширенням .whl, .tar.gz або .zip).для вказання файлу requirements.txt та встановлення перерахованих в ньому пакетівнезакритий_рядокпакети з каталогу користувачавіртуальне середовищуthonny-3.2.7/thonny/locale/uk_UA/LC_MESSAGES/thonny.po0000644000175000017500000013733513611773167023332 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: uk\n" #: thonny/workbench.py:355 msgid "File" msgstr "Файл" #: thonny/workbench.py:356 msgid "Edit" msgstr "Правка" #: thonny/workbench.py:357 msgid "View" msgstr "Вигляд" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Виконати" #: thonny/workbench.py:360 msgid "Tools" msgstr "Інстументи" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Допомога" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Інший інтерпретатор Python 3 або віртуальне середовище" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Особливе віртуальне середовище (не рекомендується)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Вихід" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Зменшити розмір шрифта" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Перейти до редактора" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Перейти до оболонки" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Разгорнути" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Повний екран" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Аргументи програми" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "Про Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Розроблено в\n" "Тартуському университеті, Естонія,\n" "за участю співтовариства вільного\n" "програмного забезпечення,\n" "фонду розробки Raspbery Pi\n" "та компанії Cybernetica " #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Ця програма надається\n" "без будь-яких гарантійних зобов'язань\n" "Це вільне програмне забезпечення\n" "і ви можете вільно розповсюджувати\n" "його на умовах ліцензії МІТ\n" "https://opensource.org/licenses/MIT " #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Історія версій" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Повідомити про проблему" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Автоматично відкривати вікно Асистента при збої програми" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Автоматично відкривати вікно Асистента при виявлені попереджень в вашій програмі" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Виконати вибрані перевірки Pylint" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Виконати перевірки MyPy " #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Вимкнути перевірки (один код на рядок)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Асистент" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Автозавершення" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Який інтерпретатор або який пристрій повинен використовувати Thonny для запуску вашої програми?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Інтерпретатор" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "Про Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye — це налагоджувач Python, який потребує окремого встановлення.\n" "\n" "Відкрити сторінку допомоги для подробиць?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Налагодити поточний скрипт (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Перемикнути коментарі" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Закоментувати" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Разкоментувати" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Скасувати" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Повторити" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Вирізати" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Скопіювати" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Вставити" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Виділити все" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Виконати до курсора" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Поки неможливо закрити" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Для завершення налагодження використовуйте команду \"Стоп\"" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Закріпити вікно користувача" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Підсвічувати імена, що збігаються" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Підсвічувати локальні змінні" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Підсвічувати парні дужки" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Підсвічувати синтаксичні елементи" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Підсвічувати поточний рядок (необхідний перезапуск редактора)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Дозволити використання «Tab» для автозавершення в редакторі" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Дозволити використання «Tab» для автозавершення в оболонці" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Показувати номери рядків" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Рекомендована максимальна довжина рядка (вкажіть 0 для вимкнення границь рядка)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Редактор" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Експортувати журнал використання..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Події" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Файли" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Знайти та замінити" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Знайти:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Замінити на:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "З урахування регістру" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Вгору" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Вниз" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Знайти" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Замінити" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Знайти та замінити" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Замінити все" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Введіть рядок для заміни" #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "Вказаний текст не знайдено!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Дозволити запускати тільки один екземпляр Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Знову відкрити всі файли з попереднього сеансу" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Вимкнути звук сповіщення" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Режим масштабування шрифта" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Режим купи ввімкнений.\n" "Закрийте вікно купи для вимкнення." #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Купа" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Мова (Language)" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Це вікно можна використовувати для ваших робочих приміток — значень, прикладів коду, чого завгодно.\n" "\n" "Все, що ви тут напишете, буде автоматично зберігатися та завантажуватися при перезапуску Thonny.\n" "\n" "Цей текст можна сміливо видалити та почати писати свої власні примітки." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Примітки" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Попередній об'єкт" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "наступний об'єка" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Інспектор об'єктів" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "План" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Режим Pygame Zero" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Зайти пакет в PyPI" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Деінсталювати" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Закрити" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Клацнути " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "тут" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Оновити" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Інсталювати" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Не вдалося знайти пакет в PyPI " #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "точна назва пакету" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Остання стабільна версія" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Остання версія" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Зведення" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Автор" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Домашня сторінка" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Багтрекер" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Документація" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "Сторінка PyPI" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Залежності" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Дійсно видалити?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Ви впевнені, що бажаєте видалити це?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Повернутися до \n" "поточного вікна" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Змінні" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Цей комп'ютер" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Оновити" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Перейти до" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Помилка" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Вам треба вибрати файл!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Перезаписати?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Бажаєте перезаписати '%s' ?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Нове" #: thonny/code.py:526 msgid "Open..." msgstr "Відкрити..." #: thonny/code.py:528 msgid "Load" msgstr "Завантажити" #: thonny/code.py:537 msgid "Recent files" msgstr "Нещодавні файли" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Закрити все" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Зберегти" #: thonny/code.py:583 msgid "Save as..." msgstr "Зберегти як..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Зберегти копію..." #: thonny/code.py:603 msgid "Rename..." msgstr "Перейменувати..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Параметри Thonny" #: thonny/running.py:94 msgid "Run current script" msgstr "Запустити поточний скрипт" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Запустити поточний скрипт в терміналі" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Зупинити та перезапустити бекенд" #: thonny/running.py:139 msgid "Stop" msgstr "Зупинити" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Перервати виконання" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Надіслати EOF / програмне перезавантаження" #: thonny/running.py:172 msgid "Disconnect" msgstr "Відключитися" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Відомі інтерпретатори" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Ваш інтерпретатор відсутній у списку?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Знайти інший" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "виконуваний модуль python" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "NB! Thonny підтримує Python 3.5 та вище" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Створити нове віртуальне середовище" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Виберіть каталог, що існує, або створіть новий порожній" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Інтерпретатори Python" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "всі файли" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Обрати порожній каталог для нового віртуального середовища" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Неправильний каталог" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "Вибраний каталог не порожній.\n" "Вибрати інший або скасувати." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Створити віртуальне середовище" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Очистити оболонку" #: thonny/shell.py:126 msgid "Plotter" msgstr "Плотер" #: thonny/shell.py:245 msgid "Clear" msgstr "Очистити" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Показати Плотер" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Через продуктивність оболонка уникає відображення дуже довгих рядків повністю (дивиться Інструменти => Параметри => Оболонка).\n" "Тут ви можете взаємодіяти з оригінальним фрагментом тексту." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "Переносити рядки (може уповільнити роботу)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Копіювати до буфера" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Розгорнути в оболонці" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Пропущений текст (%d символів)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Плоттер показує серії чисел, що надруковані в оболонці" #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Дивіться Допомогу для подробиць." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Закрити інші" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Копіювання" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Копіювання\n" " %s\n" "в\n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Скасувати" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "OK" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Скасувати процес?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Процес все ще виконується. Ви впевнені, що бажаєте скасувати його?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Вибрати все" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Оболонка" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Той же інтерпретатор, що й у Thonny (за замовчанням)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Це віртуальне середовище автоматично підтримується Thonny" #: thonny/workbench.py:532 msgid "Location: " msgstr "Розташування: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Параметри..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Збільшити розмір шрифта" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Змінити розмір шрифта" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Наблизити" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Вийти з Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "Вийти" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "Перезаписати тему «%s»" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Параметри програми:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Звичайний режим" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "Конфігурація була оновлена. Перезапустіть Thonny для роботы в звичайному режимі.\n" "\n" "(Зайдіть в «Інструменти → Параметри → Загальні», якщо ви забажаєте змінити своє рішення)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Дерево програми" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Оберіть інтерпретатор" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Продовжити" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Запустити / продовжити" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Налагодити поточний скрипт" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Налагодити" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Налагодити поточний скрипт (краще)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Налагодити поточний скрипт (швидше)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Перестрибнути" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "Через" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "Зайти" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "В" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Вийти" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "З" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Крок назад" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Назад" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Стек" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Виключення" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Записувати виконання програми до журналу" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Режим налагодження (надає більш докладну інформацію)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "Режим інтерфейсу користувача (ІК)" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "Коефіцієнт масштабування ІК" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "NB! Перезапустіть Thonny після зміни цих параметрів!" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Загальні" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "ВСТАНОВИТИ" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Перегляд пакетів" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Ви можете тільки переглядати пакети з цим інтерпретатором.\n" "Використовуйте 'Інструменти → Відкрити системну оболонку...' для встановлення, оновлення та видалення." #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Каталог апкетів" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Встановити з PyPI" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Якщо ви не знаєте, де взяти пакет, тоді, скоріше за все, вам слід пошукати в Python Package Index. Почніть з введення імені пакета у вікні пошуку вище та натисніть ENTER." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "для вказання файлу requirements.txt та встановлення перерахованих в ньому пакетів" #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Клік" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "для вказання та встановлення пакета з файлу (звичайно з розширенням .whl, .tar.gz або .zip)." #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Оновити чи видалити" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Почніть з вибору пакету зліва" #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Ціль:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "віртуальне середовищу" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "пакети з каталогу користувача" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "В цьому вікні перелічені всі доступні пакети, але доступні для оновлення та видалення тільки пакети з" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Нові пакети також будуть встановлені в цей каталог. Для інших цілей каталоги необхідно налаштувати." #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Встановлена версія:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Встановлено в:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Перевірте правильність написання!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "Необхідно ввести" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Пошук цього пакету в PyPI не дав результатів." #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Код помилки:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Ім'я пакету не знайдено в списку:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Пакет «{}» необхідний для встановлення та видалення інших пакетів." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Пакет" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Управління пакетами для %s" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Підтвердження" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Схоже, ви бажаєте встановити пакет, що стосується Thonny. Якщо ви бажаєте встановити плагин для Thonny, тоді використовуйте «Інструменти → Управління плагинами...»\n" "\n" "Ви впевнені, що бажаєте встановити %s для бэкенду?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "NB! Може бути доступна інша версія, сумісна з поточною версією Thonny. Клацніть кнопку «...» щоб обрати версію для встановлення." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Плагини Thonny без залежностей" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Схоже, ви бажаєте встановити стару версію плагину для Thonny (в ній не вказана версія Thonny).\n" "\n" "Якщо ви дійсно цього бажаєте, тоді встановіть плагин з командного рядка." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Невідповідні залежності" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "Цей пакет потребує іншої версії Thonny:" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Якщо ви дійсно цього бажаєте, тоді встановіть пакет з командного рядка." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(В цьому випадку бэкенд Thonny буде використовувати той же інтерпретатор, таким чином обидва способа будуть управляти одним й тим же набором пакетів.)" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "NB! Треба перезапустити Thonny після встановлення, оновлення або видалення плагину." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Плагини Thonny" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Просунуте встановлення / оновлення / відкат" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Бажана версія" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Оновлення залежностей" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Треба:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Помилка:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Управління пакетами..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Управління плагинами..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "Відкрити повтор..." #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Змініть робочий каталог для програми в Запуск / Налагодження" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Показувати виклики функцій (фрейми) в різних вікнах" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "Зніміть відмітку якщо ви бажаєте більш традиційний стиль" #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "Автоматично відкривати та закривати вікна стеку" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "Відкриває вікно стеку при першому виклику та закриває його, коли програма повертається до зовнішнього блоку." #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "Дозволити перехід до біблиотек (тобто до модулі за межами каталога програми)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Може уповільнити налагоджувач" #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Налагоджувач, якому надається перевага" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(використовується при кліку кнопки Налагодити)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Порт Birdseye" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(перезапустіть Thonny після цих змін)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Запустити та налагодити" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Емуляція терміналу" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "підтримує основні ANSI-кольори та стилі" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Максимальна кількість рядків, що лишаються" #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "NB! Великі значення можуть призвести до погіршення продуктивності!" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Максимальна довжина рядку, що підлягає стисканню" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Запуск поточної програми в терминалі" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Перейти до Python REPL після завершення програми" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Залишати вікно терминалу відкритим після завершення програми" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "NB! Автоматичне закриття повинно бути ввімкнено в налаштуваннях терминалу (Профілі → Оболонка → При виході з оболонки)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Термінал" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "Тема інтерфейсу" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Тема підсвітлення синтаксису" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Шрифт редактора" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "Шрифт вікна введення-виведення" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Попередній перегляд" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "Це коментар" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "Відповідю є" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "незакритий_рядок" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "бла, бла" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "NB! Деякі елементи оформлення зміняться тільки після перезапуску Thonny!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Введіть число" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Тема & шрифт" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Відкрити каталог Thonny..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Відкрити каталог даних Thonny..." #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Додому" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Зміст довідки" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "Пристрій CircuitPython" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "Пристрій MicroPython" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Підключіть пристрій до комп'ютера та оберіть відповідний порт нижче" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "знайдіть им'я вашого пристрою, «USB Serial» або «UART»" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Якщо ви не можете знайти його, спробуйте спочатку встановити відповідний драйвер USB." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Порт" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Спробувати виявити порт автоматично" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython (загальний)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Друк..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Відкрити системну оболонку..." #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Подробиці" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Встановити з файлу requirements.txt" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Встановити з локального файлу" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "Це вікно для управління плагинами та залежностями Thonny.\n" "Якщо ви бажаєте встановити пакети для ваших програм, тоді перейдіть до «Інструменти → Управління пакетами...»" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (общий)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Збільшити відступ вибраних рядків" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Зменшити відступ вибраних рядків" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Перемикнутися до звичайного режиму" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "Впевніться, що MicroPython встановлений на ваш micro:bit." #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "Не забудьте, що main.py працює без вбудованого main-script." #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "Встановіть останній MicroPython на BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "Розташування micro:bit:" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Версія до встановлення" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "зачекайте будь ласка" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "NB! Всі файли на micro:bit будуть видаленв!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Встановлення..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Зроблено!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Зараз можна закрити це вікно." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Прошивка" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "Відкрити вікно для встановлення або оновлення MicroPython на вашому пристрої" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "Не вдалось знайти диск «%s»" #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "Впевніться, що ваш micro:bit підключений!" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Бажаєте продовжити та вибрати диск вручну?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "Не вдалось знайти диск «%s». Бажаєте вибрати його вручну?" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Знайдено кілька «%s» дисків. Бажаєте вибрати один з них?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Не вдалося знайти диск, що підходить" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d елементів" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Перемістити до Корзини" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Перемістити до Мусору" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Видалити" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Новий каталог" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Власитвості" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Місце в сховищі" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "Шлях" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Властивості каталогу" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Властивості файлу" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "байт" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "розмір" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Змінений" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "Видалення %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Перенесення %s в %s" #: thonny/code.py:203 msgid "Loading" msgstr "Завантаження" #: thonny/code.py:297 msgid "Saving" msgstr "Зберігання" #: thonny/running.py:1408 msgid "Working..." msgstr "Обробка..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Вивантаження %s до %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Вивантажити до %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "Завантаження %s до %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Завантажити в %s" thonny-3.2.7/thonny/locale/de_DE/0000755000175000017500000000000013611777205017603 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/de_DE/LC_MESSAGES/0000755000175000017500000000000013611777205021370 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/de_DE/LC_MESSAGES/thonny.mo0000644000175000017500000002331513611774245023251 0ustar annamaaannamaa00000000000000,<=%Z p* : I +V - ! 7 & 1 ; B xP  '   " ( 4 %9 7_   (     + 9 > C J g n s x ~      0  6! X r      #,BzQ  ?C= B&i&n     +6/Hx !c  2 LVfDk;$$)>)2!1J, CBX$94 /9?U 77W ^iy/K $ 00a{!  ' $,3E[ c p|?C-#Jn ~' )5=Ue  G! Oi   ! 0!5!G! Z!e!w!T!!2!)" 2"@"P"`" p" z""&"&""" #6"#Y#i#)q#}#$$% % %*%9% >%"L%Do% %%%[%D5&'z&&&& Please check your spelling! (probably needs admin privileges). Upgrade (Increase font size. New packages will be also installed into this directory. Other locations must be managed by alternative means.A special virtual environment (deprecated)About BirdseyeAbout ThonnyAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAlternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?BugtrackerCan't close yetCan't find package name from the list: Case sensitiveClick CloseComment outCopyCould not find the package from PyPI.Could not find the package info from PyPI. Error code: CutDebug current script (birdseye)Debug mode (provides more detailed logs)Decrease font sizeDeviceDisable notification soundDock user windowsDocumentationDownEditEditorEnter string to be replaced.EventsExitFileFilesFindFind & ReplaceFind package from PyPIFind:Focus editorFocus shellFont scaling modeFull screenHeapHeap mode is on. Close Heap view to turn it off.HelpHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomepageIf you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER. InstallInstall from PyPI Install from local file Installed to: Installed version: Installing pip Installing pip, please wait ... InterpreterLanguageLatest stable versionLatest versionMade in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMaximize viewNext objectNotesObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOutlinePackages' directory PastePerform MyPy checksPerform selected Pylint checksPrevious objectProgram argumentsPyPI pagePygame Zero modeReally uninstall?Recommended maximum line length (Set to 0 to turn off margin line)RedoReopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRunRun cellRun cell and advanceRun selection or current lineRun to cursorSelect allShow line numbersStart by selecting the package from the left. SummaryTarget: The specified text was not found!This dialog lists all available packages, but allows upgrading and uninstalling only packages from This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsToggle commentToolsUncommentUndoUninstallUpUpgradeUpgrade or uninstall Use "Stop" command if you want to cancel debuggingVariablesVersion historyViewWhich interpreter or device should Thonny use for running your code?You must restart Thonny for language change to take effect.You seem to have problems with pip exact package nameherevirtual environment Project-Id-Version: Thonny Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2019-08-24 13:36+0300 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: de Language-Team: de Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.7.0 Bitte überprüfe deine Rechtschreibung! (benötigt wahrscheinlich Administratorrechte). Aktualisieren (Schriftgröße erhöhen. Neue Pakete werden ebenfalls in dieses Verzeichnis installiert. Andere Orte müssen mit alternativen Mitteln verwaltet werden.Eine besondere virtuelle Umgebung (veraltet)Über BirdseyeÜber ThonnyCodevervollständigung mit der Tabulatortaste in der Shell zulassenCodevervollständigung mit der Tabulatortaste in Editoren zulassenNur eine Instanz von Thonny zulassenAlternativer Python 3 Interpreter oder virtuelle UmgebungBist du sicher, dass du es deinstallieren möchtest?AssistentAutorAutovervollständigenBirdseye ist ein Python-Debugger, der separat installiert werden muss. Möchtest du die Hilfe-Seite öffnen und mehr erfahren?BugtrackerSchließen noch nicht möglichDer Paketname kann nicht in der Liste gefunden werden: Groß-/Kleinschreibung beachtenKlick SchließenAuskommentierenKopierenDas Paket konnte nicht in PyPI gefunden werden.Die Paketinformationen aus PyPI konnten nicht gefunden werden. Fehlercode: AusschneidenAktuelles Skript debuggen (birdseye)Debug-Modus (liefert ausführlichere Protokolle)Schriftgröße verringernGerätBenachrichtigungston deaktivierenBenutzerfenster andockenDokumentationUntenBearbeitenEditorGib die zu ersetzende Zeichenkette ein.EreignisseBeendenDateiDateienSuchenSuchen & ErsetzenPaket von PyPI suchenSuchen:Fokus EditorFokus ShellSchrift-SkalierungsmodusVollbildHeapHeap-Modus ist an. Schließe Heap-Ansicht um ihn auszuschalten.HilfeAktuelle Zeile hervorheben (erfordert erneutes Öffnen des Editors)Lokale Variablen hervorhebenÜbereinstimmende Namen hervorhebenKlammern hervorhebenSyntax-Elemente hervorhebenHomepageWenn du nicht weißt, woher du das Paket bekommen sollst, dann wirst du höchstwahrscheinlich im Python Package Index suchen wollen. Gib zunächst den Namen des Pakets in das Suchfeld oben ein und drücke ENTER. InstallierenVon PyPI installieren Aus lokaler Datei installieren Installiert in: Installierte Version: pip wird installiert pip wird installiert, bitte warten ... InterpreterSpracheNeueste stabile VersionNeueste VersionHergestellt an der Universität Tartu, Estland, mit Hilfe der Open-Source-Community, Raspberry Pi Foundation und Cybernetica ASAnsicht maximierenNächstes ObjektNotizenObjektinspektorAssistenten automatisch öffnen, wenn er Warnungen für deinen Code hatAssistenten automatisch öffnen, wenn das Programm mit einer Ausnahme abstürztUmrissVerzeichnis der Pakete EinfügenMyPy-Überprüfungen durchführenAusgewählte Pylint-Überprüfungen durchführenVorheriges ObjektProgramm-ArgumentePyPi-SeitePygame Zero-ModusWirklich deinstallieren?Empfohlene maximale Zeilenlänge (Auf 0 einstellen, um die Randlinie auszuschalten.)WiederherstellenAlle Dateien der vorherigen Sitzung erneut öffnenErsetzenAlle ersetzenErsetzen durch:Ersetzen+SuchenProbleme meldenBenötigtAusführenZelle ausführenZelle ausführen und vorwärts bewegenAuswahl oder aktuelle Zeile ausführenBis Cursor ausführenAlles auswählenZeilennummern anzeigenWähle zunächst das Paket auf der linken Seite aus. ZusammenfassungZiel: Der angegebene Text wurde nicht gefunden!Dieser Dialog listet alle verfügbaren Pakete auf, aber ermöglicht nur das Aktualisieren und Deinstallieren von Paketen von Diese Programm wird ohne Gewährleistung zu Verfügungen gestellt. Es ist freie Software, die du unter bestimmte Bedingungen weiterverbreiten kannst, sehe https://opensource.org/licenses/MIT für weitere InformationKommentar umschaltenExtrasEntkommentierenRückgängigDeinstallierenObenAktualisierenAktualisieren oder deinstallieren Verwende den Befehl "Stop", wenn du das Debuggen abbrechen möchtestVariablenVersionsgeschichteAnsichtWelchen Interpreter oder welches Gerät sollte Thonny zum Ausführen Ihres Codes verwenden?Du musst Thonny neu starten, damit die Sprachänderung wirksam wird.Du scheinst Probleme mit pip zu haben genauer Paketnamehiervirtuelle Umgebung thonny-3.2.7/thonny/locale/de_DE/LC_MESSAGES/thonny.po0000644000175000017500000004107313611774245023255 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: de\n" #: thonny/workbench.py:338 msgid "File" msgstr "Datei" #: thonny/workbench.py:339 msgid "Edit" msgstr "Bearbeiten" #: thonny/workbench.py:340 msgid "View" msgstr "Ansicht" #: thonny/workbench.py:341 msgid "Run" msgstr "Ausführen" #: thonny/workbench.py:342 msgid "Device" msgstr "Gerät" #: thonny/workbench.py:343 msgid "Tools" msgstr "Extras" #: thonny/workbench.py:344 msgid "Help" msgstr "Hilfe" #: thonny/workbench.py:478 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Alternativer Python 3 Interpreter oder virtuelle Umgebung" #: thonny/workbench.py:486 msgid "A special virtual environment (deprecated)" msgstr "Eine besondere virtuelle Umgebung (veraltet)" #: thonny/workbench.py:523 msgid "Exit" msgstr "Beenden" #: thonny/workbench.py:540 msgid "(Increase font size" msgstr "(Schriftgröße erhöhen" #: thonny/workbench.py:550 msgid "Decrease font size" msgstr "Schriftgröße verringern" #: thonny/workbench.py:562 msgid "Focus editor" msgstr "Fokus Editor" #: thonny/workbench.py:571 msgid "Focus shell" msgstr "Fokus Shell" #: thonny/workbench.py:582 msgid "Maximize view" msgstr "Ansicht maximieren" #: thonny/workbench.py:594 msgid "Full screen" msgstr "Vollbild" #: thonny/workbench.py:1195 msgid "Program arguments" msgstr "Programm-Argumente" #: thonny/plugins/about.py:24 thonny/plugins/about.py:160 msgid "About Thonny" msgstr "Über Thonny" #: thonny/plugins/about.py:80 msgid "" "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "" "Hergestellt an der\n" "Universität Tartu, Estland,\n" "mit Hilfe der\n" "Open-Source-Community,\n" "Raspberry Pi Foundation\n" "und Cybernetica AS" #: thonny/plugins/about.py:106 msgid "" "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "" "Diese Programm wird ohne Gewährleistung zu Verfügungen gestellt. Es ist " "freie Software, die du unter bestimmte Bedingungen weiterverbreiten kannst, " "sehe https://opensource.org/licenses/MIT für weitere Information" #: thonny/plugins/about.py:149 msgid "Version history" msgstr "Versionsgeschichte" #: thonny/plugins/about.py:156 msgid "Report problems" msgstr "Probleme melden" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "" "Assistenten automatisch öffnen, wenn das Programm mit einer Ausnahme abstürzt" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Assistenten automatisch öffnen, wenn er Warnungen für deinen Code hat" #: thonny/plugins/assistant_config_page.py:28 msgid "Perform selected Pylint checks" msgstr "Ausgewählte Pylint-Überprüfungen durchführen" #: thonny/plugins/assistant_config_page.py:35 msgid "Perform MyPy checks" msgstr "MyPy-Überprüfungen durchführen" #: thonny/plugins/assistant_config_page.py:40 msgid "Disabled checks (one id per line)" msgstr "" #: thonny/plugins/assistant_config_page.py:80 msgid "Assistant" msgstr "Assistent" #: thonny/plugins/autocomplete.py:329 msgid "Auto-complete" msgstr "Autovervollständigen" #: thonny/plugins/backend_config_page.py:44 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "" "Welchen Interpreter oder welches Gerät sollte Thonny zum Ausführen Ihres " "Codes verwenden?" #: thonny/plugins/backend_config_page.py:128 msgid "Interpreter" msgstr "Interpreter" #: thonny/plugins/birdseye_frontend.py:30 msgid "About Birdseye" msgstr "Über Birdseye" #: thonny/plugins/birdseye_frontend.py:31 msgid "" "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "" "Birdseye ist ein Python-Debugger, der separat installiert werden muss.\n" "\n" "Möchtest du die Hilfe-Seite öffnen und mehr erfahren?" #: thonny/plugins/birdseye_frontend.py:55 msgid "Debug current script (birdseye)" msgstr "Aktuelles Skript debuggen (birdseye)" #: thonny/plugins/cells.py:182 msgid "Run cell" msgstr "Zelle ausführen" #: thonny/plugins/cells.py:192 msgid "Run cell and advance" msgstr "Zelle ausführen und vorwärts bewegen" #: thonny/plugins/cells.py:202 msgid "Run selection or current line" msgstr "Auswahl oder aktuelle Zeile ausführen" #: thonny/plugins/commenting.py:113 msgid "Toggle comment" msgstr "Kommentar umschalten" #: thonny/plugins/commenting.py:123 msgid "Comment out" msgstr "Auskommentieren" #: thonny/plugins/commenting.py:133 msgid "Uncomment" msgstr "Entkommentieren" #: thonny/plugins/common_editing_commands.py:32 msgid "Undo" msgstr "Rückgängig" #: thonny/plugins/common_editing_commands.py:44 msgid "Redo" msgstr "Wiederherstellen" #: thonny/plugins/common_editing_commands.py:60 msgid "Cut" msgstr "Ausschneiden" #: thonny/plugins/common_editing_commands.py:72 msgid "Copy" msgstr "Kopieren" #: thonny/plugins/common_editing_commands.py:84 msgid "Paste" msgstr "Einfügen" #: thonny/plugins/common_editing_commands.py:96 thonny/plugins/debugger.py:123 msgid "Select all" msgstr "Alles auswählen" #: thonny/plugins/debugger.py:114 msgid "Run to cursor" msgstr "Bis Cursor ausführen" #: thonny/plugins/debugger.py:831 msgid "Can't close yet" msgstr "Schließen noch nicht möglich" #: thonny/plugins/debugger.py:832 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Verwende den Befehl \"Stop\", wenn du das Debuggen abbrechen möchtest" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Benutzerfenster andocken" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Übereinstimmende Namen hervorheben" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Lokale Variablen hervorheben" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Klammern hervorheben" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Syntax-Elemente hervorheben" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Aktuelle Zeile hervorheben (erfordert erneutes Öffnen des Editors)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Codevervollständigung mit der Tabulatortaste in Editoren zulassen" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Codevervollständigung mit der Tabulatortaste in der Shell zulassen" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Zeilennummern anzeigen" #: thonny/plugins/editor_config_page.py:50 msgid "" "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "" "Empfohlene maximale Zeilenlänge\n" "(Auf 0 einstellen, um die Randlinie auszuschalten.)" #: thonny/plugins/editor_config_page.py:71 msgid "Editor" msgstr "Editor" #: thonny/plugins/event_logging.py:24 msgid "Export usage logs..." msgstr "" #: thonny/plugins/event_view.py:41 msgid "Events" msgstr "Ereignisse" #: thonny/plugins/files.py:113 msgid "Files" msgstr "Dateien" #: thonny/plugins/find_replace.py:60 thonny/plugins/find_replace.py:422 msgid "Find & Replace" msgstr "Suchen & Ersetzen" #: thonny/plugins/find_replace.py:66 msgid "Find:" msgstr "Suchen:" #: thonny/plugins/find_replace.py:81 msgid "Replace with:" msgstr "Ersetzen durch:" #: thonny/plugins/find_replace.py:99 msgid "Case sensitive" msgstr "Groß-/Kleinschreibung beachten" #: thonny/plugins/find_replace.py:106 msgid "Up" msgstr "Oben" #: thonny/plugins/find_replace.py:110 msgid "Down" msgstr "Unten" #: thonny/plugins/find_replace.py:117 msgid "Find" msgstr "Suchen" #: thonny/plugins/find_replace.py:126 msgid "Replace" msgstr "Ersetzen" #: thonny/plugins/find_replace.py:133 msgid "Replace+Find" msgstr "Ersetzen+Suchen" #: thonny/plugins/find_replace.py:142 msgid "Replace all" msgstr "Alle ersetzen" #: thonny/plugins/find_replace.py:236 msgid "Enter string to be replaced." msgstr "Gib die zu ersetzende Zeichenkette ein." #: thonny/plugins/find_replace.py:324 msgid "The specified text was not found!" msgstr "Der angegebene Text wurde nicht gefunden!" #: thonny/plugins/general_config_page.py:14 msgid "Allow only single Thonny instance" msgstr "Nur eine Instanz von Thonny zulassen" #: thonny/plugins/general_config_page.py:20 msgid "Debug mode (provides more detailed logs)" msgstr "Debug-Modus (liefert ausführlichere Protokolle)" #: thonny/plugins/general_config_page.py:26 msgid "Reopen all files from previous session" msgstr "Alle Dateien der vorherigen Sitzung erneut öffnen" #: thonny/plugins/general_config_page.py:32 msgid "Disable notification sound" msgstr "Benachrichtigungston deaktivieren" #: thonny/plugins/general_config_page.py:65 msgid "Font scaling mode" msgstr "Schrift-Skalierungsmodus" #: thonny/plugins/general_config_page.py:83 msgid "" "NB! Restart Thonny after changing these options\n" "in order to see the full effect" msgstr "" #: thonny/plugins/heap.py:39 msgid "" "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "" "Heap-Modus ist an.\n" "Schließe Heap-Ansicht um ihn auszuschalten." #: thonny/plugins/heap.py:89 msgid "Heap" msgstr "Heap" #: thonny/plugins/language.py:13 thonny/plugins/language.py:39 msgid "Language" msgstr "Sprache" #: thonny/plugins/language.py:30 msgid "You must restart Thonny for language change to take effect." msgstr "Du musst Thonny neu starten, damit die Sprachänderung wirksam wird." #: thonny/plugins/notes.py:32 msgid "" "This box is meant for your working notes -- assignment instructions, code " "snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next " "time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "" #: thonny/plugins/notes.py:57 msgid "Notes" msgstr "Notizen" #: thonny/plugins/object_inspector.py:110 msgid "Previous object" msgstr "Vorheriges Objekt" #: thonny/plugins/object_inspector.py:113 msgid "Next object" msgstr "Nächstes Objekt" #: thonny/plugins/object_inspector.py:614 msgid "Object inspector" msgstr "Objektinspektor" #: thonny/plugins/outline.py:154 msgid "Outline" msgstr "Umriss" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Pygame Zero-Modus" #: thonny/plugins/pip_gui.py:83 msgid "Find package from PyPI" msgstr "Paket von PyPI suchen" #: thonny/plugins/pip_gui.py:184 msgid " Upgrade " msgstr " Aktualisieren " #: thonny/plugins/pip_gui.py:191 msgid "Uninstall" msgstr "Deinstallieren" #: thonny/plugins/pip_gui.py:206 msgid "Close" msgstr "Schließen" #: thonny/plugins/pip_gui.py:244 msgid "" "Installing pip\n" "\n" msgstr "" "pip wird installiert\n" "\n" #: thonny/plugins/pip_gui.py:247 msgid "" "pip, a required module for managing packages is missing or too old.\n" "\n" "Downloading pip installer (about 1.5 MB), please wait ...\n" msgstr "" #: thonny/plugins/pip_gui.py:255 msgid "Installing pip, please wait ...\n" msgstr "pip wird installiert, bitte warten ...\n" #: thonny/plugins/pip_gui.py:279 msgid "" "You seem to have problems with pip\n" "\n" msgstr "" "Du scheinst Probleme mit pip zu haben\n" "\n" #: thonny/plugins/pip_gui.py:283 msgid "" "pip, a required module for managing packages is missing or too old for " "Thonny.\n" "\n" "If your system package manager doesn't provide recent pip (9.0.0 or later), " "then you can install newest version by downloading " msgstr "" #: thonny/plugins/pip_gui.py:290 msgid " and running it with " msgstr "" #: thonny/plugins/pip_gui.py:292 msgid "" " (probably needs admin privileges).\n" "\n" msgstr "" " (benötigt wahrscheinlich Administratorrechte).\n" "\n" #: thonny/plugins/pip_gui.py:302 msgid "" "Alternatively, if you have an older pip installed, then you can install " "packages on the command line (Tools → Open system shell...)" msgstr "" #: thonny/plugins/pip_gui.py:351 msgid "" "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or " "uninstalling.\n" "\n" msgstr "" #: thonny/plugins/pip_gui.py:357 msgid "Packages' directory\n" msgstr "Verzeichnis der Pakete\n" #: thonny/plugins/pip_gui.py:363 msgid "Install from PyPI\n" msgstr "Von PyPI installieren\n" #: thonny/plugins/pip_gui.py:366 msgid "" "If you don't know where to get the package from, then most likely you'll " "want to search the Python Package Index. Start by entering the name of the " "package in the search box above and pressing ENTER.\n" "\n" msgstr "" "Wenn du nicht weißt, woher du das Paket bekommen sollst, dann wirst du " "höchstwahrscheinlich im Python Package Index suchen wollen. Gib zunächst den " "Namen des Pakets in das Suchfeld oben ein und drücke ENTER.\n" "\n" #: thonny/plugins/pip_gui.py:372 msgid "Install from local file\n" msgstr "Aus lokaler Datei installieren\n" #: thonny/plugins/pip_gui.py:374 msgid "Click " msgstr "Klick " #: thonny/plugins/pip_gui.py:375 msgid "here" msgstr "hier" #: thonny/plugins/pip_gui.py:378 msgid "" " to locate and install the package file (usually with .whl, .tar.gz or .zip " "extension).\n" "\n" msgstr "" #: thonny/plugins/pip_gui.py:381 msgid "Upgrade or uninstall\n" msgstr "Aktualisieren oder deinstallieren\n" #: thonny/plugins/pip_gui.py:383 msgid "" "Start by selecting the package from the left.\n" "\n" msgstr "" "Wähle zunächst das Paket auf der linken Seite aus.\n" "\n" #: thonny/plugins/pip_gui.py:387 msgid "Target: " msgstr "Ziel: " #: thonny/plugins/pip_gui.py:390 msgid "virtual environment\n" msgstr "virtuelle Umgebung\n" #: thonny/plugins/pip_gui.py:394 msgid "user site packages\n" msgstr "" #: thonny/plugins/pip_gui.py:399 msgid "" "This dialog lists all available packages, but allows upgrading and " "uninstalling only packages from " msgstr "" "Dieser Dialog listet alle verfügbaren Pakete auf, aber ermöglicht nur das " "Aktualisieren und Deinstallieren von Paketen von " #: thonny/plugins/pip_gui.py:407 msgid "" ". New packages will be also installed into this directory. Other locations " "must be managed by alternative means." msgstr "" ". Neue Pakete werden ebenfalls in dieses Verzeichnis installiert. Andere " "Orte müssen mit alternativen Mitteln verwaltet werden." #: thonny/plugins/pip_gui.py:430 msgid "Installed version: " msgstr "Installierte Version: " #: thonny/plugins/pip_gui.py:432 msgid "Installed to: " msgstr "Installiert in: " #: thonny/plugins/pip_gui.py:452 msgid "Upgrade" msgstr "Aktualisieren" #: thonny/plugins/pip_gui.py:457 msgid "Install" msgstr "Installieren" #: thonny/plugins/pip_gui.py:479 msgid "Could not find the package from PyPI." msgstr "Das Paket konnte nicht in PyPI gefunden werden." #: thonny/plugins/pip_gui.py:482 msgid "" "\n" "Please check your spelling!" msgstr "" "\n" "Bitte überprüfe deine Rechtschreibung!" #: thonny/plugins/pip_gui.py:482 msgid "" "\n" "You need to enter " msgstr "" #: thonny/plugins/pip_gui.py:483 msgid "exact package name" msgstr "genauer Paketname" #: thonny/plugins/pip_gui.py:488 msgid "Could not find the package info from PyPI. Error code: " msgstr "" "Die Paketinformationen aus PyPI konnten nicht gefunden werden. Fehlercode: " #: thonny/plugins/pip_gui.py:500 msgid "Latest stable version" msgstr "Neueste stabile Version" #: thonny/plugins/pip_gui.py:502 msgid "Latest version" msgstr "Neueste Version" #: thonny/plugins/pip_gui.py:503 msgid "Summary" msgstr "Zusammenfassung" #: thonny/plugins/pip_gui.py:504 msgid "Author" msgstr "Autor" #: thonny/plugins/pip_gui.py:505 msgid "Homepage" msgstr "Homepage" #: thonny/plugins/pip_gui.py:507 msgid "Bugtracker" msgstr "Bugtracker" #: thonny/plugins/pip_gui.py:509 msgid "Documentation" msgstr "Dokumentation" #: thonny/plugins/pip_gui.py:511 msgid "PyPI page" msgstr "PyPi-Seite" #: thonny/plugins/pip_gui.py:515 msgid "Requires" msgstr "Benötigt" #: thonny/plugins/pip_gui.py:553 msgid "Can't find package name from the list: " msgstr "Der Paketname kann nicht in der Liste gefunden werden: " #: thonny/plugins/pip_gui.py:586 msgid "Really uninstall?" msgstr "Wirklich deinstallieren?" #: thonny/plugins/pip_gui.py:590 msgid "Are you sure you want to uninstall it?" msgstr "Bist du sicher, dass du es deinstallieren möchtest?" #: thonny/plugins/variables.py:19 msgid "" "Back to\n" "current frame" msgstr "" #: thonny/plugins/variables.py:142 msgid "Variables" msgstr "Variablen" thonny-3.2.7/thonny/locale/zh_TW/0000755000175000017500000000000013611777205017676 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/zh_TW/LC_MESSAGES/0000755000175000017500000000000013611777205021463 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/zh_TW/LC_MESSAGES/thonny.mo0000644000175000017500000005730113611773167023350 0ustar annamaaannamaa00000000000000V ||}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/; ;h;#E<)i<<< <<7<-%=S=/o=)=$= == >>>(>l>>> > >>$>?2?9?I?Y?El??????@ @ @ @ -@:@@6@@AAA0A=HAA"AAAAABB3BQB,oB BBB BBB BB C 'C64CkCCCCCCC CDD D%D5DFDbD iDuD~DDD DDDD DDD EE"E*E1EIEdEEE91F kFuF |FLFF F*FG/GIG]G wG GGG<GG0lH HHH HHH+I >I JIXI hIrII6IIII IIJ JJ$J=JJkhK2K'L/LALQLgLwLLLLL LLM"M63M5jM&M5M=Mh;N)NTN #O 0OK=OOOO O*O0OP&P(BPkPoP8P PWP #Q-Q4Q ;QHQPQbQ.iQQQQQQQ QFR MRWR*jRRR RR R RR RRSSS5S3KS S S SS"SS SS S T T T+T2T9TITYTlTT!T T TTTTUU0U3MUU?UUUU/ V ;VHVOV jVxVVVVVV"V WW#W :WGW OWYW iW/wW,WWWXXXTX EY'RYpzY$Y ZZ(1Z ZZgZnZZZ Z3Z Z[ [[.[5[<[O[ _[l[-}[[ [[[E[y!\\\$\\]']F] M] Z] e]o]]7]] ]]]E^3Z^^^ ^%d items(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)(restart Thonny after changing this)(used when clicking Debug toolbar button)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAdvanced install / upgrade / downgradeAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAllow stepping into libraries (ie. outside of main script directory)Alternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portBrowse the packagesBugtrackerCan't close yetCan't find package name from the list:Can't find suitable diskCancelCancel the process?Case sensitiveChange font sizeChange working directory to script directory on Run / DebugCircuitPython (generic)CircuitPython deviceClearClear shellClickClick CloseClose allClose othersComment outConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)ConfirmationConnect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find disk '%s'.Could not find disk '%s'. Do you want to locate it yourself?Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDeleteDeleting %sDesired versionDetailsDirectory propertiesDisable notification soundDisabled checks (one id per line)DisconnectDo you want to continue and locate the disk yourself?Do you want to overwrite '%s' ?Dock user windowsDocumentationDon't forget that main.py only works without embedded main script.Done!DownDownload to %sDownloading %s to %sEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFile propertiesFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus intoFocus shellFont scaling modeFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: zh-TW %d 個項目(目前Thonny的後端程式使用相同的直譯器,所以兩個對話框都是管理一樣的套件)(在變更後請重新啟動Thonny)(當點選工具列除錯按鈕時使用)特定虛擬環境(已棄用)關於Birdseye關於Thonny進階 安裝 / 升級 / 降級允許在互動環境(Shell)中使用Tab鍵完成代碼允許在編輯器中使用Tab鍵完成代碼僅允許單個Thonny實例允許跳入函式庫(會跳離程式資料夾)另外的Python 3直譯器或虛擬環境您確定要將它解除安裝嗎?協助功能作者自動完成跳回跳到目前frame不合適的資料夾Birdseye是一個Python除錯器,需要獨立安裝。 您想打開說明頁面並了解更多訊息嗎?Birdseye 埠號(port)瀏覽套件問題追蹤目前還不能關閉無法從清單中找到套件名稱找不到合適的磁碟機取消取消程序?區分大小寫變更字型尺寸在執行 / 除錯時,將工作資料夾更改為程式檔資料夾CircuitPython(一般)CircuitPython 設備清除清除互動環境(Shell)點選點擊關閉關閉全部關閉其他轉為註解設置已更新. 請重新啟動Thonny進入一般模式 (如果你之後要變更,請到 工具 -> 選項 -> 一般 中設定)確認將設備連接到電腦,並選擇下方的連接埠複製複製到剪貼簿複製複製 %s 到 %s找不到磁碟機 '%s'找不到磁碟機 '%s' 。你想要自己找出位置嗎? 無法從PyPI中找到該套件無法從PyPI找到套件的資訊建立新的虛擬環境建立虛擬環境剪下除錯除錯目前程式除錯目前程式(birdseye)除錯目前的程式(較快)除錯目前的程式(較佳)除錯模式(提供更詳細的診斷記錄)縮小字體減少縮排(對選取的行)刪除刪除 %s想要的版本詳細目錄屬性禁用通知聲取消檢查(每行1個id)中斷連接你想要繼續並自己找出磁碟機的位置嗎?你想要覆寫 '%s' 嗎?停靠使用者視窗文件不要忘記main.py在沒有內嵌主要腳本程式時才會有效完成! 向下下載到 %s下載 %s 到 %s編輯編輯器編輯器字型Enter an integer輸入要取代的字符串錯誤錯誤碼: 錯誤: 事件異常(Exception)結束離開Thonny在互動環境(Shell)中擴展匯出使用日誌檔案檔案屬性檔案尋找尋找/取代從PyPI尋找套件尋找:韌體取得焦點(編輯器)取得焦點(切換目錄)取得焦點(互動環境Shell)字體縮放模式為了效能,互動環境(Shell)會避免完整顯示過長的行(請參考 工具 -> 選項 -> 互動環境) 。這裡可以調整原本的文字片段發現多個 '%s' 磁碟機。你想要自己選擇嗎?全螢幕一般堆積(Heap)堆積(Heap)模式已啟用。 關閉堆積(Heap)檢視就會結束此模式說明說明內容高亮顯示 當前行(需重啓編輯器)高亮顯示 區域變數高亮顯示 匹配名稱高亮顯示 括號高亮顯示 語法元素回主畫面網站主頁安裝輸入輸出(IO)字型如果找不到,你需要先安裝正確的USB驅動程式如果你不知道要從何處取得套件,你可以搜尋PyPI。請在上面的文字框中 輸入套件名稱並按下ENTER如果你仍想要,請從命令列進行安裝放大字體增加縮排(對選取的行)安裝從PyPI安裝從本地檔案安裝從requirements檔案來安裝安裝最新的MicroPython到 BBC micro:bit安裝到: 安裝版本:正在安裝...直釋器中斷程式執行跳入在python程式結束後,維持終端機視窗開啟找到的直譯器語言最新穩定版本最新版本載入載入找出另一個位置: 記錄程式使用事件看來你正要安裝Thonny相關套件。如果你想要安裝Thonny外掛模組,請選擇 '工具 -> 管理外掛模組' 你確定要為後端程式安裝 %s 嗎?看起來你正試著安裝過時的Thonny外掛模組(未指定Thonny版本) 如果你仍然要安裝,請從命令列安裝在Cybernetica AS、樹莓派基金會及開源社區的協助下,由愛沙尼亞,塔爾圖大學製作請確定MicroPython已安裝到你的micro:bit上請確認你已將micro:bit接上電腦為%s管理套件管理套件...管理外掛模組...最大化視窗在縮減前最大的行長度要保留的最大行數也許會讓除錯器更慢MicroPython(一般)MicroPython 設備已變更移至資源回收筒移至垃圾桶移動 %s 到 %s注意! 所有在micro:bit上的檔案將會被刪除!注意! 需要開啟終端機設定才能自動關閉注意! 大的值可能會降低效能注意! 這些選項變更後,請重新啟動Thonny注意!有些樣式項目在重新啟動Thonny後才會套用注意! 可能有另一個與目前Thonny相容的版本。點選 '...'按鈕來選擇要安裝的版本注意! 只支援Python3.5之後的版本注意! 在安裝 / 升級 / 移除 外掛模組後,你必須要重新啟動Thonny開新檔案新增目錄新套件也會安裝在這個資料夾。其他的地方需要另外處理下一個物件筆記確認物件檢查有代碼警告時自動開啓協助功能程式異常而崩潰時自動開啓協助功能開啟Thonny資料夾開啟Thonny程式資料夾自動開啟與關閉堆疊(Stack)檢視開開啟系統命令列開啟對話框,安裝或升級設備裡的MicroPython開啟舊檔在第一次呼叫時打開堆疊(Stack)檢視,並在程式返回主要frame時關閉選項...跳出大綱跳下一步覆寫?覆寫主題 '%s'套件需要'{}'套件來安裝或移除其他套件套件的資料夾貼上路徑執行MyPy檢查執行選定的Pylint檢查請檢查你的拼字繪圖器繪圖器會畫出圖表(一連串列印到互動環境Shell的數字)連接埠偏愛的除錯器在程式結束後呈現Python互動環境預覽前一個物件列印...程式引數(args)程式引數:程式樹屬性PyPI頁面Pygame Zero模式Python直譯器離開確定要解除安裝?最近編輯的檔案建議最大行字數(設置為0可關閉邊界線)取消復原重新整理一般模式重新命名...重開上個session的所有檔案取代全部取代取代:取代+尋找回報問題相依套件相依套件:繼續執行執行 & 除錯執行 / 繼續執行目前程式在終端機執行目前程式執行至游標在終端機中執行目前程式儲存檔案另存新檔儲存複本...保存請看說明了解更多細節.全選全選為新的虛擬環境選取一個空的資料夾選取現有的,或是建立一個空的資料夾選擇直譯器選取的資料夾不是空的. 請選取另一個或是取消.送出EOF / 軟開機互動環境(Shell)顯示繪圖器將函式呼叫(frames)顯示在另一個視窗顯示行號大小縮減文字(%d 個字元)堆疊(Stack)從左方的套件開始選擇跳回(Step back)跳入(Step into)跳出(Step out) 跳下一步(Step Over)停止停止 / 重新啟動 後端程式儲存空間摘要切換至 一般模式語法主題目標:終端機終端機模擬The answer is程序仍在執行中. 你確定要取消嗎?執行Thonny的同一個直譯器(預設值)找不到指定的文字!主題和字型您可以在這裡撰寫工作筆記(指派說明,代碼片段...等等)。 所有內容都會自動保存,並在下次打開Thonny時載入。 隨意刪除此文本,為您自己的筆記騰出空間。本機這是為了要管理這裡會列出所有可用的套件,但允許能升級或移除的套件只有在這是註解這個套件需要不同版本的Thonny此程式為免費軟件(絕無擔保),歡迎您在特定條件下重新發佈它,詳情請參閱MIT LicenseThonny會自動維護此虛擬環境Thonny 選項Thonny外掛模組沒有相依套件的Thonny外掛模組 切換註解工具自動偵測連接埠使用介面模式使用介面的縮放倍數介面主題如果你想要更傳統的體驗,請取消勾選取消註解復原解除安裝不相配的相依套件向上更新升級相依套件升級或移除上傳到 %s上傳 %s 到 %s要取消除錯,請使用“停止”指令變數版本歷史要安裝的版本: 檢視Thonny應該使用哪一個直釋器或設備來執行你的程式?目前的直譯器只能瀏覽套件。可另外使用'工具 -> 開啟系統工具列' 來安裝、升級或移除套件正在運作中...自動換行(可能會變慢)現在你可以關閉這個對話框你需要輸入你必須選取一個檔案!你的直譯器沒有出現在清單?縮放所有檔案blah, blah位元組正確的套件名稱這裡尋找你的設備名稱裡, 有著USB Serial或是UARTmicro:bit 位置: 請等待python可執行檔支援基本ANSI顏色與風格來安裝套件檔案(常見副檔名為 .whl .tar.gz 或是 .zip)來找requirements.txt檔, 並安裝裡面的套件unclosed_string使用者本地套件虛擬環境thonny-3.2.7/thonny/locale/zh_TW/LC_MESSAGES/thonny.po0000644000175000017500000011305213611773167023347 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: zh-TW\n" #: thonny/workbench.py:355 msgid "File" msgstr "檔案" #: thonny/workbench.py:356 msgid "Edit" msgstr "編輯" #: thonny/workbench.py:357 msgid "View" msgstr "檢視" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "執行" #: thonny/workbench.py:360 msgid "Tools" msgstr "工具" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "說明" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "另外的Python 3直譯器或虛擬環境" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "特定虛擬環境(已棄用)" #: thonny/workbench.py:568 msgid "Exit" msgstr "結束" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "縮小字體" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "取得焦點(編輯器)" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "取得焦點(互動環境Shell)" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "最大化視窗" #: thonny/workbench.py:639 msgid "Full screen" msgstr "全螢幕" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "程式引數(args)" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "關於Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "在Cybernetica AS、樹莓派基金會及開源社區的協助下,由愛沙尼亞,塔爾圖大學製作" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "此程式為免費軟件(絕無擔保),歡迎您在特定條件下重新發佈它,詳情請參閱MIT License" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "版本歷史" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "回報問題" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "程式異常而崩潰時自動開啓協助功能" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "有代碼警告時自動開啓協助功能" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "執行選定的Pylint檢查" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "執行MyPy檢查" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "取消檢查(每行1個id)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "協助功能" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "自動完成" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Thonny應該使用哪一個直釋器或設備來執行你的程式?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "直釋器" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "關於Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye是一個Python除錯器,需要獨立安裝。\n" "您想打開說明頁面並了解更多訊息嗎?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "除錯目前程式(birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "切換註解" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "轉為註解" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "取消註解" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "復原" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "取消復原" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "剪下" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "複製" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "貼上" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "全選" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "執行至游標" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "目前還不能關閉" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "要取消除錯,請使用“停止”指令" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "停靠使用者視窗" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "高亮顯示 匹配名稱" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "高亮顯示 區域變數" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "高亮顯示 括號" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "高亮顯示 語法元素" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "高亮顯示 當前行(需重啓編輯器)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "允許在編輯器中使用Tab鍵完成代碼" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "允許在互動環境(Shell)中使用Tab鍵完成代碼" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "顯示行號" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "建議最大行字數(設置為0可關閉邊界線)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "編輯器" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "匯出使用日誌" #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "事件" #: thonny/plugins/files.py:307 msgid "Files" msgstr "檔案" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "尋找/取代" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "尋找:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "取代:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "區分大小寫" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "向上" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "向下" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "尋找" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "取代" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "取代+尋找" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "全部取代" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "輸入要取代的字符串" #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "找不到指定的文字!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "僅允許單個Thonny實例" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "重開上個session的所有檔案" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "禁用通知聲" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "字體縮放模式" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "堆積(Heap)模式已啟用。\n" "關閉堆積(Heap)檢視就會結束此模式" #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "堆積(Heap)" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "語言" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "您可以在這裡撰寫工作筆記(指派說明,代碼片段...等等)。\n" "\n" "所有內容都會自動保存,並在下次打開Thonny時載入。\n" "\n" "隨意刪除此文本,為您自己的筆記騰出空間。" #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "筆記" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "前一個物件" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "下一個物件" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "物件檢查" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "大綱" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Pygame Zero模式" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "從PyPI尋找套件" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "解除安裝" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "關閉" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "點擊" #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "這裡" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "更新" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "安裝" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "無法從PyPI中找到該套件" #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "正確的套件名稱" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "最新穩定版本" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "最新版本" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "摘要" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "作者" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "網站主頁" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "問題追蹤" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "文件" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "PyPI頁面" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "相依套件" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "確定要解除安裝?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "您確定要將它解除安裝嗎?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "跳到目前frame" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "變數" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "本機" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "重新整理" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "取得焦點(切換目錄)" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "錯誤" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "你必須選取一個檔案!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "覆寫?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "你想要覆寫 '%s' 嗎?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "開新檔案" #: thonny/code.py:526 msgid "Open..." msgstr "開啟舊檔" #: thonny/code.py:528 msgid "Load" msgstr "載入" #: thonny/code.py:537 msgid "Recent files" msgstr "最近編輯的檔案" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "關閉全部" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "儲存檔案" #: thonny/code.py:583 msgid "Save as..." msgstr "另存新檔" #: thonny/code.py:594 msgid "Save copy..." msgstr "儲存複本..." #: thonny/code.py:603 msgid "Rename..." msgstr "重新命名..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Thonny 選項" #: thonny/running.py:94 msgid "Run current script" msgstr "執行目前程式" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "在終端機執行目前程式" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "停止 / 重新啟動 後端程式" #: thonny/running.py:139 msgid "Stop" msgstr "停止" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "中斷程式執行" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "送出EOF / 軟開機" #: thonny/running.py:172 msgid "Disconnect" msgstr "中斷連接" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "找到的直譯器" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "你的直譯器沒有出現在清單?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "找出另一個" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "python可執行檔" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "注意! 只支援Python3.5之後的版本" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "建立新的虛擬環境" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "選取現有的,或是建立一個空的資料夾" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Python直譯器" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "所有檔案" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "為新的虛擬環境選取一個空的資料夾" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "不合適的資料夾" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "選取的資料夾不是空的.\n" "請選取另一個或是取消." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "建立虛擬環境" #: thonny/shell.py:72 msgid "Clear shell" msgstr "清除互動環境(Shell)" #: thonny/shell.py:126 msgid "Plotter" msgstr "繪圖器" #: thonny/shell.py:245 msgid "Clear" msgstr "清除" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "顯示繪圖器" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "為了效能,互動環境(Shell)會避免完整顯示過長的行(請參考 工具 -> 選項 -> 互動環境) 。這裡可以調整原本的文字片段" #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "自動換行(可能會變慢)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "複製到剪貼簿" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "在互動環境(Shell)中擴展" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "縮減文字(%d 個字元)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "繪圖器會畫出圖表(一連串列印到互動環境Shell的數字)" #: thonny/shell.py:1613 msgid "See Help for details." msgstr "請看說明了解更多細節." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "關閉其他" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "複製" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "複製\n" " %s \n" "到 \n" "%s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "取消" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "確認" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "取消程序?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "程序仍在執行中.\n" "你確定要取消嗎?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "全選" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "互動環境(Shell)" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "執行Thonny的同一個直譯器(預設值)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Thonny會自動維護此虛擬環境" #: thonny/workbench.py:532 msgid "Location: " msgstr "位置: " #: thonny/workbench.py:578 msgid "Options..." msgstr "選項..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "放大字體" #: thonny/workbench.py:650 msgid "Change font size" msgstr "變更字型尺寸" #: thonny/workbench.py:651 msgid "Zoom" msgstr "縮放" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "離開Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "離開" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "覆寫主題 '%s'" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "程式引數:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "一般模式" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "設置已更新. 請重新啟動Thonny進入一般模式\n" "\n" "(如果你之後要變更,請到 工具 -> 選項 -> 一般 中設定)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "程式樹" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "選擇直譯器" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "繼續" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "執行 / 繼續" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "除錯目前程式" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "除錯" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "除錯目前的程式(較佳)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "除錯目前的程式(較快)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "跳下一步(Step Over)" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "跳下一步" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "跳入(Step into)" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "跳入" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "跳出(Step out) " #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "跳出" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "跳回(Step back)" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "跳回" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "堆疊(Stack)" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "異常(Exception)" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "記錄程式使用事件" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "除錯模式(提供更詳細的診斷記錄)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "使用介面模式" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "使用介面的縮放倍數" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "注意! 這些選項變更後,請重新啟動Thonny" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "一般" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "安裝" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "瀏覽套件" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "目前的直譯器只能瀏覽套件。可另外使用'工具 -> 開啟系統工具列' 來安裝、升級或移除套件" #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "套件的資料夾" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "從PyPI安裝" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "如果你不知道要從何處取得套件,你可以搜尋PyPI。請在上面的文字框中\n" "輸入套件名稱並按下ENTER" #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "來找requirements.txt檔, 並安裝裡面的套件" #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "點選" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "來安裝套件檔案(常見副檔名為 .whl .tar.gz 或是 .zip)" #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "升級或移除" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "從左方的套件開始選擇" #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "目標:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "虛擬環境" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "使用者本地套件" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "這裡會列出所有可用的套件,但允許能升級或移除的套件只有在" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "新套件也會安裝在這個資料夾。其他的地方需要另外處理" #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "安裝版本:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "安裝到: " #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "請檢查你的拼字" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "你需要輸入" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "無法從PyPI找到套件的資訊" #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "錯誤碼: " #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "無法從清單中找到套件名稱" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "需要'{}'套件來安裝或移除其他套件" #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "套件" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "為%s管理套件" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "確認" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "看來你正要安裝Thonny相關套件。如果你想要安裝Thonny外掛模組,請選擇 '工具 -> 管理外掛模組'\n" "\n" "你確定要為後端程式安裝 %s 嗎?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "注意! 可能有另一個與目前Thonny相容的版本。點選 '...'按鈕來選擇要安裝的版本" #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "沒有相依套件的Thonny外掛模組 " #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "看起來你正試著安裝過時的Thonny外掛模組(未指定Thonny版本)\n" "\n" "如果你仍然要安裝,請從命令列安裝" #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "不相配的相依套件" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "這個套件需要不同版本的Thonny" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "如果你仍想要,請從命令列進行安裝" #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(目前Thonny的後端程式使用相同的直譯器,所以兩個對話框都是管理一樣的套件)" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "注意! 在安裝 / 升級 / 移除 外掛模組後,你必須要重新啟動Thonny" #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Thonny外掛模組" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "進階 安裝 / 升級 / 降級" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "想要的版本" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "升級相依套件" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "相依套件:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "錯誤: " #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "管理套件..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "管理外掛模組..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "開" #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "在執行 / 除錯時,將工作資料夾更改為程式檔資料夾" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "將函式呼叫(frames)顯示在另一個視窗" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "如果你想要更傳統的體驗,請取消勾選" #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "自動開啟與關閉堆疊(Stack)檢視" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "在第一次呼叫時打開堆疊(Stack)檢視,並在程式返回主要frame時關閉" #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "允許跳入函式庫(會跳離程式資料夾)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "也許會讓除錯器更慢" #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "偏愛的除錯器" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(當點選工具列除錯按鈕時使用)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Birdseye 埠號(port)" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(在變更後請重新啟動Thonny)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "執行 & 除錯" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "終端機模擬" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "支援基本ANSI顏色與風格" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "要保留的最大行數" #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "注意! 大的值可能會降低效能" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "在縮減前最大的行長度" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "在終端機中執行目前程式" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "在程式結束後呈現Python互動環境" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "在python程式結束後,維持終端機視窗開啟" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "注意! 需要開啟終端機設定才能自動關閉" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "終端機" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "介面主題" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "語法主題" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "編輯器字型" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "輸入輸出(IO)字型" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "預覽" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "這是註解" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "The answer is" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "unclosed_string" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "blah, blah" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "注意!有些樣式項目在重新啟動Thonny後才會套用" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Enter an integer" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "主題和字型" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "開啟Thonny程式資料夾" #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "開啟Thonny資料夾" #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "回主畫面" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "說明內容" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "CircuitPython 設備" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "MicroPython 設備" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "將設備連接到電腦,並選擇下方的連接埠" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "尋找你的設備名稱裡, 有著USB Serial或是UART" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "如果找不到,你需要先安裝正確的USB驅動程式" #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "連接埠" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "自動偵測連接埠" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython(一般)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "列印..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "開啟系統命令列" #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "詳細" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "從requirements檔案來安裝" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "從本地檔案安裝" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "這是為了要管理" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython(一般)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "增加縮排(對選取的行)" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "減少縮排(對選取的行)" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "切換至\n" "一般模式" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "請確定MicroPython已安裝到你的micro:bit上" #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "不要忘記main.py在沒有內嵌主要腳本程式時才會有效" #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "安裝最新的MicroPython到 BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "micro:bit 位置: " #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "要安裝的版本: " #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "請等待" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "注意! 所有在micro:bit上的檔案將會被刪除!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "正在安裝..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "完成! " #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "現在你可以關閉這個對話框" #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "韌體" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "開啟對話框,安裝或升級設備裡的MicroPython" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "找不到磁碟機 '%s'" #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "請確認你已將micro:bit接上電腦" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "你想要繼續並自己找出磁碟機的位置嗎?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "找不到磁碟機 '%s' 。你想要自己找出位置嗎?\n" "" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "發現多個 '%s' 磁碟機。你想要自己選擇嗎?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "找不到合適的磁碟機" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d 個項目" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "移至資源回收筒" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "移至垃圾桶" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "刪除" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "新增目錄" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "屬性" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "儲存空間" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "路徑" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "目錄屬性" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "檔案屬性" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "位元組" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "大小" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "已變更" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "刪除 %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "移動 %s 到 %s" #: thonny/code.py:203 msgid "Loading" msgstr "載入" #: thonny/code.py:297 msgid "Saving" msgstr "保存" #: thonny/running.py:1408 msgid "Working..." msgstr "正在運作中..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "上傳 %s 到 %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "上傳到 %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "下載 %s 到 %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "下載到 %s" thonny-3.2.7/thonny/locale/thonny.pot0000644000175000017500000007353213611773167020723 0ustar annamaaannamaa00000000000000# Translations template for PROJECT. # Copyright (C) 2019 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2019. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2019-08-08 16:51+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.7.0\n" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "" #: thonny/base_file_browser.py:259 #, python-format msgid "%d items" msgstr "" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "" #: thonny/base_file_browser.py:679 #, python-format msgid "Deleting %s" msgstr "" #: thonny/base_file_browser.py:701 #, python-format msgid "Moving %s to %s" msgstr "" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "" #: thonny/base_file_browser.py:1005 #, python-format msgid "Do you want to overwrite '%s' ?" msgstr "" #: thonny/code.py:203 msgid "Loading" msgstr "" #: thonny/code.py:297 msgid "Saving" msgstr "" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "" #: thonny/code.py:526 msgid "Open..." msgstr "" #: thonny/code.py:528 msgid "Load" msgstr "" #: thonny/code.py:537 msgid "Recent files" msgstr "" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "" #: thonny/code.py:583 msgid "Save as..." msgstr "" #: thonny/code.py:594 msgid "Save copy..." msgstr "" #: thonny/code.py:603 msgid "Rename..." msgstr "" #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "" #: thonny/misc_utils.py:120 #, python-format msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "" #: thonny/misc_utils.py:123 #, python-format msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "" #: thonny/running.py:94 msgid "Run current script" msgstr "" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "" #: thonny/running.py:139 msgid "Stop" msgstr "" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "" #: thonny/running.py:172 msgid "Disconnect" msgstr "" #: thonny/running.py:1408 msgid "Working..." msgstr "" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "" #: thonny/running_config_page.py:97 msgid "" "Selected directory is not empty.\n" "Select another or cancel." msgstr "" #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "" #: thonny/shell.py:72 msgid "Clear shell" msgstr "" #: thonny/shell.py:126 msgid "Plotter" msgstr "" #: thonny/shell.py:245 msgid "Clear" msgstr "" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "" #: thonny/shell.py:1389 msgid "" "For performance reasons, Shell avoids showing very long lines in full " "(see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "" #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "" #: thonny/shell.py:1442 #, python-format msgid "Squeezed text (%d characters)" msgstr "" #: thonny/shell.py:1611 msgid "" "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "" #: thonny/shell.py:1613 msgid "See Help for details." msgstr "" #: thonny/ui_utils.py:368 msgid "Close others" msgstr "" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "" #: thonny/ui_utils.py:1502 #, python-format msgid "" "Copying\n" " %s\n" "to\n" " %s" msgstr "" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "" #: thonny/ui_utils.py:1784 msgid "" "The process is still running.\n" "Are you sure you want to cancel?" msgstr "" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "" #: thonny/workbench.py:355 msgid "File" msgstr "" #: thonny/workbench.py:356 msgid "Edit" msgstr "" #: thonny/workbench.py:357 msgid "View" msgstr "" #: thonny/workbench.py:360 msgid "Tools" msgstr "" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" msgstr "" #: thonny/workbench.py:532 msgid "Location: " msgstr "" #: thonny/workbench.py:568 msgid "Exit" msgstr "" #: thonny/workbench.py:578 msgid "Options..." msgstr "" #: thonny/workbench.py:585 msgid "Increase font size" msgstr "" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "" #: thonny/workbench.py:639 msgid "Full screen" msgstr "" #: thonny/workbench.py:650 msgid "Change font size" msgstr "" #: thonny/workbench.py:651 msgid "Zoom" msgstr "" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "" #: thonny/workbench.py:663 msgid "Quit" msgstr "" #: thonny/workbench.py:1054 thonny/workbench.py:1062 #, python-format msgid "Overwriting theme '%s'" msgstr "" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "" #: thonny/workbench.py:1264 msgid "" "Switch to\n" "regular\n" "mode" msgstr "" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "" #: thonny/workbench.py:1276 msgid "" "Configuration has been updated. Restart Thonny to start working in " "regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "" #: thonny/plugins/about.py:77 msgid "" "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "" #: thonny/plugins/about.py:103 msgid "" "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "" #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "" #: thonny/plugins/birdseye_frontend.py:33 msgid "" "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "" #: thonny/plugins/editor_config_page.py:47 msgid "" "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "" #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "" #: thonny/plugins/files.py:199 #, python-format msgid "Uploading %s to %s" msgstr "" #: thonny/plugins/files.py:206 #, python-format msgid "Upload to %s" msgstr "" #: thonny/plugins/files.py:261 #, python-format msgid "Downloading %s to %s" msgstr "" #: thonny/plugins/files.py:267 #, python-format msgid "Download to %s" msgstr "" #: thonny/plugins/files.py:307 msgid "Files" msgstr "" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "" #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "" #: thonny/plugins/heap.py:35 msgid "" "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "" #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "" #: thonny/plugins/notes.py:33 msgid "" "This box is meant for your working notes -- assignment instructions, code" " snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny " "next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "" #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "" #: thonny/plugins/pip_gui.py:355 msgid "" "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or " "uninstalling." msgstr "" #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "" #: thonny/plugins/pip_gui.py:371 msgid "" "If you don't know where to get the package from, then most likely you'll " "want to search the Python Package Index. Start by entering the name of " "the package in the search box above and pressing ENTER." msgstr "" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "" #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "" #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "" #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "" #: thonny/plugins/pip_gui.py:397 msgid "" "to locate and install the package file (usually with .whl, .tar.gz or " ".zip extension)." msgstr "" #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "" #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "" #: thonny/plugins/pip_gui.py:421 msgid "" "This dialog lists all available packages, but allows upgrading and " "uninstalling only packages from" msgstr "" #: thonny/plugins/pip_gui.py:431 msgid "" "New packages will be also installed into this directory. Other locations " "must be managed by alternative means." msgstr "" #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "" #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "" #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "" #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "" #: thonny/plugins/pip_gui.py:757 #, python-format msgid "Manage packages for %s" msgstr "" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "" #: thonny/plugins/pip_gui.py:814 #, python-format msgid "" "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "" #: thonny/plugins/pip_gui.py:912 msgid "" "NB! There may be another version available which is compatible with " "current Thonny version. Click on '...' button to choose the version to " "install." msgstr "" #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "" #: thonny/plugins/pip_gui.py:921 msgid "" "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "" #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "" #: thonny/plugins/pip_gui.py:970 msgid "" "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools " "→ Manage packages...'" msgstr "" #: thonny/plugins/pip_gui.py:984 msgid "" "(In this case Thonny's back-end uses same interpreter, so both dialogs " "manage same packages.)" msgstr "" #: thonny/plugins/pip_gui.py:990 msgid "" "NB! You need to restart Thonny after installing / upgrading / " "uninstalling a plug-in." msgstr "" #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "" #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "" #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "" #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "" #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "" #: thonny/plugins/run_debug_config_page.py:28 msgid "" "Opens the Stack view on first call and closes it when program returns to " "main frame." msgstr "" #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "" #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "" #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "" #: thonny/plugins/terminal_config_page.py:29 msgid "" "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "" #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "" #: thonny/plugins/variables.py:19 msgid "" "Back to\n" "current frame" msgstr "" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "" #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "" #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "" #: thonny/plugins/microbit/__init__.py:67 #, python-format msgid "Could not find disk '%s'." msgstr "" #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "" #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "" #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "" #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "" #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "" #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "" thonny-3.2.7/thonny/locale/tr_TR/0000755000175000017500000000000013611777205017675 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/tr_TR/LC_MESSAGES/0000755000175000017500000000000013611777205021462 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/tr_TR/LC_MESSAGES/thonny.mo0000644000175000017500000006443413611773167023354 0ustar annamaaannamaa00000000000000V ||}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/;;;4W<J<2< ==4.=.c=/===Q>7R>&> > >>>> > ?????!?@&@-@G@f@[@@@AA A'A.A4ADAWAoA4BY9BBB B BB6B(C#DChCCC CC(C0C+&DFRDD&DD DD D E$EHBEE3E%E!EFe"FFFF&FFF FFGG $G/G5G=G BGLG]G)pGGGGGGGGGG HH+HFH:I QI[IaIGjIIIMIJ7JRJgJJJJJ^JK.KKL2L9LLL!bL.L LLL LL M>MNMgMkM MM MMM!MMN{SO8O,P5POPdP {P?P#P"PQ$Q8Q GQhQ#~Q.QuQ=GRJRiR:S@SnTrT wTdT TTTUEU;YU U#U5UV*VUJVVdV W W'W .W9W%RWxWC~WW WW!W,X$3XXXP`XX X*X Y Y Y%Y;YRY bY nY|YY YY YNY)Z0Z 7ZBZ.WZ ZZ ZZ Z ZZZ Z[[6[(T[}[*[[[[ [$\%\4\,C\%p\\C\,\]!]D3]x]](]]#]]^^'^:^ A^b^r^x^^^^^^C^: _G_a_t_ p`~`Jaa3ab>b$c8cKc jcc8ccc c>c Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: tr %d öğe(Bu durumda Thonny arka uçta aynı yorumlayıcıyı kullanır, bu nedenle her iki iletişim kutusu da aynı paketleri yönetir.)(Değiştirdikten sonra Thonny'i yeniden başlatın)(Hata Ayıkla araç çubuğu düğmesini tıkladığınızda kullanılır)Özel bir sanal ortam (kullanımdan kaldırıldı)Birdseye hakkındaThonny HakkındaGelişmiş kurulum / yükseltme / sürüm düşürmeKonsolda Tab tuşuyla kod tamamlamaya izin verEditörde Tab tuşuyla kod tamamlamaya izin verAynı anda yalnızca tek bir Thonny çalıştırmaya izin verKütüphaneler içerisine adımlamaya izin ver (ör. Ana betik dizini dışında)Alternatif Python 3 yorumlayıcısı veya sanal ortamıKaldırmak istediğinize emin misiniz?YardımcıGeliştiriciOtomatik tamamlamaGeriMevcut çerçeveye geri dönHatalı dizinBirdseye, ayrı olarak yüklenmesi gereken bir Python hata ayıklayıcısıdır. Yardım sayfasını açmak ve daha fazla bilgi edinmek ister misiniz?Birdseye portuPaketlere göz atHata TakipçisiHenüz kapatılamıyorPaket adı listeden bulunamıyor:Uygun disk bulunamıyorİptalİşlem iptal edilsin mi?Büyük/küçük harf duyarlıYazı boyutunu değiştirMevcut çalışma dizini Çalıştır / Hata Ayıkla esnasında betik dizinine dönüştürCircuitPython (genel)CircuitPython cihazıTemizleKonsolu temizleTıklaClick_KapatTümünü kapatDiğerlerini kapatAçıklama satırı yapYapılandırma güncellendi. Normal modda çalışmaya başlamak için Thonny'i yeniden başlatın. (Daha sonra fikrinizi değiştirirseniz 'Araçlar → Seçenekler → Genel' kısmına bakın.)OnayCihazınızı bilgisayara bağlayın ve aşağıdan ilgili bağlantı noktasını seçin.KopyalaPanoya kopyalaKopyalanıyorKopyalanıyor:   %s >>>   %s'%s' diski bulunamadı.'%s' diski bulunamadı. Kendiniz bulmak ister misiniz?PyPI'den paket bulunamadı.PyPI'den paket bilgisi bulunamadı.Yeni bir sanal ortam oluşturSanal ortam oluşturmaKesHata ayıklaGeçerli betikte hata ayıklaGeçerli betikte hata ayıkla (birdseye)Geçerli betikte hata ayıkla (daha hızlıdır)Geçerli betikte hata ayıkla (daha iyidir)Hata ayıklama modu (daha ayrıntılı tanılama günlükleri sağlar)Yazı boyutunu küçültSeçili satırların girintisini azaltSil%s siliniyorİstenilen sürümAyrıntılarDizin özellikleriBildirim sesini devre dışı bırakDevre dışı bırakılmış kontroller (her satır başına bir kimlik)Bağlantıyı KesDevam etmek ve diski kendiniz bulmak ister misiniz?'%s' üzerine yazmak istiyor musunuz?Kullanıcı pencerelerini sabitleBelgelerBu main.py dosyasının yalnızca gömülü ana komut dosyası olmadan çalıştığını unutmayın.Bitti!Aşağı%s konumuna indir%s cihazından %s konumuna indiriliyorDüzenEditörEditör fontuBir tamsayı girinDeğiştirilecek metni girin.HataHata kodu:Hata:OlaylarHataÇıkışThonny'den çıkKonsolda GenişletKullanım günlüklerini dışa aktar ...DosyaDosya özellikleriDosyalarBulBul ve DeğiştirPyPI'den paket bulBul:Cihaz YazılımıEditöre odaklanŞuna odaklanKonsola odaklanYazı ölçeklendirme moduPerformans sebepleri dolayısıyla, Konsol çok uzun satırları tam olarak göstermekten kaçınır. (bkz. Araçlar => Seçenekler => Konsol). Burada orijinal metin parçasıyla etkileşime geçebilirsiniz.Birkaç '%s' disk bulundu. Kendiniz seçmek ister misiniz?Tam ekranGenelYığınYığın modu açık. Kapatmak için Yığın görünümünü kapatın.YardımYardım içeriğiGeçerli satırı vurgula (düzenleyicinin yeniden açılmasını gerektirir)Yerel değişkenleri vurgulaEşleşen isimleri vurgulaParantezleri vurgulaSözdizimi öğelerini vurgulaEvAnasayfaYÜKLEG/Ç yazı tipiCihazınızı bulamıyorsanız, öncelikle USB sürücüsünü yüklemeniz gerekiyor olabilir.Paketi nereden alacağınızı bilmiyorsanız, büyük olasılıkla Python Paket Dizini'nde aramak isteyeceksiniz. Paketin adını yukarıdaki arama kutusuna girip ENTER tuşuna basarak başlayın.Lütfen komut satırı kullanarak yükleyiniz.Yazı boyutunu arttırSeçili satırları girintileYüklePyPI'den yükleyinYerel dosyadan yükleGereksinimler dosyasından yükleEn son MicroPython'u BBC micro:bit'e yükleyinYüklendi:Kurulu sürüm:Yükleniyor ...YorumlayıcıÇalıştırmayı durdurİçeriyePython işlemi bittikten sonra terminal penceresini açık tutBilinen yorumlayıcılarDilSon kararlı sürümSon sürümYükleYükleniyorBaşka bir tane bulKonum: Program kullanımını günlükleThonny ile ilgili bir paket kuruyor gibisiniz. Eğer bir Thonny eklentisi kurmak istiyorsanız bunun yerine 'Araçlar → Eklentileri yönet ...' seçeneğini seçin. %s yüklemek istediğinize emin misiniz?Eski bir Thonny eklentisi yüklemeye çalışıyorsunuz gibi görünüyor (gerekli Thonny sürümünü belirtmiyor). Lütfen komut satırı kullanarak yükleyiniz.Üretim yeri Tartu Üniversitesi, Estonya, açık kaynak topluluğu yardımı ile, Raspberry Pi Vakfı ve Cybernetica A.Ş.MicroPython'un micro:bit'inize kurulduğundan emin olun.micro:bit'in takılı olduğundan emin olun!%s için paketleri yönetPaketleri yönet ...Eklentileri yönet ...Ekranı kaplaTemizleme işleminden önce maksimum satır parçası uzunluğuTutulacak maksimum satır sayısı.Hata ayıklamayı yavaşlatabilir.MicroPython (genel)MicroPython cihazıDeğiştirilmeGeri dönüşüm kutusuna taşıÇöp kutusuna taşı%s öğesi %s konumuna taşınıyorUYARI! micro:bit'teki tüm dosyalar silinecek!UYARI! Terminal ayarlarında otomatik kapanma etkinleştirilmeli (Profiller → Konsol → Konsol kapatıldığında)UYARI! Büyük değerler düşük performansa neden olabilir!UYARI! Bu seçenekleri değiştirdikten sonra Thonny'i yeniden başlatın!UYARI! Bazı stil öğelerindeki değişikliklerin uygulanması için Thonny yeniden başlatılmalıdır!UYARI! Mevcut Thonny sürümüyle uyumlu başka bir sürüm olabilir. Yüklenecek sürümü seçmek için '...' düğmesine tıklayın.UYARI! Thonny sadece Python 3.5 ve sonrasını desteklemektedir.UYARI! Bir eklentiyi kurduktan / yükselttikten / kaldırdıktan sonra Thonny'i yeniden başlatmanız gerekir.YeniYeni dizinYeni paketler de ayrıca bu dizine yüklenecek. Diğer konumlar alternatif yollarla yönetilmelidir.Sonraki nesneNotlarTamamNesne denetçisiKodda uyarı durumları olduğunda Yardımcı'yı otomatik olarak açKodda hatalar olduğunda Yardımcı'yı otomatik olarak açThonny veri klasörünü aç ...Thonny program klasörünü aç ...Yığın görünümünü otomatik olarak aç ve kapatTekrarlayıcıyı aç ...Sistem komut satırını aç...MicroPython'u cihazınıza yüklemek veya yükseltmek için iletişim kutusunu açınAç...İlk çağırmada Yığın görünümünü açar ve program ana çerçeveye döndüğünde kapatır.Seçenekler...DışarıyaTaslakÜzerindenÜzerine yazılsın mı?'%s' temasının üzerine yazılıyorPaketDiğer paketleri kurmak ve kaldırmak için '{}' paketi gereklidir.Paketler diziniYapıştırKonumMyPy kontrollerini gerçekleştirSeçilen Pylint kontrollerini gerçekleştirLütfen yazımınızı kontrol edin!ÇiziciPlotter, konsolda yazdırılmış sayı dizilerini grafiklerle görselleştirir.PortTercih edilen hata ayıklayıcıProgram bittikten sonra Python REPL kullanÖnizlemeÖnceki nesneYazdır...Program argümanlarıProgram argümanları:Program ağacıÖzelliklerPyPI sayfasıPygame Zero moduPython yorumlayıcılarıÇıkışProgram kaldırılsın mı?Son dosyalarMaksimum satır uzunluğu (Ekranın tamamını kullanmak için 0'a ayarlayın)YenileYenileNormal modYeniden adlandır...Önceki oturumdaki tüm dosyaları yeniden açDeğiştirTümünü değiştirDeğiştir:Değiştir+BulSorun bildirGereksinimlerGereksinimler:Devam etÇalıştırÇalıştır ve Hata AyıklaÇalıştır / devam etGeçerli betiği çalıştırGeçerli betiği terminalde çalıştırİmlece kadar çalıştırGeçerli betiği terminalde çalıştırmaKaydetFarklı kaydet...Kopyasını kaydet ...KaydediliyorAyrıntılar için Yardım'a bakın.Tümünü seçTümünü seçYeni sanal ortam için boş bir dizin seçinBir dizin seçin veya yeni oluşturunYorumlayıcı seçSeçilen dizin boş değil. Başka bir tane seçin veya iptal edin.Yazılımsal yeniden başlatma / EOF gönderKonsolÇiziciyi GösterFonksiyon çağrılarını (çerçeveler) ayrı pencerelerde gösterSatır numaralarını gösterBoyutSıkıştırılmış metin (%d karakter)YığınSoldaki paketi seçerek başlayın.Geriye adımlaİçeriye adımlaDışarıya adımlaÜzerinden adımlaDurdurKonsolu Durdur / Yeniden başlatDepolama alanıÖzetNormal kipe geçSözdizimi temasıHedef:TerminalTerminal emülatörüCevapİşlem hala devam ediyor. İptal etmek istediğinize emin misiniz?Thonny'yi çalıştıran aynı yorumlayıcı (varsayılan)Aranan metin bulunamadı!Tema ve Yazı TipiBu kutu çalışma notlarınız içindir - atama talimatları, kod parçacıkları, vb. Thonny'yi bir dahaki sefere açtığınızda her şey otomatik olarak kaydedilir ve geri yüklenir. Kendi notlarınıza yer açmak için bu metni silebilirsiniz.Bu bilgisayarBu iletişim kutusu Thonny eklentilerini ve bağımlılıklarını yönetmek içindir. Kendi programlarınız için paketler kurmak istiyorsanız, 'Araçlar → Paketleri yönet ...' seçeneğini seçin.Bu iletişim kutusu mevcut tüm paketleri listeler, fakat yalnızca paketlerin yükseltilmesine ve kaldırılmasına izin verir.Bu bir açıklama satırıdırBu paket farklı bir Thonny sürümü gerektiriyor:Bu program KESİNLİKLE BİR GARANTİ SUNMAMAKTADIR! Ücretsiz bir yazılımdır ve belirli koşullar dahilinde tekrar dağıtım yapabilirsiniz, detaylar için: https://opensource.org/licenses/MIT Bu sanal ortam Thonny tarafından otomatik olarak yönetilir. Thonny seçenekleriThonny eklentileriGereksinimsiz Thonny eklentisiAçıklama satırını aç/kapatAraçlarBağlantı noktasını otomatik olarak algılamayı deneUI moduUI ölçeklendirme faktörüUI temasıDaha geleneksel bir deneyim istiyorsanız işareti kaldırın.Açıklama satırını iptal etGeri alKaldırUygun olmayan gereksinimlerYukarıYükseltYükseltme bağımlılıklarıYükselt veya kaldır%s cihazına yükle%s,%s cihazına yükleniyorHata ayıklamayı iptal etmek istiyorsanız "Durdur" komutunu kullanınDeğişkenlerSürüm geçmişiYüklenecek sürüm:GörünümThonny kodunuzu çalıştırmak için hangi yorumlayıcıyı veya cihazı kullansın?Geçerli yorumlayıcı ile sadece buradaki paketlere göz atabilirsiniz. Yükleme, yükseltme veya kaldırma için 'Araçlar → Sistem konsolunu aç ...' seçeneğini kullanın.İşleniyor...Metni kaydır (yavaş olabilir)Şimdi bu iletişim kutusunu kapatabilirsiniz.Girmeniz gerekiyorBir dosya seçmeniz gerekiyor!Yorumlayıcınız listede yok mu?YakınlaştırmaTüm dosyalarfalan filanbytetam paket adıburaya"USB Seri" veya "UART" cihazınızın adını arayınmicro:bit konumu:lütfen bekleyinpython yürütülebilir dosyasıtemel ANSI renklerini ve stillerini desteklerpaket dosyasını bulmak ve kurmak için (genellikle .whl, .tar.gz veya .zip uzantılı olurlar).requirements.txt dosyasını bulmak ve içinde belirtilen paketleri kurmak için.unclosed_stringkullanıcı sitesi paketlerisanal ortamthonny-3.2.7/thonny/locale/tr_TR/LC_MESSAGES/thonny.po0000644000175000017500000012033713611773167023352 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: tr\n" #: thonny/workbench.py:355 msgid "File" msgstr "Dosya" #: thonny/workbench.py:356 msgid "Edit" msgstr "Düzen" #: thonny/workbench.py:357 msgid "View" msgstr "Görünüm" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Çalıştır" #: thonny/workbench.py:360 msgid "Tools" msgstr "Araçlar" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Yardım" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Alternatif Python 3 yorumlayıcısı veya sanal ortamı" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Özel bir sanal ortam (kullanımdan kaldırıldı)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Çıkış" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Yazı boyutunu küçült" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Editöre odaklan" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Konsola odaklan" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Ekranı kapla" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Tam ekran" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Program argümanları" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "Thonny Hakkında" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Üretim yeri\n" "Tartu Üniversitesi, Estonya,\n" "açık kaynak topluluğu\n" "yardımı ile,\n" "Raspberry Pi Vakfı\n" "ve Cybernetica A.Ş." #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Bu program KESİNLİKLE BİR\n" "GARANTİ SUNMAMAKTADIR!\n" "Ücretsiz bir yazılımdır ve belirli koşullar\n" "dahilinde tekrar dağıtım yapabilirsiniz,\n" "detaylar için: https://opensource.org/licenses/MIT\n" "" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Sürüm geçmişi" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Sorun bildir" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Kodda hatalar olduğunda Yardımcı'yı otomatik olarak aç" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Kodda uyarı durumları olduğunda Yardımcı'yı otomatik olarak aç" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Seçilen Pylint kontrollerini gerçekleştir" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "MyPy kontrollerini gerçekleştir" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Devre dışı bırakılmış kontroller (her satır başına bir kimlik)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Yardımcı" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Otomatik tamamlama" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Thonny kodunuzu çalıştırmak için hangi yorumlayıcıyı veya cihazı kullansın?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Yorumlayıcı" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "Birdseye hakkında" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye, ayrı olarak yüklenmesi gereken bir Python hata ayıklayıcısıdır.\n" "\n" "Yardım sayfasını açmak ve daha fazla bilgi edinmek ister misiniz?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Geçerli betikte hata ayıkla (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Açıklama satırını aç/kapat" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Açıklama satırı yap" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Açıklama satırını iptal et" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Geri al" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Yenile" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Kes" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Kopyala" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Yapıştır" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Tümünü seç" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "İmlece kadar çalıştır" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Henüz kapatılamıyor" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Hata ayıklamayı iptal etmek istiyorsanız \"Durdur\" komutunu kullanın" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Kullanıcı pencerelerini sabitle" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Eşleşen isimleri vurgula" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Yerel değişkenleri vurgula" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Parantezleri vurgula" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Sözdizimi öğelerini vurgula" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Geçerli satırı vurgula (düzenleyicinin yeniden açılmasını gerektirir)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Editörde Tab tuşuyla kod tamamlamaya izin ver" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Konsolda Tab tuşuyla kod tamamlamaya izin ver" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Satır numaralarını göster" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Maksimum satır uzunluğu\n" "(Ekranın tamamını kullanmak için 0'a ayarlayın)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Editör" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Kullanım günlüklerini dışa aktar ..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Olaylar" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Dosyalar" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Bul ve Değiştir" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Bul:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Değiştir:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Büyük/küçük harf duyarlı" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Yukarı" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Aşağı" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Bul" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Değiştir" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Değiştir+Bul" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Tümünü değiştir" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Değiştirilecek metni girin." #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "Aranan metin bulunamadı!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Aynı anda yalnızca tek bir Thonny çalıştırmaya izin ver" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Önceki oturumdaki tüm dosyaları yeniden aç" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Bildirim sesini devre dışı bırak" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Yazı ölçeklendirme modu" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Yığın modu açık.\n" "Kapatmak için Yığın görünümünü kapatın." #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Yığın" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Dil" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Bu kutu çalışma notlarınız içindir - atama talimatları, kod parçacıkları, vb.\n" "\n" "Thonny'yi bir dahaki sefere açtığınızda her şey otomatik olarak kaydedilir ve geri yüklenir.\n" "\n" "Kendi notlarınıza yer açmak için bu metni silebilirsiniz." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Notlar" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Önceki nesne" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Sonraki nesne" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Nesne denetçisi" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "Taslak" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Pygame Zero modu" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "PyPI'den paket bul" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Kaldır" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Kapat" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Click_" #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "buraya" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Yükselt" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Yükle" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "PyPI'den paket bulunamadı." #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "tam paket adı" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Son kararlı sürüm" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Son sürüm" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Özet" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Geliştirici" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Anasayfa" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Hata Takipçisi" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Belgeler" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "PyPI sayfası" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Gereksinimler" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Program kaldırılsın mı?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Kaldırmak istediğinize emin misiniz?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Mevcut çerçeveye\n" "geri dön" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Değişkenler" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Bu bilgisayar" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Yenile" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Şuna odaklan" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Hata" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Bir dosya seçmeniz gerekiyor!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Üzerine yazılsın mı?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "'%s' üzerine yazmak istiyor musunuz?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Yeni" #: thonny/code.py:526 msgid "Open..." msgstr "Aç..." #: thonny/code.py:528 msgid "Load" msgstr "Yükle" #: thonny/code.py:537 msgid "Recent files" msgstr "Son dosyalar" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Tümünü kapat" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Kaydet" #: thonny/code.py:583 msgid "Save as..." msgstr "Farklı kaydet..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Kopyasını kaydet ..." #: thonny/code.py:603 msgid "Rename..." msgstr "Yeniden adlandır..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Thonny seçenekleri" #: thonny/running.py:94 msgid "Run current script" msgstr "Geçerli betiği çalıştır" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Geçerli betiği terminalde çalıştır" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Konsolu Durdur / Yeniden başlat" #: thonny/running.py:139 msgid "Stop" msgstr "Durdur" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Çalıştırmayı durdur" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Yazılımsal yeniden başlatma / EOF gönder" #: thonny/running.py:172 msgid "Disconnect" msgstr "Bağlantıyı Kes" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Bilinen yorumlayıcılar" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Yorumlayıcınız listede yok mu?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Başka bir tane bul" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "python yürütülebilir dosyası" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "UYARI! Thonny sadece Python 3.5 ve sonrasını desteklemektedir." #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Yeni bir sanal ortam oluştur" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Bir dizin seçin veya yeni oluşturun" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Python yorumlayıcıları" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "Tüm dosyalar" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Yeni sanal ortam için boş bir dizin seçin" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Hatalı dizin" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "Seçilen dizin boş değil.\n" "Başka bir tane seçin veya iptal edin." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Sanal ortam oluşturma" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Konsolu temizle" #: thonny/shell.py:126 msgid "Plotter" msgstr "Çizici" #: thonny/shell.py:245 msgid "Clear" msgstr "Temizle" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Çiziciyi Göster" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Performans sebepleri dolayısıyla, Konsol çok uzun satırları tam olarak göstermekten kaçınır. (bkz. Araçlar => Seçenekler => Konsol).\n" "Burada orijinal metin parçasıyla etkileşime geçebilirsiniz." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "Metni kaydır (yavaş olabilir)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Panoya kopyala" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Konsolda Genişlet" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Sıkıştırılmış metin (%d karakter)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Plotter, konsolda yazdırılmış\n" "sayı dizilerini grafiklerle görselleştirir." #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Ayrıntılar için Yardım'a bakın." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Diğerlerini kapat" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Kopyalanıyor" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Kopyalanıyor:\n" "  %s\n" ">>>\n" "  %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "İptal" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "Tamam" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "İşlem iptal edilsin mi?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "İşlem hala devam ediyor.\n" "İptal etmek istediğinize emin misiniz?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Tümünü seç" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Konsol" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Thonny'yi çalıştıran aynı yorumlayıcı (varsayılan)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Bu sanal ortam Thonny tarafından otomatik olarak yönetilir.\n" "" #: thonny/workbench.py:532 msgid "Location: " msgstr "Konum: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Seçenekler..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Yazı boyutunu arttır" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Yazı boyutunu değiştir" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Yakınlaştırma" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Thonny'den çık" #: thonny/workbench.py:663 msgid "Quit" msgstr "Çıkış" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "'%s' temasının üzerine yazılıyor" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Program argümanları:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Normal mod" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "Yapılandırma güncellendi. Normal modda çalışmaya başlamak için Thonny'i yeniden başlatın.\n" "\n" "(Daha sonra fikrinizi değiştirirseniz 'Araçlar → Seçenekler → Genel' kısmına bakın.)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Program ağacı" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Yorumlayıcı seç" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Devam et" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Çalıştır / devam et" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Geçerli betikte hata ayıkla" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Hata ayıkla" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Geçerli betikte hata ayıkla (daha iyidir)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Geçerli betikte hata ayıkla (daha hızlıdır)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Üzerinden adımla" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "Üzerinden" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "İçeriye adımla" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "İçeriye" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Dışarıya adımla" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "Dışarıya" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Geriye adımla" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Geri" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Yığın" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Hata" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Program kullanımını günlükle" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Hata ayıklama modu (daha ayrıntılı tanılama günlükleri sağlar)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "UI modu" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "UI ölçeklendirme faktörü" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "UYARI! Bu seçenekleri değiştirdikten sonra Thonny'i yeniden başlatın!" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Genel" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "YÜKLE" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Paketlere göz at" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Geçerli yorumlayıcı ile sadece buradaki paketlere göz atabilirsiniz.\n" "Yükleme, yükseltme veya kaldırma için 'Araçlar → Sistem konsolunu aç ...' seçeneğini kullanın." #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Paketler dizini" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "PyPI'den yükleyin" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Paketi nereden alacağınızı bilmiyorsanız, büyük olasılıkla Python Paket Dizini'nde aramak isteyeceksiniz. Paketin adını yukarıdaki arama kutusuna girip ENTER tuşuna basarak başlayın." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "requirements.txt dosyasını bulmak ve içinde belirtilen paketleri kurmak için." #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Tıkla" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "paket dosyasını bulmak ve kurmak için (genellikle .whl, .tar.gz veya .zip uzantılı olurlar)." #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Yükselt veya kaldır" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Soldaki paketi seçerek başlayın." #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Hedef:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "sanal ortam" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "kullanıcı sitesi paketleri" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "Bu iletişim kutusu mevcut tüm paketleri listeler, fakat yalnızca paketlerin yükseltilmesine ve kaldırılmasına izin verir." #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Yeni paketler de ayrıca bu dizine yüklenecek. Diğer konumlar alternatif yollarla yönetilmelidir." #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Kurulu sürüm:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Yüklendi:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Lütfen yazımınızı kontrol edin!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "Girmeniz gerekiyor" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "PyPI'den paket bilgisi bulunamadı." #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Hata kodu:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Paket adı listeden bulunamıyor:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Diğer paketleri kurmak ve kaldırmak için '{}' paketi gereklidir." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Paket" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "%s için paketleri yönet" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Onay" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Thonny ile ilgili bir paket kuruyor gibisiniz.\n" "Eğer bir Thonny eklentisi kurmak istiyorsanız\n" "bunun yerine 'Araçlar → Eklentileri yönet ...' seçeneğini seçin.\n" "\n" "%s yüklemek istediğinize emin misiniz?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "UYARI! Mevcut Thonny sürümüyle uyumlu başka bir sürüm olabilir. Yüklenecek sürümü seçmek için '...' düğmesine tıklayın." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Gereksinimsiz Thonny eklentisi" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Eski bir Thonny eklentisi yüklemeye çalışıyorsunuz gibi\n" "görünüyor (gerekli Thonny sürümünü belirtmiyor).\n" "\n" "Lütfen komut satırı kullanarak yükleyiniz." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Uygun olmayan gereksinimler" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "Bu paket farklı bir Thonny sürümü gerektiriyor:" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Lütfen komut satırı kullanarak yükleyiniz." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(Bu durumda Thonny arka uçta aynı yorumlayıcıyı kullanır, bu nedenle her iki iletişim kutusu da aynı paketleri yönetir.)" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "UYARI! Bir eklentiyi kurduktan / yükselttikten / kaldırdıktan sonra Thonny'i yeniden başlatmanız gerekir." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Thonny eklentileri" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Gelişmiş kurulum / yükseltme / sürüm düşürme" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "İstenilen sürüm" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Yükseltme bağımlılıkları" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Gereksinimler:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Hata:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Paketleri yönet ..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Eklentileri yönet ..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "Tekrarlayıcıyı aç ..." #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Mevcut çalışma dizini Çalıştır / Hata Ayıkla esnasında betik dizinine dönüştür" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Fonksiyon çağrılarını (çerçeveler) ayrı pencerelerde göster" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "Daha geleneksel bir deneyim istiyorsanız işareti kaldırın." #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "Yığın görünümünü otomatik olarak aç ve kapat" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "İlk çağırmada Yığın görünümünü açar ve program ana çerçeveye döndüğünde kapatır." #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "Kütüphaneler içerisine adımlamaya izin ver (ör. Ana betik dizini dışında)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Hata ayıklamayı yavaşlatabilir." #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Tercih edilen hata ayıklayıcı" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(Hata Ayıkla araç çubuğu düğmesini tıkladığınızda kullanılır)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Birdseye portu" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(Değiştirdikten sonra Thonny'i yeniden başlatın)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Çalıştır ve Hata Ayıkla" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Terminal emülatörü" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "temel ANSI renklerini ve stillerini destekler" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Tutulacak maksimum satır sayısı." #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "UYARI! Büyük değerler düşük performansa neden olabilir!" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Temizleme işleminden önce maksimum satır parçası uzunluğu" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Geçerli betiği terminalde çalıştırma" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Program bittikten sonra Python REPL kullan" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Python işlemi bittikten sonra terminal penceresini açık tut" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "UYARI! Terminal ayarlarında otomatik kapanma etkinleştirilmeli\n" "(Profiller → Konsol → Konsol kapatıldığında)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Terminal" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "UI teması" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Sözdizimi teması" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Editör fontu" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "G/Ç yazı tipi" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Önizleme" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "Bu bir açıklama satırıdır" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "Cevap" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "unclosed_string" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "falan filan" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "UYARI! Bazı stil öğelerindeki değişikliklerin uygulanması için Thonny yeniden başlatılmalıdır!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Bir tamsayı girin" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Tema ve Yazı Tipi" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Thonny program klasörünü aç ..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Thonny veri klasörünü aç ..." #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Ev" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Yardım içeriği" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "CircuitPython cihazı" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "MicroPython cihazı" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Cihazınızı bilgisayara bağlayın ve aşağıdan ilgili bağlantı noktasını seçin." #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "\"USB Seri\" veya \"UART\" cihazınızın adını arayın" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Cihazınızı bulamıyorsanız, öncelikle USB sürücüsünü yüklemeniz gerekiyor olabilir." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Port" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Bağlantı noktasını otomatik olarak algılamayı dene" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython (genel)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Yazdır..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Sistem komut satırını aç..." #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Ayrıntılar" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Gereksinimler dosyasından yükle" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Yerel dosyadan yükle" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "Bu iletişim kutusu Thonny eklentilerini ve bağımlılıklarını yönetmek içindir.\n" "Kendi programlarınız için paketler kurmak istiyorsanız, 'Araçlar → Paketleri yönet ...' seçeneğini seçin." #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (genel)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Seçili satırları girintile" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Seçili satırların girintisini azalt" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Normal\n" "kipe\n" "geç" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "MicroPython'un micro:bit'inize kurulduğundan emin olun." #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "Bu main.py dosyasının yalnızca gömülü ana komut dosyası olmadan çalıştığını unutmayın." #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "En son MicroPython'u BBC micro:bit'e yükleyin" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "micro:bit konumu:" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Yüklenecek sürüm:" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "lütfen bekleyin" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "UYARI! micro:bit'teki tüm dosyalar silinecek!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Yükleniyor ..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Bitti!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Şimdi bu iletişim kutusunu kapatabilirsiniz." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Cihaz Yazılımı" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "MicroPython'u cihazınıza yüklemek veya yükseltmek için iletişim kutusunu açın" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "'%s' diski bulunamadı." #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "micro:bit'in takılı olduğundan emin olun!" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Devam etmek ve diski kendiniz bulmak ister misiniz?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "'%s' diski bulunamadı. Kendiniz bulmak ister misiniz?" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Birkaç '%s' disk bulundu. Kendiniz seçmek ister misiniz?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Uygun disk bulunamıyor" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d öğe" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Geri dönüşüm kutusuna taşı" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Çöp kutusuna taşı" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Sil" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Yeni dizin" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Özellikler" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Depolama alanı" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "Konum" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Dizin özellikleri" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Dosya özellikleri" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "byte" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "Boyut" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Değiştirilme" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "%s siliniyor" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "%s öğesi %s konumuna taşınıyor" #: thonny/code.py:203 msgid "Loading" msgstr "Yükleniyor" #: thonny/code.py:297 msgid "Saving" msgstr "Kaydediliyor" #: thonny/running.py:1408 msgid "Working..." msgstr "İşleniyor..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "%s,%s cihazına yükleniyor" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "%s cihazına yükle" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "%s cihazından %s konumuna indiriliyor" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "%s konumuna indir" thonny-3.2.7/thonny/locale/et_EE/0000755000175000017500000000000013611777205017624 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/et_EE/LC_MESSAGES/0000755000175000017500000000000013611777205021411 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/et_EE/LC_MESSAGES/thonny.mo0000644000175000017500000006172313611773167023301 0ustar annamaaannamaa00000000000000V |}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/; <<*D=8o=,===!=0>1I>{>C>;>.? J?T?Z?u?|? ?v? @ %@1@A@U@t@@@ @@<@AA4A[K[ ,\7\i\D],V]]27^ j^x^(^^ ^"^ _!_>_DT___ _____``5`8Q`````;`a aa aaa$b)b 0b =bHbNb_b9dbb bb+bOcCTcccc%d items(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)(restart Thonny after changing this)(used when clicking Debug toolbar button)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAdvanced install / upgrade / downgradeAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAllow stepping into libraries (ie. outside of main script directory)Alternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portBrowse the packagesBugtrackerCan't close yetCan't find package name from the list:Can't find suitable diskCancelCancel the process?Case sensitiveChange font sizeChange working directory to script directory on Run / DebugCircuitPython (generic)CircuitPython deviceClearClear shellClickClick CloseClose allClose othersComment outConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)ConfirmationConnect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find disk '%s'.Could not find disk '%s'. Do you want to locate it yourself?Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDeleteDeleting %sDesired versionDetailsDirectory propertiesDisable notification soundDisabled checks (one id per line)DisconnectDo you want to continue and locate the disk yourself?Do you want to overwrite '%s' ?Dock user windowsDocumentationDon't forget that main.py only works without embedded main script.Done!DownDownload to %sDownloading %s to %sEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFile propertiesFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus intoFocus shellFont scaling modeFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentProject-Id-Version: Thonny Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2019-08-24 13:36+0300 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: et Language-Team: et Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.7.0 %d üksust(Antud juhul kasutab Thonny programmide jooksutamiseks sama interpretaatorit, seega tegelevad mõlemad dialoogid samade pakkidega.)(taaskäivita Thonny peale selle muutmist)(rakendatakse "Silur" tööriistariba nupu klõpsamisel)Spetsiaalne virtuaalkeskkond (pole soovitav)Birdseye kohtaInfo Thonny kohtaTäpsem install / versiooni valikVõimalda sõnu lõpetada Tab-klahviga käsurealVõimalda sõnu lõpetada Tab-klahviga redaktorisLuba korraga ainult üks ThonnyLuba teegifunktsioonide sisse astumine (väljaspool skripti kausta)Alternatiivne Python 3 interpretaator või virtuaalkeskkondKas oled kindel, et soovid seda desinstallida?JuhendajaAutorLõpeta sõna automaatseltTagasiTagasi aktiivsesse raamiHalb kaustBirdseye on Pythoni silur, mis tuleb eraldi paigaldada. Kas soovid avada vastava abiinfo lehe, et rohkem teada saada?Birdseye portVaata pakkeVigade registerEi saa veel sulgedaEi leia paki nime nimekirjast:Ei leia sobivat draivi.TühistaTühista protsess?TõstutundlikMuuda kirja suurustMuuda jooksutamisel / silumisel automaatselt jooksvat kaustaCircuitPython (üldine)CircuitPythoni seadePuhastaPuhasta käsuridaKlõpsaKlõpsa SulgeSulge kõikSulge ülejäänudKommenteeriSeaded on muudetud. Tavarežiimis alustamiseks taaskäivita Thonny. (Vaata 'Tööriistad → Seaded → Üldine', kui Sa mõtled hiljem ümber.)KinnitusÜhenda seade arvutiga ja vali allpoolt selle portKopeeriKopeeri lõikepuhvrisseKopeerinKopeerin %s => %sEi leia draivi '%s'.Ei leia draivi nimega '%s'. Kas soovid selle ise valida?Ei leidnud PyPI-st sellist pakkiEi leidnud sellist pakki PyPI-stLoo uus virtuaalkeskkondLoon virtuaalkeskkondaLõikaSiluSilu käesolevat skriptiSilu käesolevat skripti (birdseye)Silu käesolevat skripti (kiirem)Silu käesolevat skripti (ägedam)Arendusrežiim (annab detailsemat diagnostilised logid)Vähenda fondi suurustVähenda ridade taanetKustutaKustutan %sSoovitud versioonDetailidKausta omadusedKeela teavitushelidTühistatud kontrollid (üks identifikaator rea kohta)Ühenda lahtiKas soovid jätkata ja draivi ise valida?Kas soovid '%s' üle kirjutada?Kinnita kasutaja aknadDokumentatsioonÄra unusta, et main.py toimib ainult siis kui MicroPython on ilma peaskriptita.Valmis!AllaLaadi alla asukohta %sLaadi %s alla asukohta %sRedigeeriRedaktorRedaktori fontSisesta täisarvSisesta asendatav sõneVigaVeakood:Viga:SündmusedErindVäljuVälju ThonnystKirjuta Käsureale väljaEkspordi kasutuslogiFailFaili omadusedFailidOtsiOtsi ja asendaOtsi pakki PyPI-stOtsi:PüsivaraMine redaktorisseMine sisseMine käsurealeFondi suuruse režiimParema jõudluse nimel ei näidata Käsureal väga pikki ridu (vaata Tööriistad => Seaded => Käsurida). Siin saad Sa algset tekstifragmenti täielikult näha.Leidsin mitu draivi nimega '%s'. Kas soovid ühe neist ise valida?TäisekraanÜldineKuhiKuhja režiim on sees. Väljalülitamiseks sulge Kuhja vaadeAbiinfoAbiinfo sisukordToo esile jooksev ridaToo esile lokaalsed muutujadToo esile samad nimedToo esile sulupaaridTee kood värviliseksAvalehtKodulehtINSTALLISisend/väljund fontKui sa ei leia seda, siis pead võibolla installima sobiva USB draiveri.Kui Sa ei tea, kust pakki saada, siis on mõistlik otsida seda Pythoni pakiregistrist (PyPI), Alustuseks sisest paki nimi otsingukasti ja vajuta ENTER.Kui sa ikkagi tahad seda, siis installi see süsteemi käsurealt..Suurenda kirja suurustSuurenda ridade taanetInstalliInstalli PyPI-stInstalli lokaalsest failistInstalli sõltuvusfaili järgiInstalli värskeim MicroPython BBC micro:bit-ileInstallimise asukoht:Installitud versioon:Installin ...InterpretaatorKatkesta programmSisseHoia terminali aken avatuna ka peale Pythoni protsessi lõppemistTeadaolevad interpretaatoridKeelViimane stabiilne versioonViimane versioonLaeLaadinVali mõni muuAsukoht: Logi kasutussündmusiPaistab, et soovid installida Thonny pistikprogrammi. Õige oleks seda teha 'Tööriistad → Halda pistikprogramme' alt. Oled sa kindel, et tahad installida %s siin?Paistab, et proovid installida aegunud Thonny pistikprogrammi (sellel pole märgitud vajalikku Thonny versiooni). Kui sa tõesti tahad seda, siis installi see süsteemi käsurealt.Loodud Tartu Ülikoolis, Eestis. Abiks on olnud avatud tarkvara kogukond, Raspberry Pi Foundation ja Cybernetica ASVeendu, et MicroPython oleks su micro:bit-ile installitud.Veendu, et micro:bit on ühendatud!Halda %s pakkeHalda lisapakke...Halda pistikprogramme...Suurenda vaadeMaksimaalne realõigu pikkus enne "kokkupigistamist"Maksimaalne ridade arv.Võib teha silumise aeglasemaks.MicroPython (üldine)MicroPythoni seadeMuudetudLiiguta PrügikastiLiiguta PrügikastiLiigutan %s asukohta %sNB! kõik failid micro:bit-il kustutatakseNB! Automaatset sulgemist tuleb lubada Terminali seadetes (Profiles → Shell → When the shell exits)NB! Suurte väärtustega võib jõudlus halveneda!NB! Need seaded rakenduvad peale Thonny taaskäivitamistNB! Mõned stiilielemendid muutuvad alles peale Thonny taaskäivitamist!NB! Mõni muu versioon võib selle Thonny versiooniga klappida. Klõpsa '...' nupule versiooni valimiseks.NB! Thonny toetab ainult Python 3.5 ja hilisemaidNB! Äsja installitud pistikprogramm rakendub alles peale Thonny taaskäivitamist.UusUus kaustUued pakid installitakse ka sellesse kausta. Teisi asukohti tuleb hallata teiste vahenditegaJärgmine objektMärkmedSobibObjektivaaturAva Juhendaja automaatselt, kui tal on hoiatusi Sinu koodi kohtaAva Juhendaja automaatselt, kui programm annab veaAva Thonny andmekaust...Ava Thonny programmikaust...Ava ja sulge Pinu vaade automaatseltAva Taasesitaja...Ava süsteemi käsurida / terminalAva MicroPythoni installimise või uuendamise dialoogAva...Avab Pinu vaate esimesel funktsiooni väljakutsel ja sulgeb, kui programm jõuab tagasi pearaamiSeaded...VäljaStruktuurÜleKirjutada üle?Kirjutan üle teemat nimega '%s'PakkPakk '{}' on vajalik teiste pakkide installimiseks ja uuendamisksPakkide kaustKleebiTeeTeosta MyPy kontrolleTeosta Pylint kontrolleKontrolli kas kirjutasid paki nime õigesti!PlotterPlotter visualiseerib käsureale prinditud numbrijadasid.PortEelistatud silurNäita peale programmi lõppu Pythoni käsuridaEelvaadeEelmine objektPrindi...Programmi argumendidProgrammi argumendid:ProgrammipuuOmadusedPyPI lehtPygame Zero režiimPythoni interpretaatordVäljuDesinstallida?Hiljutised failidSoovitatav maksimaalne reapikkus (0 lülitab serva näitamise välja)Rakenda tagasivõetud muudatus uuestiVärskendaTavarežiimNimeta ümber...Ava käivitumisel kõik eelmise sessiooni failidAsendaAsenda kõikAsenda:Otsi ja asendaTeata probleemidestNõuabNõuab:NaaseKäivitaKäivitamineJooksuta / naaseJooksuta käesolev skriptJooksuta käesolev skript terminalisJooksuta kursoriniSkripti käivitamine terminalisSalvestaSalvesta nimega...Salvesta koopia...SalvestanTäpsemalt vaata abiinfost.Vali kõikVali kõikVali uue virtuaalkeskkonna jaoks tühi kaustVali olemasolev või loo uus tühi kaustVali interpretaatorValitud kaust pole tühi. Vali mõni muu või tühista.Saada EOF / Soft rebootKäsuridaAva PlotterNäita funktsiooni väljakutseid (raame) eraldi akendesNäita reanumbreidSuurusKokkupressitud tekst (%d sümbolit)PinuAlustuseks vali vasakult huvipakkuv pakkAstu tagasiAsti sisseAstu väljaAstu ülePeataPeata/taaskäivita interpretaatorSalvestusruumKokkuvõteMine tavalisse režiimiSüntaksi stiilSihtkoht:TerminalTerminali emuleerimineVastus onProtsess käib veel. Oled Sa kindel, et soovid katkestada?Sama interpretaator, mis jooksutab Thonnyt (vaikimisi)Otsitavat teksti ei leitud!Stiil & fontSee kast on mõeldud Sinu märkmeteks -- tööjuhenditeks, koodijuppideks, ... Tekst salvestub automaatselt ja laetakse uuesti kui Sa avad Thonny uuesti. Võid vabalt selle teksti kustutada, et enda märkmetele ruumi teha.See arvutiSee dialoog on mõeldud Thonny pistiprogrammide haldamiseks. Kui soovid installida pakke enda programmide jaoks, siis kasuta 'Tööriistad → Halda lisapakke...'Selles dialoogis näidatakse kõiki pakke, aga uuendada ja desinstallida lubatakse ainult pakke asukohastSee on kommentaarSee pakk vajab teistsugust Thonny versiooni:Selle programmi toimimise kohta ei anta mingeid garantiisid. See on avatud tarkvara ja seda võib teatud tingimustel levitada. Vaata täpsemalt https://opensource.org/licenses/MITSeda virtuaalkeskkonda haldab Thonny automaatselt.Thonny seadedThonny pistikprogrammidThonny pistikprogramm ilma sõltuvustetaLülita kommentaar sisse/väljaTööriistadProovi tuvastada port automaatseltKasutajaliidese režiimKasutajaliidese suurendamineKasutajaliidese stiilÄra vali, kui soovid tavapärast (vähem intuitiivset) esitusviisi.Eemalda kommentaarVõta muudatus tagasiDesinstalliEbasobivad sõltuvusedÜlesUuendaUuenda sõltuvusedUuenda või desinstalliLaadi üles asukohta %sLaadin %s üles asukohta %sKui soovid silumist lõpetada, siis kasuta "Stop" käskuMuutujadVersioonide ajaluguInstallitav versioon:VaatedMillise interpretaatoriga peaks Thonny Su koodi jooksutama?Käesoleva interpretaatoriga saad Sa siin pakke ainult vaadata. Installimiseks, kustutamiseks ja uuendamiseks on vaja kasutada muid vahendeidTöötan...Murra rida (võib olla aeglane)Võid nüüd selle akna sulgeda.On vaja sisestadaSa peand valima faili!Ei leida vajalikku interpretaatorit?Suuruskõik failidblaa, blaabaititäpne paki nimisiiaotsi oma seadme nime või fraase "USB Serial" või "UART"micro:bit-i asukoht:palun ootaPythoni käivitusprogrammtoetab põhilisi ANSI värvikoode ja stiileet valida ja installida pakifail (harilikult .whl, .tar.gz või .zip laiendiga)et valida requirements.txt fail ja installida seal näidatud pakid.sulgemata_stringkasutaja "site-packages"virtuaalkeskkondthonny-3.2.7/thonny/locale/et_EE/LC_MESSAGES/thonny.po0000644000175000017500000011531313611773167023277 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: et\n" #: thonny/workbench.py:355 msgid "File" msgstr "Fail" #: thonny/workbench.py:356 msgid "Edit" msgstr "Redigeeri" #: thonny/workbench.py:357 msgid "View" msgstr "Vaated" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Käivita" #: thonny/workbench.py:360 msgid "Tools" msgstr "Tööriistad" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Abiinfo" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Alternatiivne Python 3 interpretaator või virtuaalkeskkond" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Spetsiaalne virtuaalkeskkond (pole soovitav)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Välju" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Vähenda fondi suurust" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Mine redaktorisse" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Mine käsureale" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Suurenda vaade" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Täisekraan" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Programmi argumendid" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "Info Thonny kohta" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Loodud\n" "Tartu Ülikoolis, Eestis.\n" "Abiks on olnud\n" "avatud tarkvara kogukond,\n" "Raspberry Pi Foundation\n" "ja Cybernetica AS" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Selle programmi toimimise\n" "kohta ei anta mingeid garantiisid.\n" "See on avatud tarkvara ja seda\n" "võib teatud tingimustel levitada.\n" "Vaata täpsemalt\n" "https://opensource.org/licenses/MIT" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Versioonide ajalugu" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Teata probleemidest" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Ava Juhendaja automaatselt, kui programm annab vea" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Ava Juhendaja automaatselt, kui tal on hoiatusi Sinu koodi kohta" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Teosta Pylint kontrolle" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Teosta MyPy kontrolle" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Tühistatud kontrollid (üks identifikaator rea kohta)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Juhendaja" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Lõpeta sõna automaatselt" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Millise interpretaatoriga peaks Thonny Su koodi jooksutama?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Interpretaator" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "Birdseye kohta" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye on Pythoni silur, mis tuleb eraldi paigaldada.\n" "\n" "Kas soovid avada vastava abiinfo lehe, et rohkem teada saada?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Silu käesolevat skripti (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Lülita kommentaar sisse/välja" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Kommenteeri" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Eemalda kommentaar" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Võta muudatus tagasi" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Rakenda tagasivõetud muudatus uuesti" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Lõika" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Kopeeri" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Kleebi" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Vali kõik" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Jooksuta kursorini" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Ei saa veel sulgeda" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Kui soovid silumist lõpetada, siis kasuta \"Stop\" käsku" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Kinnita kasutaja aknad" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Too esile samad nimed" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Too esile lokaalsed muutujad" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Too esile sulupaarid" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Tee kood värviliseks" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Too esile jooksev rida" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Võimalda sõnu lõpetada Tab-klahviga redaktoris" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Võimalda sõnu lõpetada Tab-klahviga käsureal" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Näita reanumbreid" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Soovitatav maksimaalne reapikkus\n" "(0 lülitab serva näitamise välja)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Redaktor" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Ekspordi kasutuslogi" #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Sündmused" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Failid" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Otsi ja asenda" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Otsi:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Asenda:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Tõstutundlik" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Üles" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Alla" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Otsi" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Asenda" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Otsi ja asenda" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Asenda kõik" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Sisesta asendatav sõne" #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "Otsitavat teksti ei leitud!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Luba korraga ainult üks Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Ava käivitumisel kõik eelmise sessiooni failid" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Keela teavitushelid" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Fondi suuruse režiim" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Kuhja režiim on sees.\n" "Väljalülitamiseks sulge Kuhja vaade" #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Kuhi" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Keel" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "See kast on mõeldud Sinu märkmeteks -- tööjuhenditeks, koodijuppideks, ...\n" "\n" "Tekst salvestub automaatselt ja laetakse uuesti kui Sa avad Thonny uuesti.\n" "\n" "Võid vabalt selle teksti kustutada, et enda märkmetele ruumi teha." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Märkmed" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Eelmine objekt" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Järgmine objekt" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Objektivaatur" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "Struktuur" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Pygame Zero režiim" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Otsi pakki PyPI-st" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Desinstalli" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Sulge" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Klõpsa " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "siia" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Uuenda" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Installi" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Ei leidnud PyPI-st sellist pakki" #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "täpne paki nimi" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Viimane stabiilne versioon" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Viimane versioon" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Kokkuvõte" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Autor" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Koduleht" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Vigade register" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Dokumentatsioon" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "PyPI leht" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Nõuab" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Desinstallida?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Kas oled kindel, et soovid seda desinstallida?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Tagasi\n" "aktiivsesse raami" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Muutujad" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "See arvuti" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Värskenda" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Mine sisse" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Viga" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Sa peand valima faili!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Kirjutada üle?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Kas soovid '%s' üle kirjutada?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Uus" #: thonny/code.py:526 msgid "Open..." msgstr "Ava..." #: thonny/code.py:528 msgid "Load" msgstr "Lae" #: thonny/code.py:537 msgid "Recent files" msgstr "Hiljutised failid" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Sulge kõik" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Salvesta" #: thonny/code.py:583 msgid "Save as..." msgstr "Salvesta nimega..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Salvesta koopia..." #: thonny/code.py:603 msgid "Rename..." msgstr "Nimeta ümber..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Thonny seaded" #: thonny/running.py:94 msgid "Run current script" msgstr "Jooksuta käesolev skript" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Jooksuta käesolev skript terminalis" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Peata/taaskäivita interpretaator" #: thonny/running.py:139 msgid "Stop" msgstr "Peata" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Katkesta programm" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Saada EOF / Soft reboot" #: thonny/running.py:172 msgid "Disconnect" msgstr "Ühenda lahti" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Teadaolevad interpretaatorid" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Ei leida vajalikku interpretaatorit?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Vali mõni muu" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "Pythoni käivitusprogramm" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "NB! Thonny toetab ainult Python 3.5 ja hilisemaid" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Loo uus virtuaalkeskkond" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Vali olemasolev või loo uus tühi kaust" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Pythoni interpretaatord" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "kõik failid" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Vali uue virtuaalkeskkonna jaoks tühi kaust" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Halb kaust" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "Valitud kaust pole tühi.\n" "Vali mõni muu või tühista." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Loon virtuaalkeskkonda" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Puhasta käsurida" #: thonny/shell.py:126 msgid "Plotter" msgstr "Plotter" #: thonny/shell.py:245 msgid "Clear" msgstr "Puhasta" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Ava Plotter" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Parema jõudluse nimel ei näidata Käsureal väga pikki ridu\n" "(vaata Tööriistad => Seaded => Käsurida).\n" "Siin saad Sa algset tekstifragmenti täielikult näha." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "Murra rida (võib olla aeglane)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Kopeeri lõikepuhvrisse" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Kirjuta Käsureale välja" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Kokkupressitud tekst (%d sümbolit)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Plotter visualiseerib käsureale\n" "prinditud numbrijadasid." #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Täpsemalt vaata abiinfost." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Sulge ülejäänud" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Kopeerin" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Kopeerin\n" " %s\n" "=> \n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Tühista" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "Sobib" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Tühista protsess?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Protsess käib veel.\n" "Oled Sa kindel, et soovid katkestada?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Vali kõik" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Käsurida" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Sama interpretaator, mis jooksutab Thonnyt (vaikimisi)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Seda virtuaalkeskkonda haldab Thonny automaatselt." #: thonny/workbench.py:532 msgid "Location: " msgstr "Asukoht: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Seaded..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Suurenda kirja suurust" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Muuda kirja suurust" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Suurus" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Välju Thonnyst" #: thonny/workbench.py:663 msgid "Quit" msgstr "Välju" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "Kirjutan üle teemat nimega '%s'" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Programmi argumendid:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Tavarežiim" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "Seaded on muudetud. Tavarežiimis alustamiseks taaskäivita Thonny.\n" "\n" "(Vaata 'Tööriistad → Seaded → Üldine', kui Sa mõtled hiljem ümber.)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Programmipuu" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Vali interpretaator" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Naase" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Jooksuta / naase" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Silu käesolevat skripti" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Silu" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Silu käesolevat skripti (ägedam)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Silu käesolevat skripti (kiirem)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Astu üle" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "Üle" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "Asti sisse" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "Sisse" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Astu välja" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "Välja" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Astu tagasi" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Tagasi" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Pinu" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Erind" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Logi kasutussündmusi" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Arendusrežiim (annab detailsemat diagnostilised logid)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "Kasutajaliidese režiim" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "Kasutajaliidese suurendamine" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "NB! Need seaded rakenduvad peale Thonny taaskäivitamist" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Üldine" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "INSTALLI" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Vaata pakke" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Käesoleva interpretaatoriga saad Sa siin pakke ainult vaadata.\n" "Installimiseks, kustutamiseks ja uuendamiseks on vaja kasutada\n" "muid vahendeid" #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Pakkide kaust" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Installi PyPI-st" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Kui Sa ei tea, kust pakki saada, siis on mõistlik otsida\n" "seda Pythoni pakiregistrist (PyPI), Alustuseks sisest\n" "paki nimi otsingukasti ja vajuta ENTER." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "et valida requirements.txt fail ja installida seal näidatud pakid." #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Klõpsa" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "et valida ja installida pakifail (harilikult .whl, .tar.gz või .zip laiendiga)" #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Uuenda või desinstalli" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Alustuseks vali vasakult huvipakkuv pakk" #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Sihtkoht:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "virtuaalkeskkond" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "kasutaja \"site-packages\"" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "Selles dialoogis näidatakse kõiki pakke, aga uuendada ja desinstallida\n" "lubatakse ainult pakke asukohast" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Uued pakid installitakse ka sellesse kausta. Teisi asukohti\n" "tuleb hallata teiste vahenditega" #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Installitud versioon:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Installimise asukoht:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Kontrolli kas kirjutasid paki nime õigesti!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "On vaja sisestada" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Ei leidnud sellist pakki PyPI-st" #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Veakood:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Ei leia paki nime nimekirjast:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Pakk '{}' on vajalik teiste pakkide installimiseks ja uuendamisks" #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Pakk" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Halda %s pakke" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Kinnitus" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Paistab, et soovid installida Thonny pistikprogrammi.\n" "Õige oleks seda teha 'Tööriistad → Halda pistikprogramme' alt.\n" "\n" "Oled sa kindel, et tahad installida %s siin?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "NB! Mõni muu versioon võib selle Thonny versiooniga klappida. \n" "Klõpsa '...' nupule versiooni valimiseks." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Thonny pistikprogramm ilma sõltuvusteta" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Paistab, et proovid installida aegunud Thonny pistikprogrammi\n" "(sellel pole märgitud vajalikku Thonny versiooni).\n" "\n" "Kui sa tõesti tahad seda, siis installi see süsteemi käsurealt." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Ebasobivad sõltuvused" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "See pakk vajab teistsugust Thonny versiooni:" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Kui sa ikkagi tahad seda, siis installi see süsteemi käsurealt.." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(Antud juhul kasutab Thonny programmide jooksutamiseks sama interpretaatorit,\n" "seega tegelevad mõlemad dialoogid samade pakkidega.)" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "NB! Äsja installitud pistikprogramm rakendub alles peale Thonny taaskäivitamist." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Thonny pistikprogrammid" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Täpsem install / versiooni valik" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Soovitud versioon" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Uuenda sõltuvused" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Nõuab:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Viga:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Halda lisapakke..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Halda pistikprogramme..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "Ava Taasesitaja..." #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Muuda jooksutamisel / silumisel automaatselt jooksvat kausta" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Näita funktsiooni väljakutseid (raame) eraldi akendes" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "Ära vali, kui soovid tavapärast (vähem intuitiivset) esitusviisi." #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "Ava ja sulge Pinu vaade automaatselt" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "Avab Pinu vaate esimesel funktsiooni väljakutsel ja sulgeb, kui programm jõuab tagasi pearaami" #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "Luba teegifunktsioonide sisse astumine (väljaspool skripti kausta)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Võib teha silumise aeglasemaks." #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Eelistatud silur" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(rakendatakse \"Silur\" tööriistariba nupu klõpsamisel)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Birdseye port" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(taaskäivita Thonny peale selle muutmist)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Käivitamine" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Terminali emuleerimine" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "toetab põhilisi ANSI värvikoode ja stiile" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Maksimaalne ridade arv." #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "NB! Suurte väärtustega võib jõudlus halveneda!" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Maksimaalne realõigu pikkus enne \"kokkupigistamist\"" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Skripti käivitamine terminalis" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Näita peale programmi lõppu Pythoni käsurida" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Hoia terminali aken avatuna ka peale Pythoni protsessi lõppemist" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "NB! Automaatset sulgemist tuleb lubada Terminali seadetes\n" "(Profiles → Shell → When the shell exits)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Terminal" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "Kasutajaliidese stiil" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Süntaksi stiil" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Redaktori font" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "Sisend/väljund font" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Eelvaade" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "See on kommentaar" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "Vastus on" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "sulgemata_string" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "blaa, blaa" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "NB! Mõned stiilielemendid muutuvad alles peale Thonny taaskäivitamist!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Sisesta täisarv" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Stiil & font" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Ava Thonny programmikaust..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Ava Thonny andmekaust..." #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Avaleht" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Abiinfo sisukord" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "CircuitPythoni seade" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "MicroPythoni seade" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Ühenda seade arvutiga ja vali allpoolt selle port" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "otsi oma seadme nime või fraase \"USB Serial\" või \"UART\"" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Kui sa ei leia seda, siis pead võibolla installima sobiva USB draiveri." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Port" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Proovi tuvastada port automaatselt" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython (üldine)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Prindi..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Ava süsteemi käsurida / terminal" #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Detailid" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Installi sõltuvusfaili järgi" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Installi lokaalsest failist" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "See dialoog on mõeldud Thonny pistiprogrammide haldamiseks.\n" "Kui soovid installida pakke enda programmide jaoks, siis kasuta 'Tööriistad → Halda lisapakke...'" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (üldine)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Suurenda ridade taanet" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Vähenda ridade taanet" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Mine\n" "tavalisse\n" "režiimi" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "Veendu, et MicroPython oleks su micro:bit-ile installitud." #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "Ära unusta, et main.py toimib ainult siis kui MicroPython on ilma peaskriptita." #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "Installi värskeim MicroPython BBC micro:bit-ile" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "micro:bit-i asukoht:" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Installitav versioon:" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "palun oota" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "NB! kõik failid micro:bit-il kustutatakse" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Installin ..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Valmis!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Võid nüüd selle akna sulgeda." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Püsivara" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "Ava MicroPythoni installimise või uuendamise dialoog" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "Ei leia draivi '%s'." #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "Veendu, et micro:bit on ühendatud!" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Kas soovid jätkata ja draivi ise valida?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "Ei leia draivi nimega '%s'. Kas soovid selle ise valida?" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Leidsin mitu draivi nimega '%s'. Kas soovid ühe neist ise valida?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Ei leia sobivat draivi." #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d üksust" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Liiguta Prügikasti" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Liiguta Prügikasti" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Kustuta" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Uus kaust" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Omadused" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Salvestusruum" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "Tee" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Kausta omadused" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Faili omadused" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "baiti" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "Suurus" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Muudetud" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "Kustutan %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Liigutan %s asukohta %s" #: thonny/code.py:203 msgid "Loading" msgstr "Laadin" #: thonny/code.py:297 msgid "Saving" msgstr "Salvestan" #: thonny/running.py:1408 msgid "Working..." msgstr "Töötan..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Laadin %s üles asukohta %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Laadi üles asukohta %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "Laadi %s alla asukohta %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Laadi alla asukohta %s" thonny-3.2.7/thonny/locale/it_IT/0000755000175000017500000000000013611777205017653 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/it_IT/LC_MESSAGES/0000755000175000017500000000000013611777205021440 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/it_IT/LC_MESSAGES/thonny.mo0000644000175000017500000003616213611773167023327 0ustar annamaaannamaa00000000000000L||$}* +-!C7e&   x  &  $.G $,%A*g +H[b!}   %1B_ eqx     6";QkpyF  3FOety z-@ Sa| +<-E IU[^?oC, 4 ?JHR:3;K ]g{ B &  ( 4 BO_ hry }      2&/Y: 1-7 eot| >0!  /< - ; M @!H!W!f! l!v! {!!!!! !!2! ""'"@"DE" """#"" " # # #1%# W#c#u##*&$)Q$ {$ $A$5$+ %35%"i% %%%%%%{%b&t&6&&&&& ''#')' 0'='U'((.( D(Q((i(((( (() )/%))U)())))() **5*P*_*f*k*}*****!***+ + ++#+2+F+]+b+g+m+++++++z,,,<,,",-")-L- Q- ]-Qh--- --. .".:.O.V.n.~. .. .~.1/K/a/w/////1/I00e000000E0M1#a1+11 11 1O1-252%M2!s22?2 222 330373 U3Lb333 3-3 344(4:4S4 \4f4o4v444'444 45 5$5?5O5<_5455F5/6K6Q6c6{66+666667A71Q7*7 7 78887999 : :: #:/:2:;:R:f:y:0: ::::U;\;m;;%;; ;;;<8<><N<`<(restart Thonny after changing this)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAlternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portCan't close yetCan't find package name from the list:CancelCancel the process?Case sensitiveChange font sizeClearClear shellClick CloseClose allConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)Connect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Decrease font sizeDeleteDisable notification soundDisabled checks (one id per line)DisconnectDo you want to overwrite '%s' ?Dock user windowsDocumentationDone!DownDownload to %sDownloading %s to %sEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus shellFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Full screenHeapHelpHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageIO fontIf you can't find it, you may need to install proper USB driver first.Increase font sizeInstallInstalled to:Installed version:Installing ...InterpreterInterrupt executionKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASManage packages for %sManage packages...Manage plug-ins...Maximize viewMay make debugging slower.Move to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Some style elements change only after restarting Thonny!NB! Thonny only supports Python 3.5 and laterNewNext objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open...Options...Overwrite?PackagePackage '{}' is required for installing and uninstalling other packages.PastePerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PreviewPrevious objectProgram argumentsPyPI pagePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow line numbersSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStopSummaryTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis is a commentThis program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsToggle commentToolsUncommentUndoUninstallUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?Working...You can now close this dialog.You need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahexact package nameherelook for your device name, "USB Serial" or "UART"please waitpython executablevirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: it (riavvia Thonny dopo aver cambiato questo)Ambiente virtuale speciale (sconsigliato)Su BirdseyeSu ThonnyPermette il completamento del codice con il tasto Tab nella shellPermette il completamento del codice con il tasto TabPermetti solo una singola istanza di ThonnyInterprete Python 3 alternativo o ambiente virtualeSei sicuro di voler disinstallare?AssistenteAutoreAuto-completamentoIndietroTorna al riquadro correnteDirectory errataBirdseye è un debugger Python che deve essere installato separatamente. Vuoi aprire la pagina di aiuto e saperne di più?Porta di BirdseyeImpossibile chiudereImpossibile trovare il nome del pacchetto nella lista:AnnullaAnnulla il processo?Case sensitiveCambia la dimensione del fontPulisciPulisci la shellClickChiudiChiudi tuttoLa configurazione è stata aggiornata. Riavvia Thonny per lavorare in modalità normale. (Vedi 'Strumenti → Opzioni → Generale' se ci ripensi.)Collega il tuo dispositivo al computer e seleziona la porta corrispondente quì sottoCopiaCopia nella clipboardSto copiandoSto copiando %s su %sImpossibile trovare il pacchetto in PyPlImpossibile trovare il pacchetto in PyPlCrea un nuovo ambiente virtualeSto creando un ambiente virtualeTagliaDebugDebug dello script correnteEsegue il debug dello script attuale (birdseye)Debug dello script corrente (più veloce)Debug dello script corrente (più bello)Riduci dimensione fontCancellaDisabilita i suoni di notificaDisattiva i controlli (una id per linea)DisconnettiVuoi sovrascrivere '%s'?Disponi le finestre utenteDocumentazioneFatto!GiùSto scaricando %sSto scaricando %s su %sModificaEditorFont dell'editorInserisci un interoImmetti la stringa da sostituire.ErroreCodice di errore:Errore:EventiEccezioneEsciEsci da ThonnyEspande nella ShellEsporta i log d'uso...FileFileTrovaTrova & SostituisciTrova una pacchetto PyPlTrova:FirmwareVai all'editorVai alla shellPer raggioni di efficenza, la shell non mostra le righe molto lunghe completamente (vedi Strumenti => Opzioni => Shell). Qui puoi interagire con il frammento di testo originale.Schermo interoHeapAiutoEvidenzia la riga corrente (richeide il riavvio dell'editor)Evidenzia le variabili localiEvidenzia i nomi che corrispondonoEvidenzia le parentesiEvidenzia gli elementi di sintassiHomePagine Homefont di IOSe non riesci a trovarlo potresti aver bisgno di installare un driver USB adatto.Aumenta la dimensione del fontInstallaInstalla su:Versione installata:Sto installando...InterpreteInterrompi l'esecuzioneInterpreti esistentiLinguaUltima versione stabileUltima versioneCaricaSto caricandoTrova un intepretePosizione: Made in University of Tartu, Estonia, con il contributo della comunità open-source, Raspberry Pi Foundation e Cybernetica ASGestisci pacchetti per %sGestisci i pacchetti:Gestisci i plug-in...Vista massimizzataPuò renderelento il debug. Sposta nel cestinoElimina definitivamenteSto spostando %s su %sNB! Tutti i file su micro:bit saranno cancellati!NB! Alcuni elementi dello stile cambiano solo dopo aver riavviato Thonny!NB! Thonny supporta solo Python 3.5 o successiviNuovoProssimo oggettoNoteOKAnalizzatore di oggettiAttiva l'assistente automaticamente se ci sono allerte sul tuo codiceAttiva l'Assistente automaticamente se il programma va in crash per un erroreApri la cartella dei dati di ThonnyApri la cartella di porogramma di Thonny...Apri...Opzioni...Sovrascrivere?PacchettoIl pacchetto '{}' è necessario per installare e disinstallare altri pacchetti.IncollaEsegue i controlli MyPyEsegue i controlli Pylint selezionatiPer favore controlla lo spelling!PlotterIl plotter visualizza una serie di numeri stampati nella Shell.AnteprimaOggetto precedenteArgomenti del programmaPagina PyPlInterprete PythonChiudiVuoi veramente disinstallare?File recentiMassima lunghezza di linea raccomandata (0 per eliminare i margini di linea)RipetiAggiornaRinomina...Riapri tutti i file dalla sessione precedenteSostituisciSostituisci tuttoSostituisci con:Sostituisci+TrovaSegnalazione di problemiRichiedeRicheide:RiprendiEseguiEsegui & DebugEsegui / riprendiEsegui lo script correnteEsegui lo script corrente nel terminaleEsegui fino al cursoreSalvaSalva come...Salva una copia...Sto salvandoVedi Aiuto per i dettagli.Seleziona tuttoSeleziona tuttoSeleziona una directory vuota per un nuovo ambiente virtualeSeleziona uan directory esistente o creane una nuovaSeleziona l'interpreteLa directory selezionata non è vuota. Selezionane un'altra o annulla.Invia un EOF / riavvio softShellMostra il plotterMostra i numeri di rigaTesto compresso (%d caratteri)StackInizia selezioando un pacchetto a sinistra.Passo indietroFermaIndiceEmulazione di terminaleLa risposta èIl processo sta ancora girando. Sei sicuro di volerlo annuallare?Lo stesso interprete che gira su Thonny (default)Il testo specificato non è stato trovato!Temi & FontQuesto riquadro serve per le tue note di lavoro -- istruzioni di assegnazione, pezzi di codice, qualunque cosa. Qualunque cosa sarà salvata automaticamente e ricaricata la prossima volat che aprirai Thonny. Puoi cancellare questo testo per fare spazio alle tue note.Questo computerQuesto è un commentoIl programma viene fornito SENZA ALCUNA GARANZIA! E' software libero e può essere ridistribuito a determinate condizioni. Per maggiori dettagli visitate https://opensource.org/licenses/MITQuesto ambiente è mantenuto automaticamente da Thonny.Ozioni di ThonnyAttiva commentiStrumentiDecommentaAnnullaDisinstallaSuAggiornaAggiorna le dipendenzeAggiorna o installaSto caricando su %Sto aggiornando %s su %sUsa il comando "Stop" per annullare il debuggingVariabiliCronologia delle versioniVersione da installare:MostraQuale interprete o dispositivo deve essere usato da Thonny per eseguire il tuo codiceSto lavorando...Puoi chiudere questa finestra.Devi selezionare un file!Il tuo interprete non è nella lista?Zoomtutti i filebla, blanome esatto del pacchettoquicerca il nome del tuo dispositivo, "USB Serial" o "UART"attendere pregoeseguibile pythonambiente virtualethonny-3.2.7/thonny/locale/it_IT/LC_MESSAGES/thonny.po0000644000175000017500000010603713611773167023331 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: it\n" #: thonny/workbench.py:355 msgid "File" msgstr "File" #: thonny/workbench.py:356 msgid "Edit" msgstr "Modifica" #: thonny/workbench.py:357 msgid "View" msgstr "Mostra" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Esegui" #: thonny/workbench.py:360 msgid "Tools" msgstr "Strumenti" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Aiuto" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Interprete Python 3 alternativo o ambiente virtuale" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Ambiente virtuale speciale (sconsigliato)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Esci" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Riduci dimensione font" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Vai all'editor" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Vai alla shell" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Vista massimizzata" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Schermo intero" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Argomenti del programma" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "Su Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Made in\n" "University of Tartu, Estonia,\n" "con il contributo della \n" "comunità open-source,\n" "Raspberry Pi Foundation\n" "e Cybernetica AS" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Il programma viene fornito\n" "SENZA ALCUNA GARANZIA!\n" "E' software libero e può essere \n" "ridistribuito a determinate condizioni.\n" "Per maggiori dettagli visitate\n" "https://opensource.org/licenses/MIT" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Cronologia delle versioni" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Segnalazione di problemi" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Attiva l'Assistente automaticamente se il programma va in crash per un errore" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Attiva l'assistente automaticamente se ci sono allerte sul tuo codice" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Esegue i controlli Pylint selezionati" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Esegue i controlli MyPy" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Disattiva i controlli (una id per linea)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Assistente" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Auto-completamento" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Quale interprete o dispositivo deve essere usato da Thonny per eseguire il tuo codice" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Interprete" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "Su Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye è un debugger Python che deve essere installato separatamente.\n" "\n" "Vuoi aprire la pagina di aiuto e saperne di più?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Esegue il debug dello script attuale (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Attiva commenti" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Decommenta" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Annulla" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Ripeti" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Taglia" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Copia" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Incolla" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Seleziona tutto" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Esegui fino al cursore" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Impossibile chiudere" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Usa il comando \"Stop\" per annullare il debugging" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Disponi le finestre utente" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Evidenzia i nomi che corrispondono" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Evidenzia le variabili locali" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Evidenzia le parentesi" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Evidenzia gli elementi di sintassi" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Evidenzia la riga corrente (richeide il riavvio dell'editor)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Permette il completamento del codice con il tasto Tab" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Permette il completamento del codice con il tasto Tab nella shell" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Mostra i numeri di riga" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Massima lunghezza di linea raccomandata\n" "(0 per eliminare i margini di linea)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Editor" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Esporta i log d'uso..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Eventi" #: thonny/plugins/files.py:307 msgid "Files" msgstr "File" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Trova & Sostituisci" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Trova:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Sostituisci con:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Case sensitive" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Su" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Giù" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Trova" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Sostituisci" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Sostituisci+Trova" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Sostituisci tutto" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Immetti la stringa da sostituire." #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "Il testo specificato non è stato trovato!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Permetti solo una singola istanza di Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Riapri tutti i file dalla sessione precedente" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Disabilita i suoni di notifica" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "" #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Heap" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Lingua" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Questo riquadro serve per le tue note di lavoro -- istruzioni di assegnazione, pezzi di codice, qualunque cosa.\n" "\n" "Qualunque cosa sarà salvata automaticamente e ricaricata la prossima volat che aprirai Thonny.\n" "\n" "Puoi cancellare questo testo per fare spazio alle tue note." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Note" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Oggetto precedente" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Prossimo oggetto" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Analizzatore di oggetti" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Trova una pacchetto PyPl" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Disinstalla" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Chiudi" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Click" #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "qui" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Aggiorna" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Installa" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Impossibile trovare il pacchetto in PyPl" #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "nome esatto del pacchetto" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Ultima versione stabile" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Ultima versione" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Indice" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Autore" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Pagine Home" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Documentazione" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "Pagina PyPl" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Richiede" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Vuoi veramente disinstallare?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Sei sicuro di voler disinstallare?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Torna al riquadro corrente" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Variabili" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Questo computer" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Aggiorna" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Errore" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Devi selezionare un file!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Sovrascrivere?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Vuoi sovrascrivere '%s'?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Nuovo" #: thonny/code.py:526 msgid "Open..." msgstr "Apri..." #: thonny/code.py:528 msgid "Load" msgstr "Carica" #: thonny/code.py:537 msgid "Recent files" msgstr "File recenti" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Chiudi tutto" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Salva" #: thonny/code.py:583 msgid "Save as..." msgstr "Salva come..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Salva una copia..." #: thonny/code.py:603 msgid "Rename..." msgstr "Rinomina..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Ozioni di Thonny" #: thonny/running.py:94 msgid "Run current script" msgstr "Esegui lo script corrente" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Esegui lo script corrente nel terminale" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "" #: thonny/running.py:139 msgid "Stop" msgstr "Ferma" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Interrompi l'esecuzione" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Invia un EOF / riavvio soft" #: thonny/running.py:172 msgid "Disconnect" msgstr "Disconnetti" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Interpreti esistenti" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Il tuo interprete non è nella lista?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Trova un inteprete" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "eseguibile python" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "NB! Thonny supporta solo Python 3.5 o successivi" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Crea un nuovo ambiente virtuale" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Seleziona uan directory esistente o creane una nuova" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Interprete Python" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "tutti i file" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Seleziona una directory vuota per un nuovo ambiente virtuale" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Directory errata" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "La directory selezionata non è vuota.\n" "Selezionane un'altra o annulla." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Sto creando un ambiente virtuale" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Pulisci la shell" #: thonny/shell.py:126 msgid "Plotter" msgstr "Plotter" #: thonny/shell.py:245 msgid "Clear" msgstr "Pulisci" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Mostra il plotter" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Per raggioni di efficenza, la shell non mostra le righe molto lunghe\n" "completamente (vedi Strumenti => Opzioni => Shell).\n" "Qui puoi interagire con il frammento di testo originale." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Copia nella clipboard" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Espande nella Shell" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Testo compresso (%d caratteri)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Il plotter visualizza una serie\n" "di numeri stampati nella Shell." #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Vedi Aiuto per i dettagli." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Sto copiando" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Sto copiando\n" " %s\n" "su\n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Annulla" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "OK" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Annulla il processo?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Il processo sta ancora girando.\n" "Sei sicuro di volerlo annuallare?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Seleziona tutto" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Shell" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Lo stesso interprete che gira su Thonny (default)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Questo ambiente è mantenuto automaticamente da Thonny." #: thonny/workbench.py:532 msgid "Location: " msgstr "Posizione: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Opzioni..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Aumenta la dimensione del font" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Cambia la dimensione del font" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Zoom" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Esci da Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "Chiudi" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "La configurazione è stata aggiornata. Riavvia Thonny per\n" "lavorare in modalità normale.\n" "\n" "(Vedi 'Strumenti → Opzioni → Generale' se ci ripensi.)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Seleziona l'interprete" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Riprendi" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Esegui / riprendi" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Debug dello script corrente" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Debug" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Debug dello script corrente (più bello)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Debug dello script corrente (più veloce)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Passo indietro" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Indietro" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Stack" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Eccezione" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "" #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "" #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "" #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "" #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Aggiorna o installa" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Inizia selezioando un pacchetto a sinistra." #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "ambiente virtuale" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "" #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Versione installata:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Installa su:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Per favore controlla lo spelling!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Impossibile trovare il pacchetto in PyPl" #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Codice di errore:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Impossibile trovare il nome del pacchetto nella lista:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Il pacchetto '{}' è necessario per installare e disinstallare altri\n" "pacchetti." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Pacchetto" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Gestisci pacchetti per %s" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "" #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "" #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "" #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "" #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Aggiorna le dipendenze" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Richeide:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Errore:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Gestisci i pacchetti:" #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Gestisci i plug-in..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "" #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "" #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "" #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Può renderelento il debug. " #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Porta di Birdseye" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(riavvia Thonny dopo aver cambiato questo)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Esegui & Debug" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Emulazione di terminale" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "" #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Font dell'editor" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "font di IO" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Anteprima" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "Questo è un commento" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "La risposta è" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "bla, bla" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "NB! Alcuni elementi dello stile cambiano solo dopo aver riavviato Thonny!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Inserisci un intero" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Temi & Font" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Apri la cartella di porogramma di Thonny..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Apri la cartella dei dati di Thonny" #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Home" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Collega il tuo dispositivo al computer e seleziona la porta corrispondente\n" "quì sotto" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "cerca il nome del tuo dispositivo, \"USB Serial\" o \"UART\"" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Se non riesci a trovarlo potresti aver bisgno di installare un driver USB adatto." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "" #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "" #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "" #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "" #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Versione da installare:" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "attendere prego" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "NB! Tutti i file su micro:bit saranno cancellati!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Sto installando..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Fatto!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Puoi chiudere questa finestra." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Firmware" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "" #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Sposta nel cestino" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Elimina definitivamente" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Cancella" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Sto spostando %s su %s" #: thonny/code.py:203 msgid "Loading" msgstr "Sto caricando" #: thonny/code.py:297 msgid "Saving" msgstr "Sto salvando" #: thonny/running.py:1408 msgid "Working..." msgstr "Sto lavorando..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Sto aggiornando %s su %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Sto caricando su %" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "Sto scaricando %s su %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Sto scaricando %s" thonny-3.2.7/thonny/locale/ru_RU/0000755000175000017500000000000013611777205017677 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/ru_RU/LC_MESSAGES/0000755000175000017500000000000013611777205021464 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/ru_RU/LC_MESSAGES/thonny.mo0000644000175000017500000010337213611773167023351 0ustar annamaaannamaa00000000000000V ||}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/;;;J<N3=X= = =M=m?>o>U?s?_@?c@@ @@ @.@'A@ABB3B,FB8sB<B B)B C*ACilCC"CD!%DGDPDbDqD!D D*DEFF$FF#F.Gb=G1GNGC!H8eHHH2H7HC+I?oIiI,J=FJJJJJ!J0JG/KwKVK,K>LQLajL LLLL M#M4MRM/lM MM MMM MM(N;;NwNN N NNN NN" O/O"AO6dOyOhQ~Q QQcQ R#Ru?R@R:R21SFdSS!SS+STTU,[V=VVV9V52WFhWW(WW X%$XJXrMX/XX4Y9YYYlY}YYRYsZ6w[\R]?^/W^(^)^^S^HC_/__ __(` .`O`?o``{abbfbb:cd dddeee#eenf4f'&gWNgg5g~gzhhGi]ibi kivi(i ioi4jRjcj(lj?j?j kg"kk-kPkl!+lMl%gl&lllll#m 6m*Amlmmn#n4nNnQlnnnnn$oBo Yoeozo&o)o.oD p&RpDyppp pq=$qbqxqjqhq+drirDr?sPsZps,s s7t=t7Ft~t t ttt?t u 5u7Bu0zu uu#u uvuUlv0vv wx.y6zzD {)R{o|||}5}-R}}M}I}:/~j~g~"~ "/C s~2&Pm#€ɀ!xN7!7*YI΃* 8WC#'*GZ}!hE)І%d items(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)(restart Thonny after changing this)(used when clicking Debug toolbar button)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAdvanced install / upgrade / downgradeAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAllow stepping into libraries (ie. outside of main script directory)Alternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portBrowse the packagesBugtrackerCan't close yetCan't find package name from the list:Can't find suitable diskCancelCancel the process?Case sensitiveChange font sizeChange working directory to script directory on Run / DebugCircuitPython (generic)CircuitPython deviceClearClear shellClickClick CloseClose allClose othersComment outConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)ConfirmationConnect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find disk '%s'.Could not find disk '%s'. Do you want to locate it yourself?Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDeleteDeleting %sDesired versionDetailsDirectory propertiesDisable notification soundDisabled checks (one id per line)DisconnectDo you want to continue and locate the disk yourself?Do you want to overwrite '%s' ?Dock user windowsDocumentationDon't forget that main.py only works without embedded main script.Done!DownDownload to %sDownloading %s to %sEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFile propertiesFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus intoFocus shellFont scaling modeFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: ru %d элементов(В этом случае бэкенд Thonny будет использовать такой же интерпретатор, таким образом оба способа будут управлять одним и тем же набором пакетов.)(перезапустите Thonny после этих изменений)(используется при щелчке кнопки отладчика)Особое виртуальное окружение (не рекомендуется)О BirdseyeО ThonnyПродвинутая установка, обновление и откатРазрешить использование «Tab» для автозавершения в оболочкеРазрешить использование «Tab» для автозавершения в редактореРазрешить запускать только один экземпляр ThonnyРазрешить переход в библиотеки (т. е. в модули за пределами каталога программы)Другой интепретатор Python 3 или виртуальное окружениеВы уверены, что хотите удалить это?АссистентАвторАвтозавершениеНазадВернуться в текущее окноНеправильный каталогBirdseye — это отладчик Python, который требует отдельной установки. Открыть страницу помощи для подробностей?Порт BirdseyeПросмотр пакетовБагтрекерПока невозможно закрытьИмя пакета не найдено в списке:Не удалось найти подходящий дискОтменаОтменить этот процесс?С учётом регистраИзменить размер шрифтаИзмените рабочий каталог для программы в Запуск / ОтладкаCircuitPython (общий)Устройство CircuitPythonОчиститьОчистить оболочкуКликЩёлкните ЗакрытьЗакрыть всёЗакрыть остальныеЗакомментироватьКонфигурация была обновлена. Перезапустите Thonny для работы в обычном режиме. (Зайдите в «Инструменты → Параметры → Общие», если вы захотите изменить своё решение)ПодтверждениеПодключите устройство к компьютеру и выберите соответствующий порт нижеСкопироватьКопировать в буфферКопированиеКопирование %s в %sНе удалось найти диск «%s»Не удалось найти диск «%s». Хотите выбрать его вручную?Не удалось найти пакет в PyPIПоиск этого пакета в PyPI не дал результатов.Создать новое виртуальное окружениеСоздать виртуальное окружениеВырезатьОтладитьОтладить текущую программуОтладить текущий скрипт (birdseye)Отладить текущую программу (быстрее)Отладить текущую программу (лучше)Режим отладки (предоставляет более подробную информацию)Уменьшить размер шрифтаУменьшить отступ выбранных строкУдалитьУдаление %sЖелаемая версияПодробностиСвойства каталогаОтключить звук оповещенийОтключить проверки (один код на строку)ОтключитьсяХотите ли вы продолжить и выбрать диск вручную?Хотите перезаписать '%s' ?Прикрепить пользовательское окноДокументацияНе забудьте, что main.py работает без встроенного main-script.Готово!ВнизЗагрузить в %sЗагрузка %s в %sПравкаРедакторШрифт редактораВведите числоВведите строку для заменыОшибкаКод ошибки:Ошибка:СобытияИсключениеВыходВыйти из ThonnyРазвернуть в оболочкеЭкспорт журнала использования...ФайлСвойства файлаФайлыНайтиНайти и заменитьНайти пакет в PyPIНайти:ПрошивкаПерейти в редакторПерейти вПерейти в оболочкуРежим масштабирования шрифтаПо причине производительности оболочка избегает отображения очень длинных строк целиком (смотрите Инструменты => Параметры => Оболочка). Здесь вы можете взаимодействовать с оригинальным фрагментом текста.Найдено несколько «%s» дисков. Хотите выбрать один из них?Полный экранОбщиеКучаРежим кучи включён. Закройте окно кучи для отключения.ПомощьСодержание справкиПодсвечивать текущую строку (потребуется перезапуск редактора)Подсвечивать локальные переменныеПодсвечивать совпадающие именаПодсвечивать парные скобкиПодсвечивать синтаксические элементыДомДомашняя страницаУСТАНОВИТЬШрифт окна ввода-выводаЕсли вы не можете найти его, попробуйте сначала установить соответствующий драйвер USB.Если вы не знаете, где взять пакет, тогда, скорее всего, вам следует поискать в Python Package Index. Начните с ввода имени пакета в окне поиска выше и нажмите ENTER.Если вы действительно этого хотите, тогда установите пакет из командной строки.Увеличить размер шрифтаУвеличить отступ выбранных строкУстановитьУстановить с PyPIУстановить из локального файлаУстановить из файла requirements.txtУстановить последний MicroPython на BBC micro:bitУстановлено в:Установленная версия:Установка...ИнтерпретаторПрервать выполнениеВОставлять окно терминала открытым после завершения программыИзвестные интерпретаторыЯзык (Language)Последняя стабильная версияПоследняя версияЗагрузитьЗагрузкаНайти другойРасположение: Записывать использование программы в журналПохоже, вы хотите установить пакет, относящийся к Thonny. Если вы хотите установить плагин для Thonny, тогда используйте «Инструменты → Управление плагинами...» Вы уверены, что хотите установить %s для бэкенда?Похоже, вы хотите установить старую версию плагина для Thonny (в ней не указана версия Thonny). Если вы действительно этого хотите, тогда установите плагин из командной строки.Разработано в эстонском Тартуском университете при участии сообщества свободного программного обеспечения, фонда разработки Raspbery Pi и компании CyberneticaУбедитесь, что MicroPython установлен на ваш micro:bit.Убедитесь, что ваш micro:bit подключён!Управление пакетами для %sУправление пакетами...Управление плагинами..РазвернутьМаксимальная длина строки, подлежащей сжатиюМаксимальное число удерживаемых строк.Может замедлить отладчик.MicroPython (общий)Устройство MicroPythonИзмененПереместить в КорзинуПеренести в МусорПеремещение %s в %sNB! Все файлы на micro:bit будут удалены!NB! Автоматическое закрытие должно быть включено в настройках терминала (Профили → Оболочка → При выходе из оболочки)NB! Большие значения могут привести к ухудшению производительности!NB! Перезапустите Thonny после изменения этих параметров!NB! Некоторые элементы оформления изменятся только после перезапуска Thonny!NB! Может быть доступной другая версия, совместимая с текущей версией Thonny. Щёлкните кнопку «...» чтобы выбрать версию для установки.NB! Thonny поддерживает Python 3.5 и вышеNB! Нужно перезапустить Thonny после установки, обновления или удаления плагина.НовоеНовый каталогНовые пакеты также будут установлены в этот каталог. Для других целей каталоги необходимо настроить.Следующий объектЗаметкиОКИнспектор объектовАвтоматически открывать окно Ассистента при обнаружении предупреждений в вашей программеАвтоматически открывать окно Ассистента при сбое программыОткрыть каталог данных Thonny...Открыть каталог Thonny...Автоматически открывать и закрывать окно стекаОткрыть повтор...Открыть системную оболочку...Открыть окно для установки или обновления MicroPython на вашем устройствеОткрыть...Открывает окно стека при первом вызове и закрывает его, когда программа возвращается во внешний блок.Параметры...ИзПланЧерезПерезаписать?Перезаписать тему «%s»ПакетПакет «{}» необходим для установки и удаления других пакетов.Каталог пакетовВставитьПутьВыполнить проверки MyPyВыполнить отмеченные проверки PylintПроверьте правильность написания!ПлотерПлоттер показывает серии чисел, напечатанных в оболочкеПортПредпочитаемый отладчикПерейти в Python REPL после завершения программыПредпросмотрПредыдущий объектРаспечатать...Аргументы программыПараметры программы:Дерево программыСвойстваСтраница PyPIРежим Pygame ZeroИнтерпретаторы PythonВыйтиДействительно удалить?Недавние файлыРекомендуемая максимальна длина строки (укажите 0 для отключения линейки)ПовторитьОбновитьОбычный режимПереименовать...Переоткрыть все файлы из предыдущего сеансаЗаменитьЗаменить всёЗаменить на:Заменить и найтиСообщить о проблемеЗависимостиНужно:ПродолжитьВыполнитьЗапустить и отладитьЗапустить / продолжитьЗапустить текущий скриптЗапустить текущий скрипт в терминалеВыполнить до курсораЗапуск текущей программы в терминалеСохранитьСохранить как...Сохранить копию...СохранениеСмотрите Помощь для подробностейВыбрать ВсёВыделить всёВыбрать пустой каталог для нового виртуального окруженияВыберите существующий или создайте новый пустой каталогВыберите интерпретаторВыбранный каталог не пустой. Выбрать другой или отменить.Послать EOF / программная перезагрузкаОболочкаПоказать ПлоттерПоказывать вызовы функций (фреймы) в разных окнахПоказывать номера строкРазмерПропущенный текст (%d символов)СтекНачните с выбора пакета слева.Шаг назадЗайтиВыйтиПерепрыгнутьОстановитьОстановить и перезапустить бэкендМесто в хранилищеСводкаПереключиться в обычный режимТема подсветки синтаксисаЦель:ТерминалЭмуляция терминалаОтветПроцесс всё ещё выполняется. Вы уверены, что хотите прервать его?Тот же интерпретатор, что и у Thonny (по умолчанию)Указанный текст не найден!Тема & шрифтЭто окно можно использовать для ваших рабочих заметок — значений, примеров кода, чего угодно. Всё, что вы здесь напишете, будет автоматически сохраняться и загружаться при перезапуске Thonny. Этот текст можно смело удалить и начать писать свои собственные заметки.Этот компьютерЭто окно для управления плагинами и зависимостями Thonny. Если вы хотите установить пакеты для ваших программ, тогда перейдите в «Инструменты → Управление пакетами...»В этом окне перечислены все доступные пакеты, но доступны для обновления и удаления только пакеты изЭто комментарийЭтот пакет требует другой версии Thonny:Это ПО поставляется без каких-либо гарантийных обязательств. Это свободное ПО и вы можте свободно распространять его на условиях лицензии МИТ https://opensource.org/licenses/MITЭто виртуальное окружение автоматически поддерживается ThonnyПараметры ThonnyПлагины ThonnyПлагины Thonny без зависимостейПереключить комментарийИнструментыПопытаться обнаружить порт автоматическиРежим пользовательского интерфейса (ПИ)Коэффициент масштабирования ПИТема интерфейсаСнимите отметку если вы хотите более традиционный стильРаскомментироватьВернутьДеинсталлироватьНеподходящие зависимостиВверхОбновитьЗависимости для обновленияОбновить или удалитьВыгрузить в %sВыгрузка %s в %sДля прекращения отладки используйте «Стоп»ПеременныеИстория версийВерсия к установке:ВидКакой интерпретатор или какое устройство должен использовать Thonny для запуска вашей программы?Вы можете только просматривать пакеты с этим интерпретатором. Используйте 'Инструменты → Открыть системную оболочку...' для установки, обновления и удаления.Обработка...Переносить строки (может замедлять работу)Теперь можно закрыть это окно.Необходимо ввестиВам нужно выбрать файл!Ваш интерпретатор отсутствует в списке?Приблизитьвсе файлыбла, блабайтточное название пакетаздесьнайдите имя вашего устройства, «USB Serial» или «UART»Расположение micro:bit:пожалуйста подождитеисполняемый модуль pythonподдерживает основные ANSI-цвета и стилидля указания и установки пакета из файла (обычно с расширением .whl, .tar.gz или .zip). для указания файла requirements.txt и установки перечисленных в нём пакетовнезакрытая_строкапакеты из пользовательского каталогавиртуальное окружениеthonny-3.2.7/thonny/locale/ru_RU/LC_MESSAGES/thonny.po0000644000175000017500000013726613611773167023365 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: ru\n" #: thonny/workbench.py:355 msgid "File" msgstr "Файл" #: thonny/workbench.py:356 msgid "Edit" msgstr "Правка" #: thonny/workbench.py:357 msgid "View" msgstr "Вид" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Выполнить" #: thonny/workbench.py:360 msgid "Tools" msgstr "Инструменты" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Помощь" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Другой интепретатор Python 3 или виртуальное окружение" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Особое виртуальное окружение (не рекомендуется)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Выход" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Уменьшить размер шрифта" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Перейти в редактор" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Перейти в оболочку" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Развернуть" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Полный экран" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Аргументы программы" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "О Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Разработано в\n" "эстонском Тартуском университете\n" "при участии сообщества свободного\n" "программного обеспечения,\n" "фонда разработки Raspbery Pi\n" "и компании Cybernetica" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Это ПО поставляется без каких-либо\n" "гарантийных обязательств.\n" "Это свободное ПО и вы можте свободно\n" "распространять его на условиях\n" "лицензии МИТ\n" "https://opensource.org/licenses/MIT" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "История версий" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Сообщить о проблеме" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Автоматически открывать окно Ассистента при сбое программы" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Автоматически открывать окно Ассистента при обнаружении предупреждений в вашей программе" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Выполнить отмеченные проверки Pylint" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Выполнить проверки MyPy" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Отключить проверки (один код на строку)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Ассистент" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Автозавершение" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Какой интерпретатор или какое устройство должен использовать Thonny для запуска вашей программы?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Интерпретатор" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "О Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye — это отладчик Python, который требует отдельной установки.\n" "\n" "Открыть страницу помощи для подробностей?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Отладить текущий скрипт (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Переключить комментарий" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Закомментировать" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Раскомментировать" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Вернуть" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Повторить" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Вырезать" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Скопировать" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Вставить" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Выделить всё" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Выполнить до курсора" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Пока невозможно закрыть" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Для прекращения отладки используйте «Стоп»" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Прикрепить пользовательское окно" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Подсвечивать совпадающие имена" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Подсвечивать локальные переменные" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Подсвечивать парные скобки" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Подсвечивать синтаксические элементы" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Подсвечивать текущую строку (потребуется перезапуск редактора)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Разрешить использование «Tab» для автозавершения в редакторе" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Разрешить использование «Tab» для автозавершения в оболочке" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Показывать номера строк" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Рекомендуемая максимальна длина строки (укажите 0 для отключения линейки)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Редактор" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Экспорт журнала использования..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "События" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Файлы" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Найти и заменить" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Найти:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Заменить на:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "С учётом регистра" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Вверх" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Вниз" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Найти" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Заменить" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Заменить и найти" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Заменить всё" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Введите строку для замены" #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "Указанный текст не найден!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Разрешить запускать только один экземпляр Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Переоткрыть все файлы из предыдущего сеанса" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Отключить звук оповещений" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Режим масштабирования шрифта" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Режим кучи включён.\n" "Закройте окно кучи для отключения." #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Куча" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Язык (Language)" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Это окно можно использовать для ваших рабочих заметок — значений, примеров кода, чего угодно.\n" "\n" "Всё, что вы здесь напишете, будет автоматически сохраняться и загружаться при перезапуске Thonny.\n" "\n" "Этот текст можно смело удалить и начать писать свои собственные заметки." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Заметки" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Предыдущий объект" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Следующий объект" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Инспектор объектов" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "План" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Режим Pygame Zero" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Найти пакет в PyPI" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Деинсталлировать" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Закрыть" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Щёлкните " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "здесь" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Обновить" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Установить" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Не удалось найти пакет в PyPI" #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "точное название пакета" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Последняя стабильная версия" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Последняя версия" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Сводка" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Автор" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Домашняя страница" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Багтрекер" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Документация" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "Страница PyPI" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Зависимости" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Действительно удалить?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Вы уверены, что хотите удалить это?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Вернуться в \n" "текущее окно" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Переменные" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Этот компьютер" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Обновить" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Перейти в" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Ошибка" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Вам нужно выбрать файл!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Перезаписать?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Хотите перезаписать '%s' ?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Новое" #: thonny/code.py:526 msgid "Open..." msgstr "Открыть..." #: thonny/code.py:528 msgid "Load" msgstr "Загрузить" #: thonny/code.py:537 msgid "Recent files" msgstr "Недавние файлы" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Закрыть всё" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Сохранить" #: thonny/code.py:583 msgid "Save as..." msgstr "Сохранить как..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Сохранить копию..." #: thonny/code.py:603 msgid "Rename..." msgstr "Переименовать..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Параметры Thonny" #: thonny/running.py:94 msgid "Run current script" msgstr "Запустить текущий скрипт" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Запустить текущий скрипт в терминале" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Остановить и перезапустить бэкенд" #: thonny/running.py:139 msgid "Stop" msgstr "Остановить" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Прервать выполнение" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Послать EOF / программная перезагрузка" #: thonny/running.py:172 msgid "Disconnect" msgstr "Отключиться" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Известные интерпретаторы" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Ваш интерпретатор отсутствует в списке?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Найти другой" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "исполняемый модуль python" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "NB! Thonny поддерживает Python 3.5 и выше" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Создать новое виртуальное окружение" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Выберите существующий или создайте новый пустой каталог" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Интерпретаторы Python" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "все файлы" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Выбрать пустой каталог для нового виртуального окружения" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Неправильный каталог" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "Выбранный каталог не пустой.\n" "Выбрать другой или отменить." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Создать виртуальное окружение" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Очистить оболочку" #: thonny/shell.py:126 msgid "Plotter" msgstr "Плотер" #: thonny/shell.py:245 msgid "Clear" msgstr "Очистить" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Показать Плоттер" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "По причине производительности оболочка избегает отображения очень длинных строк целиком (смотрите Инструменты => Параметры => Оболочка).\n" "Здесь вы можете взаимодействовать с оригинальным фрагментом текста." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "Переносить строки (может замедлять работу)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Копировать в буффер" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Развернуть в оболочке" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Пропущенный текст (%d символов)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Плоттер показывает серии чисел, напечатанных в оболочке" #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Смотрите Помощь для подробностей" #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Закрыть остальные" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Копирование" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Копирование\n" " %s\n" "в\n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Отмена" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "ОК" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Отменить этот процесс?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Процесс всё ещё выполняется. Вы уверены, что хотите прервать его?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Выбрать Всё" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Оболочка" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Тот же интерпретатор, что и у Thonny (по умолчанию)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Это виртуальное окружение автоматически поддерживается Thonny" #: thonny/workbench.py:532 msgid "Location: " msgstr "Расположение: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Параметры..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Увеличить размер шрифта" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Изменить размер шрифта" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Приблизить" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Выйти из Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "Выйти" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "Перезаписать тему «%s»" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Параметры программы:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Обычный режим" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "Конфигурация была обновлена. Перезапустите Thonny для работы в обычном режиме.\n" "\n" "(Зайдите в «Инструменты → Параметры → Общие», если вы захотите изменить своё решение)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Дерево программы" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Выберите интерпретатор" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Продолжить" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Запустить / продолжить" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Отладить текущую программу" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Отладить" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Отладить текущую программу (лучше)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Отладить текущую программу (быстрее)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Перепрыгнуть" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "Через" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "Зайти" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "В" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Выйти" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "Из" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Шаг назад" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Назад" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Стек" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Исключение" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Записывать использование программы в журнал" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Режим отладки (предоставляет более подробную информацию)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "Режим пользовательского интерфейса (ПИ)" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "Коэффициент масштабирования ПИ" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "NB! Перезапустите Thonny после изменения этих параметров!" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Общие" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "УСТАНОВИТЬ" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Просмотр пакетов" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Вы можете только просматривать пакеты с этим интерпретатором.\n" "Используйте 'Инструменты → Открыть системную оболочку...' для установки, обновления и удаления." #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Каталог пакетов" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Установить с PyPI" #. мб не правильно... #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Если вы не знаете, где взять пакет, тогда, скорее всего, вам следует поискать в Python Package Index. Начните с ввода имени пакета в окне поиска выше и нажмите ENTER." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "для указания файла requirements.txt и установки перечисленных в нём пакетов" #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Клик" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "для указания и установки пакета из файла (обычно с расширением .whl, .tar.gz или .zip).\n" "" #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Обновить или удалить" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Начните с выбора пакета слева." #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Цель:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "виртуальное окружение" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "пакеты из пользовательского каталога" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "В этом окне перечислены все доступные пакеты, но доступны для обновления и удаления только пакеты из" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Новые пакеты также будут установлены в этот каталог. Для других целей каталоги необходимо настроить." #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Установленная версия:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Установлено в:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Проверьте правильность написания!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "Необходимо ввести" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Поиск этого пакета в PyPI не дал результатов." #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Код ошибки:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Имя пакета не найдено в списке:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Пакет «{}» необходим для установки и удаления других пакетов." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Пакет" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Управление пакетами для %s" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Подтверждение" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Похоже, вы хотите установить пакет, относящийся к Thonny. Если вы хотите установить плагин для Thonny, тогда используйте «Инструменты → Управление плагинами...»\n" "\n" "Вы уверены, что хотите установить %s для бэкенда?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "NB! Может быть доступной другая версия, совместимая с текущей версией Thonny. Щёлкните кнопку «...» чтобы выбрать версию для установки." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Плагины Thonny без зависимостей" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Похоже, вы хотите установить старую версию плагина для Thonny (в ней не указана версия Thonny).\n" "\n" "Если вы действительно этого хотите, тогда установите плагин из командной строки." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Неподходящие зависимости" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "Этот пакет требует другой версии Thonny:" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Если вы действительно этого хотите, тогда установите пакет из командной строки." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(В этом случае бэкенд Thonny будет использовать такой же интерпретатор, таким образом оба способа будут управлять одним и тем же набором пакетов.)" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "NB! Нужно перезапустить Thonny после установки, обновления или удаления плагина." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Плагины Thonny" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Продвинутая установка, обновление и откат" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Желаемая версия" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Зависимости для обновления" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Нужно:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Ошибка:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Управление пакетами..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Управление плагинами.." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "Открыть повтор..." #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Измените рабочий каталог для программы в Запуск / Отладка" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Показывать вызовы функций (фреймы) в разных окнах" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "Снимите отметку если вы хотите более традиционный стиль" #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "Автоматически открывать и закрывать окно стека" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "Открывает окно стека при первом вызове и закрывает его, когда программа возвращается во внешний блок." #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "Разрешить переход в библиотеки (т. е. в модули за пределами каталога программы)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Может замедлить отладчик." #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Предпочитаемый отладчик" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(используется при щелчке кнопки отладчика)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Порт Birdseye" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(перезапустите Thonny после этих изменений)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Запустить и отладить" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Эмуляция терминала" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "поддерживает основные ANSI-цвета и стили" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Максимальное число удерживаемых строк." #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "NB! Большие значения могут привести к ухудшению производительности!" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Максимальная длина строки, подлежащей сжатию" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Запуск текущей программы в терминале" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Перейти в Python REPL после завершения программы" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Оставлять окно терминала открытым после завершения программы" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "NB! Автоматическое закрытие должно быть включено в настройках терминала (Профили → Оболочка → При выходе из оболочки)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Терминал" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "Тема интерфейса" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Тема подсветки синтаксиса" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Шрифт редактора" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "Шрифт окна ввода-вывода" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Предпросмотр" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "Это комментарий" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "Ответ" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "незакрытая_строка" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "бла, бла" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "NB! Некоторые элементы оформления изменятся только после перезапуска Thonny!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Введите число" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Тема & шрифт" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Открыть каталог Thonny..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Открыть каталог данных Thonny..." #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Дом" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Содержание справки" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "Устройство CircuitPython" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "Устройство MicroPython" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Подключите устройство к компьютеру и выберите соответствующий порт ниже" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "найдите имя вашего устройства, «USB Serial» или «UART»" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Если вы не можете найти его, попробуйте сначала установить соответствующий драйвер USB." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Порт" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Попытаться обнаружить порт автоматически" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython (общий)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Распечатать..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Открыть системную оболочку..." #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Подробности" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Установить из файла requirements.txt" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Установить из локального файла" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "Это окно для управления плагинами и зависимостями Thonny.\n" "Если вы хотите установить пакеты для ваших программ, тогда перейдите в «Инструменты → Управление пакетами...»" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (общий)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Увеличить отступ выбранных строк" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Уменьшить отступ выбранных строк" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Переключиться в обычный режим" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "Убедитесь, что MicroPython установлен на ваш micro:bit." #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "Не забудьте, что main.py работает без встроенного main-script." #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "Установить последний MicroPython на BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "Расположение micro:bit:" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Версия к установке:" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "пожалуйста подождите" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "NB! Все файлы на micro:bit будут удалены!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Установка..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Готово!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Теперь можно закрыть это окно." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Прошивка" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "Открыть окно для установки или обновления MicroPython на вашем устройстве" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "Не удалось найти диск «%s»" #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "Убедитесь, что ваш micro:bit подключён!" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Хотите ли вы продолжить и выбрать диск вручную?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "Не удалось найти диск «%s». Хотите выбрать его вручную?" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Найдено несколько «%s» дисков. Хотите выбрать один из них?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Не удалось найти подходящий диск" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d элементов" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Переместить в Корзину" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Перенести в Мусор" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Удалить" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Новый каталог" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Свойства" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Место в хранилище" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "Путь" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Свойства каталога" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Свойства файла" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "байт" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "Размер" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Изменен" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "Удаление %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Перемещение %s в %s" #: thonny/code.py:203 msgid "Loading" msgstr "Загрузка" #: thonny/code.py:297 msgid "Saving" msgstr "Сохранение" #: thonny/running.py:1408 msgid "Working..." msgstr "Обработка..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Выгрузка %s в %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Выгрузить в %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "Загрузка %s в %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Загрузить в %s" thonny-3.2.7/thonny/locale/es_ES/0000755000175000017500000000000013611777205017641 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/es_ES/LC_MESSAGES/0000755000175000017500000000000013611777205021426 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/es_ES/LC_MESSAGES/thonny.mo0000644000175000017500000003231613611773167023312 0ustar annamaaannamaa00000000000000  *  + -9!g7&  x &+18 > H U ans{%*$3Dx ! )I [iot   &,1@W] f s 061J`z   '=LQY hzs  & :HX \ jv|?C ' /:HB $- ? JTey~ B & & 2 @M] fpw {      $7INS hv~>0!!  @*9 ?I NX[cx 2 D DOn   % &B@7 *x 5 * !! !"!9!!!7!$"-"D"["u"""" " "" """"#"-#1L#~#####G#$'7$_$ h$t$$$'$,$ $ %(%G%V%_%e%t%%%!%%%%% %%%&&%&=& F&P&g& &&&&&&&&H'X'=^''%''#'(0(9(#T(x(( (( ( (((()) ))) 8)E))&) **#*5*F*L*]*n*t*w*J*T*,+ 5+A+H+Y+Ha++++0+",8,?, S,a, q,}, ,,,,,,,[ -e- m-w-8- ----.. #.-.6.?.R.f.%..... .. //-/@/[/c/k/// //B/3/)20\0c1s1?92y22 222 22 22 3 #3.39?3 y333K3 3344494L4U4[4u4{44,4%d itemsA special virtual environment (deprecated)About BirdseyeAbout ThonnyAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAlternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBack to current frameBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?BugtrackerCan't close yetCan't find package name from the list:CancelCancel the process?Case sensitiveChange font sizeCircuitPython (generic)ClickClick CloseClose allClose othersComment outConfirmationCopyCopyingCopying %s to %sCould not find disk '%s'.Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCutDebugDebug current script (birdseye)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDeleteDeleting %sDesired versionDetailsDirectory propertiesDisable notification soundDisabled checks (one id per line)DisconnectDo you want to overwrite '%s' ?Dock user windowsDocumentationDone!DownDownload to %sDownloading %s to %sEditEditorEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExport usage logs...FileFile propertiesFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus shellFont scaling modeFull screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomepageINSTALLIncrease font sizeIndent selected linesInstallInstall from PyPIInstalled to:Installed version:Installing ...InterpreterInterrupt executionLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMaximize viewMaximum number of lines to keep.ModifiedMove to Recycle BinMove to TrashMoving %s to %sNewNew directoryNext objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen...Options...OutlineOverwrite?PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePerform MyPy checksPerform selected Pylint checksPlease check your spelling!PortPreferred debuggerPreviewPrevious objectPrint...Program argumentsPropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect interpreterShow line numbersSizeStopStop/Restart backendStorage spaceSummaryTarget:TerminalThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!This box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsToggle commentToolsUncommentUndoUninstallUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyViewWhich interpreter or device should Thonny use for running your code?Working...You can now close this dialog.You need to select a file!Zoomall filesblah, blahbytesexact package namehereplease waitpython executablesupports basic ANSI-colors and stylesMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: es %d ítemesUn entorno virtual especial (obsoleto)Sobre BirdseyeAcerca de ThonnyPermitir el completado de código con la tecla "Tab" en la ConsolaPermitir el completado de código con la tecla "Tab" en editoresPermitir solamente una instancia de ThonnyIntérprete de Python 3 alternativo o entorno virtual¿Está seguro de que desea desinstalarlo?AsistenteAutorAutocompletarVolver al marco actualBirdseye es un depurador de Python que debe instalarse por separado. ¿Desea abrir la página de ayuda y obtener más información?Rastreador de erroresAún no se puede cerrarNo se pudo encontrar el nombre del paquete en la lista:Cancelar¿Cancelar el proceso?Sensible a mayúsculasCambiar tamaño de fuenteCircuitPython (genérico)ClickClic CerrarCerrar todosCerrar otrosComentarConfirmaciónCopiarCopiandoCopiando %s a %sNo se pudo encontrar el disco '%s'.No se ha podido encontrar el paquete en PyPI.No se encontró información del paquete en PyPI.Crear un nuevo entorno virtualCortarDepurarDepurar el script actual (birdseye)Modo de depuración (provee un diagnóstico detallado de los registros)Disminuir tamaño de la fuenteDes-indentar las líneas seleccionadas.EliminarBorrando %sVersión deseadaDetallesPropiedades del directorioDesactivar los sonidos de notificaciónDesactivar comprobaciones (un id por línea)Desconectar¿Quieres sobreescribir '%s'?Anclar las ventanas de usuarioDocumentación¡Listo!AbajoDescargar a %sDescargando %s a %sEditarEditorIntroducir la cadena a sustituir.ErrorCódigo de error:Error:EventosExcepciónSalirSalir de ThonnyExportar registros de uso...ArchivoPropiedades del archivoArchivosEncontrarEncontrar y reemplazarEncontrar un paquete en PyPIEncontrar:FirmwareCambiar foco al editorCambiar foco al terminalModo de escalado de fuentePantalla completaGeneralMontículo (heap)Modo heap (montículo) activado. Seleccione "Vista heap" para cerrarlo. AyudaResaltar la línea actual (requiere abrir de nuevo el editor)Resaltar las variables localesResaltar las coincidencias de nombresResaltar los paréntesisResaltar los elementos sintácticosPágina principalINSTALARAumentar tamaño de fuenteIndentar las líneas seleccionadas.InstalarInstalar desde PyPIInstalado en:Versión instalada:Instalando...IntérpreteInterrumpir ejecuciónIdiomaÚltima versión estableÚltima versiónCargarCargandoLocalizar otroUbicación: Hecho en la Universidad de Tartu, Estonia, con la ayuda de la comunidad de código abierto, la Raspberry Pi Foundation y Cybernetica ASMaximizar vistaNúmero máximo de líneas a mantener.ModificadoMover a la papeleraMover al basureroMoviendo %s a %sNuevoNuevo DirectorioObjeto siguienteNotasOkInspector de objetosAbrir el asistente automáticamente cuando haya advertencias en tu códigoAbrir el asistente automáticamente cuando el programa se cuelgue con una excepciónAbrir...Opciones...Boceto¿Sobreescribir?PaqueteEl paquete '{}' es requerido para instalar y desinstalar otros paquetes.Directorio de paquetesPegarRealizar comprobaciones MyPyRealizar las comprobaciones Pylint seleccionadas¡Por favor revisa tu ortografía!PuertoDepurador preferidoPrevisualizarObjeto anteriorImprimir...Argumentos del programaPropiedadesPágina de PyPIModo Pygame ZeroIntérpretes de PythonSalir¿Desea desinstalarlo?Archivos recientesLongitud de línea máxima recomendada (establecer a 0 para desactivar el margen de línea)RehacerRefrescarCambiar nombre...Volver a abrir todos los archivos de la sesión anteriorReemplazarReemplazar todoReemplazar por:Reemplazar+EncontrarInformar de un problemaRequiereRequiere:ReanudarEjecutarEjecutar y DepurarEjecutar / reanudarEjecutar el script actualEjecutar el script actual en terminalEjecutar hasta el cursorGuardarGuardar como...Guardar copia...GuardandoVea Ayuda para detalles.Seleccionar todoSeleccionar todoElegir intérpreteMostrar números de líneaTamañoDetenerDetener/Reiniciar back-endEspacio de almacenamientoResumenObjetivo:TerminalAún está en ejecución el proceso. ¿Realmente quieres cancelar?El mismo intérprete que corre Thonny (por defecto)No se ha encontrado el texto especificadoEsta casilla es para sus notas de trabajo -- instrucciones de asignación, fragmentos de código, o similares. Todo se guardará automáticamente y se cargará cuando abra Thonny la próxima vez. Sírvase borrar este texto para hacer sitio a sus propias notas.Este computadorEste programa viene completamente sin garantía. Es software libre, por lo que puede redistribuirse bajo unas determinadas condiciones: véase https://opensource.org/licenses/MIT para más detallesEste ambiente virtual es mantenido automáticamente por Thonny.Opciones de ThonnyActivar/desactivar comentarioHerramientasRetirar comentarioDeshacerDesinstalarArribaActualizadoActualizar dependenciasActualizar o desinstalarSubir a %sSubiendo %s a %sUtiliza la orden "Parar" si desea cancelar la depuraciónVariablesHistorial de versionesVer¿Qué intérprete o dispositivo debe usar Thonny para ejecutar tu código?TrabajandoYa puede cerrar este diálogo.¡Debes seleccionar un archivo!Zoomtodos los archivosbla, blabytesnombre exacto del paqueteaquípor favor espereEjecutable de Pythonsoporte para colores y estilos básicos ANSIthonny-3.2.7/thonny/locale/es_ES/LC_MESSAGES/thonny.po0000644000175000017500000010430113611773167023307 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: es\n" #: thonny/workbench.py:355 msgid "File" msgstr "Archivo" #: thonny/workbench.py:356 msgid "Edit" msgstr "Editar" #: thonny/workbench.py:357 msgid "View" msgstr "Ver" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Ejecutar" #: thonny/workbench.py:360 msgid "Tools" msgstr "Herramientas" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Ayuda" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Intérprete de Python 3 alternativo o entorno virtual" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Un entorno virtual especial (obsoleto)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Salir" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Disminuir tamaño de la fuente" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Cambiar foco al editor" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Cambiar foco al terminal" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Maximizar vista" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Pantalla completa" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Argumentos del programa" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "Acerca de Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Hecho en la Universidad de Tartu, Estonia, con la ayuda de la comunidad de código abierto, la Raspberry Pi Foundation y Cybernetica AS" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Este programa viene completamente sin garantía. Es software libre, por lo que puede redistribuirse bajo unas determinadas condiciones: véase https://opensource.org/licenses/MIT para más detalles" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Historial de versiones" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Informar de un problema" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Abrir el asistente automáticamente cuando el programa se cuelgue con una excepción" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Abrir el asistente automáticamente cuando haya advertencias en tu código" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Realizar las comprobaciones Pylint seleccionadas" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Realizar comprobaciones MyPy" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Desactivar comprobaciones (un id por línea)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Asistente" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Autocompletar" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "¿Qué intérprete o dispositivo debe usar Thonny para ejecutar tu código?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Intérprete" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "Sobre Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye es un depurador de Python que debe instalarse por separado.\n" "\n" "¿Desea abrir la página de ayuda y obtener más información?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Depurar el script actual (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Activar/desactivar comentario" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Comentar" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Retirar comentario" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Deshacer" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Rehacer" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Cortar" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Copiar" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Pegar" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Seleccionar todo" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Ejecutar hasta el cursor" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Aún no se puede cerrar" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Utiliza la orden \"Parar\" si desea cancelar la depuración" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Anclar las ventanas de usuario" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Resaltar las coincidencias de nombres" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Resaltar las variables locales" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Resaltar los paréntesis" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Resaltar los elementos sintácticos" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Resaltar la línea actual (requiere abrir de nuevo el editor)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Permitir el completado de código con la tecla \"Tab\" en editores" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Permitir el completado de código con la tecla \"Tab\" en la Consola" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Mostrar números de línea" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Longitud de línea máxima recomendada (establecer a 0 para desactivar el margen de línea)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Editor" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Exportar registros de uso..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Eventos" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Archivos" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Encontrar y reemplazar" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Encontrar:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Reemplazar por:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Sensible a mayúsculas" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Arriba" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Abajo" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Encontrar" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Reemplazar" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Reemplazar+Encontrar" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Reemplazar todo" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Introducir la cadena a sustituir." #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "No se ha encontrado el texto especificado" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Permitir solamente una instancia de Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Volver a abrir todos los archivos de la sesión anterior" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Desactivar los sonidos de notificación" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Modo de escalado de fuente" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Modo heap (montículo) activado. Seleccione \"Vista heap\" para cerrarlo.\n" "" #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Montículo (heap)" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Idioma" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Esta casilla es para sus notas de trabajo -- instrucciones de asignación, fragmentos de código, o similares.\n" "\n" "Todo se guardará automáticamente y se cargará cuando abra Thonny la próxima vez.\n" "\n" "Sírvase borrar este texto para hacer sitio a sus propias notas." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Notas" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Objeto anterior" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Objeto siguiente" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Inspector de objetos" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "Boceto" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Modo Pygame Zero" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Encontrar un paquete en PyPI" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Desinstalar" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Cerrar" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Clic " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "aquí" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Actualizado" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Instalar" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "No se ha podido encontrar el paquete en PyPI." #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "nombre exacto del paquete" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Última versión estable" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Última versión" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Resumen" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Autor" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Página principal" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Rastreador de errores" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Documentación" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "Página de PyPI" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Requiere" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "¿Desea desinstalarlo?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "¿Está seguro de que desea desinstalarlo?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Volver al marco actual" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Variables" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Este computador" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Refrescar" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Error" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "¡Debes seleccionar un archivo!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "¿Sobreescribir?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "¿Quieres sobreescribir '%s'?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Nuevo" #: thonny/code.py:526 msgid "Open..." msgstr "Abrir..." #: thonny/code.py:528 msgid "Load" msgstr "Cargar" #: thonny/code.py:537 msgid "Recent files" msgstr "Archivos recientes" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Cerrar todos" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Guardar" #: thonny/code.py:583 msgid "Save as..." msgstr "Guardar como..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Guardar copia..." #: thonny/code.py:603 msgid "Rename..." msgstr "Cambiar nombre..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Opciones de Thonny" #: thonny/running.py:94 msgid "Run current script" msgstr "Ejecutar el script actual" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Ejecutar el script actual en terminal" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Detener/Reiniciar back-end" #: thonny/running.py:139 msgid "Stop" msgstr "Detener" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Interrumpir ejecución" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "" #: thonny/running.py:172 msgid "Disconnect" msgstr "Desconectar" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Localizar otro" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "Ejecutable de Python" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Crear un nuevo entorno virtual" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Intérpretes de Python" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "todos los archivos" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "" #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "" #: thonny/shell.py:72 msgid "Clear shell" msgstr "" #: thonny/shell.py:126 msgid "Plotter" msgstr "" #: thonny/shell.py:245 msgid "Clear" msgstr "" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "" #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "" #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Vea Ayuda para detalles." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Cerrar otros" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Copiando" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Copiando\n" " %s\n" "a\n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Cancelar" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "Ok" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "¿Cancelar el proceso?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Aún está en ejecución el proceso.\n" "¿Realmente quieres cancelar?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Seleccionar todo" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "El mismo intérprete que corre Thonny (por defecto)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Este ambiente virtual es mantenido automáticamente por Thonny." #: thonny/workbench.py:532 msgid "Location: " msgstr "Ubicación: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Opciones..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Aumentar tamaño de fuente" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Cambiar tamaño de fuente" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Zoom" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Salir de Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "Salir" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Elegir intérprete" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Reanudar" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Ejecutar / reanudar" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Depurar" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Excepción" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Modo de depuración (provee un diagnóstico detallado de los registros)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "General" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "INSTALAR" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "" #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Directorio de paquetes" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Instalar desde PyPI" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "" #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "" #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Click" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "" #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Actualizar o desinstalar" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "" #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Objetivo:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "" #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Versión instalada:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Instalado en:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "¡Por favor revisa tu ortografía!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "No se encontró información del paquete en PyPI." #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Código de error:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "No se pudo encontrar el nombre del paquete en la lista:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "El paquete '{}' es requerido para instalar y desinstalar otros paquetes." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Paquete" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Confirmación" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "" #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "" #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "" #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "" #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Versión deseada" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Actualizar dependencias" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Requiere:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Error:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "" #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "" #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "" #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "" #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "" #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "" #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Depurador preferido" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Ejecutar y Depurar" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "soporte para colores y estilos básicos ANSI" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Número máximo de líneas a mantener." #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Terminal" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Previsualizar" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "bla, bla" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "" #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "" #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "" #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Puerto" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Imprimir..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "" #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Detalles" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (genérico)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Indentar las líneas seleccionadas." #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Des-indentar las líneas seleccionadas." #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "" #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "" #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "por favor espere" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Instalando..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "¡Listo!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Ya puede cerrar este diálogo." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Firmware" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "No se pudo encontrar el disco '%s'." #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d ítemes" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Mover a la papelera" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Mover al basurero" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Eliminar" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Nuevo Directorio" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Propiedades" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Espacio de almacenamiento" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Propiedades del directorio" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Propiedades del archivo" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "bytes" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "Tamaño" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Modificado" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "Borrando %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Moviendo %s a %s" #: thonny/code.py:203 msgid "Loading" msgstr "Cargando" #: thonny/code.py:297 msgid "Saving" msgstr "Guardando" #: thonny/running.py:1408 msgid "Working..." msgstr "Trabajando" #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Subiendo %s a %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Subir a %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "Descargando %s a %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Descargar a %s" thonny-3.2.7/thonny/locale/ja_JP/0000755000175000017500000000000013611777205017626 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/ja_JP/LC_MESSAGES/0000755000175000017500000000000013611777205021413 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/ja_JP/LC_MESSAGES/thonny.mo0000644000175000017500000003275413611773167023305 0ustar annamaaannamaa00000000000000  * %> d n Y  p *c  + - ! 7& ^ &   * x@  '     $ %) 7O   (    ! + =KPU\y    0C6H   >JSizx O Q]c?tC/N^ pzB&    .;KTXav  / !#cx2A GQ V`ck2 D;$ #s~'Cibsu$(Mb<u?18$]0 L _ f  _ !!C-!q!! !! !=!P! H"8U"B"" "*"7"#-Z#### ## ##$# $ $"$)$9$Y$a$$$$ $g$ =%BG%!%!%%%&&''02'c'1''I'(.(5( H(R( )]!)))$)K)]*n*$* ****+ +)+0>+Do+ +3+++ ,,-,=,D,K,[,<w,, ,,6, '-1-09-<j-.3_/0 00 000091FI1111o1$2K3!k333-34"5 5 Please check your spelling! You need to enter (probably needs admin privileges). Upgrade and running it with to locate and install the package file (usually with .whl, .tar.gz or .zip extension). (Increase font size. New packages will be also installed into this directory. Other locations must be managed by alternative means.A special virtual environment (deprecated)About BirdseyeAbout ThonnyAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAlternative Python 3 interpreter or virtual environmentAlternatively, if you have an older pip installed, then you can install packages on the command line (Tools → Open system shell...)Are you sure you want to uninstall it?AssistantAuthorAuto-completeBack to current frameBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?BugtrackerCan't close yetCan't find package name from the list: Case sensitiveClick CloseComment outCopyCould not find the package from PyPI.Could not find the package info from PyPI. Error code: CutDebug current script (birdseye)Debug mode (provides more detailed logs)Decrease font sizeDeviceDisable notification soundDisabled checks (one id per line)Dock user windowsDocumentationDownEditEditorEnter string to be replaced.EventsExitExport usage logs...FileFilesFindFind & ReplaceFind package from PyPIFind:Focus editorFocus shellFont scaling modeFull screenHeapHeap mode is on. Close Heap view to turn it off.HelpHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomepageIf you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER. InstallInstall from PyPI Install from local file Installed to: Installed version: Installing pip Installing pip, please wait ... InterpreterLanguageLatest stable versionLatest versionMade in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMaximize viewNB! Restart Thonny after changing these options in order to see the full effectNext objectNotesObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOutlinePackages' directory PastePerform MyPy checksPerform selected Pylint checksPrevious objectProgram argumentsPyPI pagePygame Zero modeReally uninstall?Recommended maximum line length (Set to 0 to turn off margin line)RedoReopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRunRun cellRun cell and advanceRun selection or current lineRun to cursorSelect allShow line numbersStart by selecting the package from the left. SummaryTarget: The specified text was not found!This box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This dialog lists all available packages, but allows upgrading and uninstalling only packages from This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsToggle commentToolsUncommentUndoUninstallUpUpgradeUpgrade or uninstall Use "Stop" command if you want to cancel debuggingVariablesVersion historyViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling. You must restart Thonny for language change to take effect.You seem to have problems with pip exact package nameherepip, a required module for managing packages is missing or too old for Thonny. If your system package manager doesn't provide recent pip (9.0.0 or later), then you can install newest version by downloading pip, a required module for managing packages is missing or too old. Downloading pip installer (about 1.5 MB), please wait ... user site packages virtual environment Project-Id-Version: Thonny Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2019-08-24 13:36+0300 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: ja Language-Team: ja Plural-Forms: nplurals=1; plural=0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.7.0 スペルを確認してください。正しいパッケージ名をを実行することでインストールできます(おそらく管理者権限が必要です)。アップグレードからダウンロードしてをクリックしてパッケージファイル(拡張子が.whl, .tar.gz, .zipのもの)をインストール文字を大きくする新しいパッケージもこのディレクトリにインストールされます。これ以外の場所は別の方法で管理してください。特別な仮想環境(非推奨)BirdseyeについてThonnyについてシェル内でタブキーによるコード補完をするエディタ内でタブキーによるコード補完をするThonnyが1つしか起動しないようにする代替のPython 3インタプリタまたは仮想環境もしくは、古いpipがインストールされていればコマンドライン(ツール→システムシェルを開く...)でパッケージをインストールできます。本当にアンインストールしますか?アシスタント作者オートコンプリート現在のフレームへ戻るBirdseyeはPythonデバッガであり、別にインストールする必要があります。バグの追跡まだ閉じられません一覧からパッケージ名を見つけられませんでした:大文字小文字の区別 閉じるコメントアウトコピーPyPIでパッケージを見つけられませんでした。PyPIでパッケージを見つけられませんでした。エラーコード:切り取りBirdseyeで現在のスクリプトをデバッグするデバッグモード(より詳細なログを出力します)文字を小さくするデバイス通知音を鳴らさないようにする無効にするチェック項目(1行に1つのid)ユーザーウインドウをドッキングドキュメント下へ編集エディタ置換される文字列イベント終了使用履歴をエクスポート...ファイルファイル検索検索と置換PyPIでパッケージを検索検索:エディタにフォーカスシェルにフォーカス文字の拡大縮小モード全画面表示ヒープヒープモードがオンです。 オフにするにはヒープビューを閉じてください。ヘルプ現在の行を強調表示(エディタの再起動が必要)ローカル変数を強調表示対応する名前を強調表示カッコを強調表示文法要素を強調表示ホームページどこからパッケージを取得すればいいかわからない場合はPython Package Indexで探すと良いでしょう。パッケージの名前を上にある検索ボックスに入力し、ENTERを押してください。インストールPyPIからインストールローカルファイルからインストールインストールする場所:インストールされているバージョン:Pipをインストール中pipをインストールしています。少々お待ちください ...インタプリタ言語最新の安定版最新版このアプリケーションは オープンソースコミュニティの Cybernetica ASと Raspberry Pi財団の助けを得て エストニアのタルトゥ大学で 作られています。最大化注意:これらの設定を反映させるためにはThonnyの再起動が必要です。次のオブジェクトメモオブジェクトインスペクタコードに警告がある場合にアシスタントを自動的に開くプログラムが例外を送出して停止したら自動的にアシスタントを開くアウトラインパッケージのディレクトリ貼り付けMypyでチェックするPylintでチェックする前のオブジェクトプログラムの引数PyPIページPygame Zeroモード本当にアンインストールしますか?1行の推奨最大文字数(0でガイドラインを非表示)やり直す前回開いていたファイルをすべて開く置換すべて置換置換:置換して次を検索問題を報告必須実行セルを実行セルを実行して次へ選択範囲または現在選択されている行を実行カーソル位置まで実行全て選択行数を表示左からパッケージを選択してください。まとめ対象:指定された文字列が見つかりませんここにはメモをとることができます。例えば、やることリスト・コードスニペットなど、なんでも書き込めます。 すべてのメモは自動で保存され、次にThonnyを起動した時に読み込まれます。 この文章は消してしまっても大丈夫です。このダイアログではすべてのパッケージを表示していますが、アップグレードとアンインストールができるのは次のパッケージのみですこのプログラムの使用によって起きた いかなる事象に対しても一切の保証はありません。 このプログラムはフリーソフトウェアであり、 https://opensource.org/licenses/MIT に記載された条件のもとで 自由に再配布することが出来ます。コメントの切り替えツールコメント解除元に戻すアンインストール上へアップグレードアップグレードもしくはアンインストールデバッグをキャンセルするためにStopコマンドを使う変数バージョン履歴表示Thonnyはコードの実行にどのインタプリタまたはデバイスを使用すればよいですか?現在のインタプリタではこれらのパッケージのみ閲覧できます。 インストール・アップグレード・アンインストールするには「ツール→システムシェルを開く...」を使用してください。言語の変更を反映するにはThonnyを再起動してください。pipに問題があるようです入力してくださいここパッケージの管理に必要なモジュールpipが見つからないか、Thonnyで使うにはバージョンが古すぎます。 もしシステムのパッケージマネージャが新しいバージョンのpip(9.0.0以上)を提供していない場合は最新のバージョンをパッケージの管理に必要なモジュールpipが見つからないか、バージョンが古すぎます。 pipインストーラ(約1.5MB)をダウンロードしています。少々お待ちください ...ユーザーのsiteパッケージ仮想環境thonny-3.2.7/thonny/locale/ja_JP/LC_MESSAGES/thonny.po0000644000175000017500000004560313611773167023305 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: ja\n" #: thonny/workbench.py:338 msgid "File" msgstr "ファイル" #: thonny/workbench.py:339 msgid "Edit" msgstr "編集" #: thonny/workbench.py:340 msgid "View" msgstr "表示" #: thonny/workbench.py:341 msgid "Run" msgstr "実行" #: thonny/workbench.py:342 msgid "Device" msgstr "デバイス" #: thonny/workbench.py:343 msgid "Tools" msgstr "ツール" #: thonny/workbench.py:344 msgid "Help" msgstr "ヘルプ" #: thonny/workbench.py:478 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "代替のPython 3インタプリタまたは仮想環境" #: thonny/workbench.py:486 msgid "A special virtual environment (deprecated)" msgstr "特別な仮想環境(非推奨)" #: thonny/workbench.py:523 msgid "Exit" msgstr "終了" #: thonny/workbench.py:540 msgid "(Increase font size" msgstr "文字を大きくする" #: thonny/workbench.py:550 msgid "Decrease font size" msgstr "文字を小さくする" #: thonny/workbench.py:562 msgid "Focus editor" msgstr "エディタにフォーカス" #: thonny/workbench.py:571 msgid "Focus shell" msgstr "シェルにフォーカス" #: thonny/workbench.py:582 msgid "Maximize view" msgstr "最大化" #: thonny/workbench.py:594 msgid "Full screen" msgstr "全画面表示" #: thonny/workbench.py:1195 msgid "Program arguments" msgstr "プログラムの引数" #: thonny/plugins/about.py:24 thonny/plugins/about.py:160 msgid "About Thonny" msgstr "Thonnyについて" #: thonny/plugins/about.py:80 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "このアプリケーションは\n" "オープンソースコミュニティの\n" "Cybernetica ASと\n" "Raspberry Pi財団の助けを得て\n" "エストニアのタルトゥ大学で\n" "作られています。" #: thonny/plugins/about.py:106 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "このプログラムの使用によって起きた\n" "いかなる事象に対しても一切の保証はありません。\n" "このプログラムはフリーソフトウェアであり、\n" "https://opensource.org/licenses/MIT\n" "に記載された条件のもとで\n" "自由に再配布することが出来ます。" #: thonny/plugins/about.py:149 msgid "Version history" msgstr "バージョン履歴" #: thonny/plugins/about.py:156 msgid "Report problems" msgstr "問題を報告" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "プログラムが例外を送出して停止したら自動的にアシスタントを開く" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "コードに警告がある場合にアシスタントを自動的に開く" #: thonny/plugins/assistant_config_page.py:28 msgid "Perform selected Pylint checks" msgstr "Pylintでチェックする" #: thonny/plugins/assistant_config_page.py:35 msgid "Perform MyPy checks" msgstr "Mypyでチェックする" #: thonny/plugins/assistant_config_page.py:40 msgid "Disabled checks (one id per line)" msgstr "無効にするチェック項目(1行に1つのid)" #: thonny/plugins/assistant_config_page.py:80 msgid "Assistant" msgstr "アシスタント" #: thonny/plugins/autocomplete.py:329 msgid "Auto-complete" msgstr "オートコンプリート" #: thonny/plugins/backend_config_page.py:44 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Thonnyはコードの実行にどのインタプリタまたはデバイスを使用すればよいですか?" #: thonny/plugins/backend_config_page.py:128 msgid "Interpreter" msgstr "インタプリタ" #: thonny/plugins/birdseye_frontend.py:30 msgid "About Birdseye" msgstr "Birdseyeについて" #: thonny/plugins/birdseye_frontend.py:31 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "BirdseyeはPythonデバッガであり、別にインストールする必要があります。" #: thonny/plugins/birdseye_frontend.py:55 msgid "Debug current script (birdseye)" msgstr "Birdseyeで現在のスクリプトをデバッグする" #: thonny/plugins/cells.py:182 msgid "Run cell" msgstr "セルを実行" #: thonny/plugins/cells.py:192 msgid "Run cell and advance" msgstr "セルを実行して次へ" #: thonny/plugins/cells.py:202 msgid "Run selection or current line" msgstr "選択範囲または現在選択されている行を実行" #: thonny/plugins/commenting.py:113 msgid "Toggle comment" msgstr "コメントの切り替え" #: thonny/plugins/commenting.py:123 msgid "Comment out" msgstr "コメントアウト" #: thonny/plugins/commenting.py:133 msgid "Uncomment" msgstr "コメント解除" #: thonny/plugins/common_editing_commands.py:32 msgid "Undo" msgstr "元に戻す" #: thonny/plugins/common_editing_commands.py:44 msgid "Redo" msgstr "やり直す" #: thonny/plugins/common_editing_commands.py:60 msgid "Cut" msgstr "切り取り" #: thonny/plugins/common_editing_commands.py:72 msgid "Copy" msgstr "コピー" #: thonny/plugins/common_editing_commands.py:84 msgid "Paste" msgstr "貼り付け" #: thonny/plugins/common_editing_commands.py:96 thonny/plugins/debugger.py:123 msgid "Select all" msgstr "全て選択" #: thonny/plugins/debugger.py:114 msgid "Run to cursor" msgstr "カーソル位置まで実行" #: thonny/plugins/debugger.py:831 msgid "Can't close yet" msgstr "まだ閉じられません" #: thonny/plugins/debugger.py:832 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "デバッグをキャンセルするためにStopコマンドを使う" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "ユーザーウインドウをドッキング" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "対応する名前を強調表示" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "ローカル変数を強調表示" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "カッコを強調表示" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "文法要素を強調表示" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "現在の行を強調表示(エディタの再起動が必要)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "エディタ内でタブキーによるコード補完をする" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "シェル内でタブキーによるコード補完をする" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "行数を表示" #: thonny/plugins/editor_config_page.py:50 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "1行の推奨最大文字数(0でガイドラインを非表示)" #: thonny/plugins/editor_config_page.py:71 msgid "Editor" msgstr "エディタ" #: thonny/plugins/event_logging.py:24 msgid "Export usage logs..." msgstr "使用履歴をエクスポート..." #: thonny/plugins/event_view.py:41 msgid "Events" msgstr "イベント" #: thonny/plugins/files.py:113 msgid "Files" msgstr "ファイル" #: thonny/plugins/find_replace.py:60 thonny/plugins/find_replace.py:422 msgid "Find & Replace" msgstr "検索と置換" #: thonny/plugins/find_replace.py:66 msgid "Find:" msgstr "検索:" #: thonny/plugins/find_replace.py:81 msgid "Replace with:" msgstr "置換:" #: thonny/plugins/find_replace.py:99 msgid "Case sensitive" msgstr "大文字小文字の区別" #: thonny/plugins/find_replace.py:106 msgid "Up" msgstr "上へ" #: thonny/plugins/find_replace.py:110 msgid "Down" msgstr "下へ" #: thonny/plugins/find_replace.py:117 msgid "Find" msgstr "検索" #: thonny/plugins/find_replace.py:126 msgid "Replace" msgstr "置換" #: thonny/plugins/find_replace.py:133 msgid "Replace+Find" msgstr "置換して次を検索" #: thonny/plugins/find_replace.py:142 msgid "Replace all" msgstr "すべて置換" #: thonny/plugins/find_replace.py:236 msgid "Enter string to be replaced." msgstr "置換される文字列" #: thonny/plugins/find_replace.py:324 msgid "The specified text was not found!" msgstr "指定された文字列が見つかりません" #: thonny/plugins/general_config_page.py:14 msgid "Allow only single Thonny instance" msgstr "Thonnyが1つしか起動しないようにする" #: thonny/plugins/general_config_page.py:20 msgid "Debug mode (provides more detailed logs)" msgstr "デバッグモード(より詳細なログを出力します)" #: thonny/plugins/general_config_page.py:26 msgid "Reopen all files from previous session" msgstr "前回開いていたファイルをすべて開く" #: thonny/plugins/general_config_page.py:32 msgid "Disable notification sound" msgstr "通知音を鳴らさないようにする" #: thonny/plugins/general_config_page.py:65 msgid "Font scaling mode" msgstr "文字の拡大縮小モード" #: thonny/plugins/general_config_page.py:83 msgid "NB! Restart Thonny after changing these options\n" "in order to see the full effect" msgstr "注意:これらの設定を反映させるためにはThonnyの再起動が必要です。" #: thonny/plugins/heap.py:39 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "ヒープモードがオンです。\n" "オフにするにはヒープビューを閉じてください。" #: thonny/plugins/heap.py:89 msgid "Heap" msgstr "ヒープ" #: thonny/plugins/language.py:13 thonny/plugins/language.py:39 msgid "Language" msgstr "言語" #: thonny/plugins/language.py:30 msgid "You must restart Thonny for language change to take effect." msgstr "言語の変更を反映するにはThonnyを再起動してください。" #: thonny/plugins/notes.py:32 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "ここにはメモをとることができます。例えば、やることリスト・コードスニペットなど、なんでも書き込めます。\n" "\n" "すべてのメモは自動で保存され、次にThonnyを起動した時に読み込まれます。\n" "\n" "この文章は消してしまっても大丈夫です。" #: thonny/plugins/notes.py:57 msgid "Notes" msgstr "メモ" #: thonny/plugins/object_inspector.py:110 msgid "Previous object" msgstr "前のオブジェクト" #: thonny/plugins/object_inspector.py:113 msgid "Next object" msgstr "次のオブジェクト" #: thonny/plugins/object_inspector.py:614 msgid "Object inspector" msgstr "オブジェクトインスペクタ" #: thonny/plugins/outline.py:154 msgid "Outline" msgstr "アウトライン" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Pygame Zeroモード" #: thonny/plugins/pip_gui.py:83 msgid "Find package from PyPI" msgstr "PyPIでパッケージを検索" #: thonny/plugins/pip_gui.py:184 msgid " Upgrade " msgstr "アップグレード" #: thonny/plugins/pip_gui.py:191 msgid "Uninstall" msgstr "アンインストール" #: thonny/plugins/pip_gui.py:206 msgid "Close" msgstr "閉じる" #: thonny/plugins/pip_gui.py:244 msgid "Installing pip\n" "\n" "" msgstr "Pipをインストール中" #: thonny/plugins/pip_gui.py:247 msgid "pip, a required module for managing packages is missing or too old.\n" "\n" "Downloading pip installer (about 1.5 MB), please wait ...\n" "" msgstr "パッケージの管理に必要なモジュールpipが見つからないか、バージョンが古すぎます。\n" "\n" "pipインストーラ(約1.5MB)をダウンロードしています。少々お待ちください ..." #: thonny/plugins/pip_gui.py:255 msgid "Installing pip, please wait ...\n" "" msgstr "pipをインストールしています。少々お待ちください ..." #: thonny/plugins/pip_gui.py:279 msgid "You seem to have problems with pip\n" "\n" "" msgstr "pipに問題があるようです" #: thonny/plugins/pip_gui.py:283 msgid "pip, a required module for managing packages is missing or too old for Thonny.\n" "\n" "If your system package manager doesn't provide recent pip (9.0.0 or later), then you can install newest version by downloading " msgstr "パッケージの管理に必要なモジュールpipが見つからないか、Thonnyで使うにはバージョンが古すぎます。\n" "\n" "もしシステムのパッケージマネージャが新しいバージョンのpip(9.0.0以上)を提供していない場合は最新のバージョンを" #: thonny/plugins/pip_gui.py:290 msgid " and running it with " msgstr "からダウンロードして" #: thonny/plugins/pip_gui.py:292 msgid " (probably needs admin privileges).\n" "\n" "" msgstr "を実行することでインストールできます(おそらく管理者権限が必要です)。" #: thonny/plugins/pip_gui.py:302 msgid "Alternatively, if you have an older pip installed, then you can install packages on the command line (Tools → Open system shell...)" msgstr "もしくは、古いpipがインストールされていればコマンドライン(ツール→システムシェルを開く...)でパッケージをインストールできます。" #: thonny/plugins/pip_gui.py:351 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.\n" "\n" "" msgstr "現在のインタプリタではこれらのパッケージのみ閲覧できます。\n" "インストール・アップグレード・アンインストールするには「ツール→システムシェルを開く...」を使用してください。" #: thonny/plugins/pip_gui.py:357 msgid "Packages' directory\n" "" msgstr "パッケージのディレクトリ" #: thonny/plugins/pip_gui.py:363 msgid "Install from PyPI\n" "" msgstr "PyPIからインストール" #: thonny/plugins/pip_gui.py:366 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.\n" "\n" "" msgstr "どこからパッケージを取得すればいいかわからない場合はPython Package Indexで探すと良いでしょう。パッケージの名前を上にある検索ボックスに入力し、ENTERを押してください。" #: thonny/plugins/pip_gui.py:372 msgid "Install from local file\n" "" msgstr "ローカルファイルからインストール" #: thonny/plugins/pip_gui.py:374 msgid "Click " msgstr " " #: thonny/plugins/pip_gui.py:375 msgid "here" msgstr "ここ" #: thonny/plugins/pip_gui.py:378 msgid " to locate and install the package file (usually with .whl, .tar.gz or .zip extension).\n" "\n" "" msgstr "をクリックしてパッケージファイル(拡張子が.whl, .tar.gz, .zipのもの)をインストール" #: thonny/plugins/pip_gui.py:381 msgid "Upgrade or uninstall\n" "" msgstr "アップグレードもしくはアンインストール" #: thonny/plugins/pip_gui.py:383 msgid "Start by selecting the package from the left.\n" "\n" "" msgstr "左からパッケージを選択してください。" #: thonny/plugins/pip_gui.py:387 msgid "Target: " msgstr "対象:" #: thonny/plugins/pip_gui.py:390 msgid "virtual environment\n" "" msgstr "仮想環境" #: thonny/plugins/pip_gui.py:394 msgid "user site packages\n" "" msgstr "ユーザーのsiteパッケージ" #: thonny/plugins/pip_gui.py:399 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from " msgstr "このダイアログではすべてのパッケージを表示していますが、アップグレードとアンインストールができるのは次のパッケージのみです" #: thonny/plugins/pip_gui.py:407 msgid ". New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "新しいパッケージもこのディレクトリにインストールされます。これ以外の場所は別の方法で管理してください。" #: thonny/plugins/pip_gui.py:430 msgid "Installed version: " msgstr "インストールされているバージョン:" #: thonny/plugins/pip_gui.py:432 msgid "Installed to: " msgstr "インストールする場所:" #: thonny/plugins/pip_gui.py:452 msgid "Upgrade" msgstr "アップグレード" #: thonny/plugins/pip_gui.py:457 msgid "Install" msgstr "インストール" #: thonny/plugins/pip_gui.py:479 msgid "Could not find the package from PyPI." msgstr "PyPIでパッケージを見つけられませんでした。" #: thonny/plugins/pip_gui.py:482 msgid "\n" "Please check your spelling!" msgstr "スペルを確認してください。" #: thonny/plugins/pip_gui.py:482 msgid "\n" "You need to enter " msgstr "正しいパッケージ名を" #: thonny/plugins/pip_gui.py:483 msgid "exact package name" msgstr "入力してください" #: thonny/plugins/pip_gui.py:488 msgid "Could not find the package info from PyPI. Error code: " msgstr "PyPIでパッケージを見つけられませんでした。エラーコード:" #: thonny/plugins/pip_gui.py:500 msgid "Latest stable version" msgstr "最新の安定版" #: thonny/plugins/pip_gui.py:502 msgid "Latest version" msgstr "最新版" #: thonny/plugins/pip_gui.py:503 msgid "Summary" msgstr "まとめ" #: thonny/plugins/pip_gui.py:504 msgid "Author" msgstr "作者" #: thonny/plugins/pip_gui.py:505 msgid "Homepage" msgstr "ホームページ" #: thonny/plugins/pip_gui.py:507 msgid "Bugtracker" msgstr "バグの追跡" #: thonny/plugins/pip_gui.py:509 msgid "Documentation" msgstr "ドキュメント" #: thonny/plugins/pip_gui.py:511 msgid "PyPI page" msgstr "PyPIページ" #: thonny/plugins/pip_gui.py:515 msgid "Requires" msgstr "必須" #: thonny/plugins/pip_gui.py:553 msgid "Can't find package name from the list: " msgstr "一覧からパッケージ名を見つけられませんでした:" #: thonny/plugins/pip_gui.py:586 msgid "Really uninstall?" msgstr "本当にアンインストールしますか?" #: thonny/plugins/pip_gui.py:590 msgid "Are you sure you want to uninstall it?" msgstr "本当にアンインストールしますか?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "現在のフレームへ戻る" #: thonny/plugins/variables.py:142 msgid "Variables" msgstr "変数" thonny-3.2.7/thonny/locale/zh_CN/0000755000175000017500000000000013611777205017644 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/zh_CN/LC_MESSAGES/0000755000175000017500000000000013611777205021431 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/zh_CN/LC_MESSAGES/thonny.mo0000644000175000017500000005571413611773167023324 0ustar annamaaannamaa00000000000000V ||}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/; ;U;3<$K< p<< <<#<'<=,,=(Y==== ====]=D> S> ]> j>(w>>>>>>3>.?D?X? _?k?r?y? ?? ??0@:7@r@ y@ @@@1@@A#ABNB^B|B"BBBB:BCC "C0CAC HCRCbCxCC CCCCC CCCC CD D D!D2D:DADTD[DjD}D3EEELESE*WEE E,EEEEFF "F /F 9F=CFjF2F G,G?G FGTGmG*G GG G G GG!G H3H:HPH`H gHqHHHHoOIfI2&JYJ yJ JJJ"JJJKK *K7KJKZK1kKGK+K&L28LlkL1LB M MM WMVdMM MM M*M-NBN^NzNNN;N N7O ;OEOLOSOZObOtO2xO OOOOOO P P5PGY^Y YYZ.Z>Z"ZZ}Z Z ZZZZ.ZZ Z["[?<[|[[[ [%d items(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)(restart Thonny after changing this)(used when clicking Debug toolbar button)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAdvanced install / upgrade / downgradeAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAllow stepping into libraries (ie. outside of main script directory)Alternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portBrowse the packagesBugtrackerCan't close yetCan't find package name from the list:Can't find suitable diskCancelCancel the process?Case sensitiveChange font sizeChange working directory to script directory on Run / DebugCircuitPython (generic)CircuitPython deviceClearClear shellClickClick CloseClose allClose othersComment outConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)ConfirmationConnect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find disk '%s'.Could not find disk '%s'. Do you want to locate it yourself?Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDeleteDeleting %sDesired versionDetailsDirectory propertiesDisable notification soundDisabled checks (one id per line)DisconnectDo you want to continue and locate the disk yourself?Do you want to overwrite '%s' ?Dock user windowsDocumentationDon't forget that main.py only works without embedded main script.Done!DownDownload to %sDownloading %s to %sEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFile propertiesFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus intoFocus shellFont scaling modeFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: zh-CN %d 个品目(此时和Thonny后台使用相同的解释器,所以两个窗口管理相同的包.)(改变后重启Thonny)(当按下调试按钮后使用)特殊的虚拟环境(已弃用)关于Birdseye关于Thonny高级 安装/升级/允许在shell中使用Tab键补全允许在编辑器中使用Tab键补全只允许运行一个Thonny.允许进入包脚本中(即主脚本之外)可选的python3解释器或虚拟环境你确定你想要卸载吗?助手作者自动补全回执回到当前frame无效的文件夹Birdseye是一个python的调试器,需要独立安装. 你想打开帮助页了解更多吗?Birdseye端口浏览包问题追踪未能关闭无法从这个表中找到包的名字:无法找到合适的磁盘取消取消这个进程?区分大小写改变字体大小改变工作目录为运行或调试脚本的目录CircuitPython(一般)CircuitPython设备清空清空shell点击点击关闭全部关闭关闭其他的转为注释配置已更新。 重启Thonny以开始于常规模式工作。 (如果您稍后改变主意,请参阅'工具→设置→通用'.)确认连接你的设备到电脑,并在下方选择响应端口复制复制文本复制中复制 %s 到 %s无法找到磁盘'%s'无法找到磁盘 '%s'.你想自己找到它吗?没有从PyPI找到此包无法从PyPI找到此包.生成新的虚拟环境新的虚拟环境剪切调试调试当前脚本调试当前脚本(birdseye)调试当前脚本(faster)调试当前脚本(nicer)调试模式(提供更详细的诊断日志)缩小字体反缩进选择的行删除删除 %s需要的版本详细文件夹属性禁用通知声禁用检查(one id per line)断开你确定要自己选定磁盘吗?你想要覆盖掉'%s'?停靠用户窗口文档不要忘记main.py没有被主要脚本导入才能运行完成!向下下载到 %s 下载 %s 到 %s编辑编辑器编辑器字体请输入一个整数输入替换的字符串错误错误代码错误:事件异常退出退出ThonnyShell中展开导出使用日志文件文件属性文件查找查找&替换从PyPI安装包查找:固件切换到编辑器切换切换到shell字体缩放模式出于性能原因,Shell避免显示非常长的行(请参阅 工具 => 设置 => Shell). 在这里,您可以与原始文本片段进行交互.找到多个'%s'磁盘.你想自己选择一个吗?全屏常规堆堆模式已开启. 在视图中可关闭.帮助帮助内容高亮显示当前行(需要重启编辑器)斜体显示局部变量高亮匹配名称高亮显示括号高亮显示语法元素主页网站主页已安装IO 字体如果未找到,你可能需要安装相应的USB驱动程序如果你不知道包的来源,那么你可从PyPI 中查找,在搜索框输入名字并回车进行查找如果你需要它,那么请从命令行中安装.增大字体缩进选择的行安装从PyPI安装从本地文件中安装从requirements文件中安装安装最新的MicroPython到BBC micro:bit安装在:已安装版本:安装中...解释器中断执行步进程序执行后保持终端开启已知的解释器语言最新的稳定版本最新的版本加载加载中选择另一个?位置记录程序执行事件看起来你在安装一个与Thonny相关的包, 如果你想安装一个Thonny的插件你应该通过 '工具--->管理插件...'替代. 你确定在后台安装 %s 吗?看起来你正在安装过时的Thonny插件(未指定版本). 假如你仍然要安装,请从命令行安装.编写于: 爱沙尼亚,塔尔图大学. 帮助者: 开源社区,树莓派基金 会和Cybernetica AS.确认MicroPython已经安装到你的micro:bit上请确定micro:bit已经插入!管理%s包管理包...管理插件...最大化查看行的最大长度.超出后提取可保存的最大行数可能使调试变慢MicroPython(一般)MicroPython设备修改时间移动到回收站移至废纸篓移动 %s 到 %s注意!所有在micro:bit上的文件将被删除注意!自动关闭终端需要自行设置 (Shell ->当Shell退出时)注意!该值较大可能影响运行效果注意,改变设置后请重启Thonny!注意!改变一些风格在重启Thonny后生效!注意!这还可能存在一个与当前Thonny兼容的版本, 点击'...'可查看或选择该版本安装.注意!Thonny仅支持Python3.5和之后的版本注意!你需要重启Thonny在安装/升级/卸载一个插件后新文件新文件夹新的包也会安装到这个文件夹下,其他位置必须通过其他方式管理.下一个对象笔记本确认实例检查当代码有警告自动打开助手功能当程序遇到异常自动打开助手功能打开Thonny日志目录...打开Thonny安装目录...自动打开和关闭栈视图打开replayer打开系统shell...打开对话框用于安装或升级你设备的MicroPython打开...第一次调用时打开栈试图,回到主程序关闭设置...步出大纲步过覆盖?重写主题 '%s'包在安装或卸载其他包时需要用到'{}'包.包文件夹粘贴路径执行MyPy检查执行选定的Pylink检查请检查你的拼写!绘图器绘图器数字可视化到Shell端口首选调试器程序执行后启动Python REPL预览上一个对象打印...程序参数程序参数:程序树图属性PyPI页面Pygame Zero模式 Python解释器退出真的卸载吗?最近的文件建议最大代码长度(0表示关闭边界线)恢复撤销刷新常规模式重命名...重新打开上一个会话中的所有文件替换全部替换替代项:替换+查找报告问题依赖项依赖项:恢复执行运行运行&调试执行/继续运行当前脚本在终端运行当前脚本运行至光标在终端运行此脚本保存另存为...保存一个副本...保存中详细请查看帮助.全选全选为新的虚拟环境选择一个新的文件夹选择已存在或创建新的文件夹选择解释器选择的文件夹非空, 请选择另一个或取消.发送 EOF/软重启Shell显示绘图器在单独的窗口中显示函数调用(框架)显示行号大小提取的文本(%d 个字符)栈在左边选择你要操作的包回执步进步出步过停止停止/重启后端进程存储空间摘要切换至一般模式语法主题位置:终端终端仿真The answer is这个进程正在运行,你确定取消吗?Thonny的解释器(默认)找不到替换的文字!主题&字体这里您可以记录你的笔记 (文档,代码段,等等)。 所有内容都会自动保存并下次打开Thonny时加载。 您可以随意删除此文本,为自己的笔记腾出空间。此电脑此窗口是为了管理Thonny的插件和插件的依赖项. 如果你想为你的程序安装包请选择'工具 ->管理包...'这里列出了所有可用的包,但升级或卸载只能在这里这是一个注释这个包需要另一个Thonny版本:此软件完全免责! 这是一款自由软件,你也可以在特 定的条款下分发它,详细请查看 https://opensource.org/licenses/MIT. 此虚拟环境由Thonny自动维护Thonny 设置Thonny插件没有依赖项的Thonny插件注释切换工具自动探测端口UI 模式UI 缩放倍数UI主题如果你想要传统的体验请取消勾选取消注释撤销卸载不匹配的依赖项向上升级升级依赖项升级或卸载上载到 %s上载 %s 到 %s如果你想停止调试,请使用"停止"指令变量版本历史要安装的版本:视图Thonny应该使用哪个解释器或 设备运行你的代码?当前解释器下,你只能通过'工具--->打开系统Shell...' 来安装升级或卸载包工作中换行文字(可能很慢)你现在可以关闭此提示.你需要输入你需要选择一个文件你的解释器不在此列表里?放大全部文件blah,blah字节确切的包名这里查找你的设备名字,"USB Serial"或"UART"micro:bit位置:请等待python可执行软件支持基本的ANSI颜色和样式安装本地的包(扩展名通常为.whl, .tar.gz or .zip)安装requirements.txt中的包unclosed_string用户安装的包虚拟环境thonny-3.2.7/thonny/locale/zh_CN/LC_MESSAGES/thonny.po0000644000175000017500000011752313611773167023324 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: zh-CN\n" #: thonny/workbench.py:355 #, fuzzy msgid "File" msgstr "文件" #: thonny/workbench.py:356 #, fuzzy msgid "Edit" msgstr "编辑" #: thonny/workbench.py:357 #, fuzzy msgid "View" msgstr "视图" #: thonny/running.py:95 thonny/workbench.py:358 #, fuzzy msgid "Run" msgstr "运行" #: thonny/workbench.py:360 #, fuzzy msgid "Tools" msgstr "工具" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 #, fuzzy msgid "Help" msgstr "帮助" #: thonny/workbench.py:522 #, fuzzy msgid "Alternative Python 3 interpreter or virtual environment" msgstr "可选的python3解释器或虚拟环境" #: thonny/workbench.py:530 #, fuzzy msgid "A special virtual environment (deprecated)" msgstr "特殊的虚拟环境(已弃用)" #: thonny/workbench.py:568 #, fuzzy msgid "Exit" msgstr "退出" #: thonny/workbench.py:595 #, fuzzy msgid "Decrease font size" msgstr "缩小字体" #: thonny/workbench.py:607 #, fuzzy msgid "Focus editor" msgstr "切换到编辑器" #: thonny/workbench.py:616 #, fuzzy msgid "Focus shell" msgstr "切换到shell" #: thonny/workbench.py:627 #, fuzzy msgid "Maximize view" msgstr "最大化查看" #: thonny/workbench.py:639 #, fuzzy msgid "Full screen" msgstr "全屏" #: thonny/workbench.py:1250 #, fuzzy msgid "Program arguments" msgstr "程序参数" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 #, fuzzy msgid "About Thonny" msgstr "关于Thonny" #: thonny/plugins/about.py:77 #, fuzzy msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "编写于:\n" "爱沙尼亚,塔尔图大学.\n" "帮助者:\n" "开源社区,树莓派基金\n" "会和Cybernetica AS." #: thonny/plugins/about.py:103 #, fuzzy msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "此软件完全免责!\n" "这是一款自由软件,你也可以在特\n" "定的条款下分发它,详细请查看\n" "https://opensource.org/licenses/MIT.\n" "" #: thonny/plugins/about.py:146 #, fuzzy msgid "Version history" msgstr "版本历史" #: thonny/plugins/about.py:153 #, fuzzy msgid "Report problems" msgstr "报告问题" #: thonny/plugins/assistant_config_page.py:15 #, fuzzy msgid "Open Assistant automatically when program crashes with an exception" msgstr "当程序遇到异常自动打开助手功能" #: thonny/plugins/assistant_config_page.py:21 #, fuzzy msgid "Open Assistant automatically when it has warnings for your code" msgstr "当代码有警告自动打开助手功能" #: thonny/plugins/assistant_config_page.py:26 #, fuzzy msgid "Perform selected Pylint checks" msgstr "执行选定的Pylink检查" #: thonny/plugins/assistant_config_page.py:29 #, fuzzy msgid "Perform MyPy checks" msgstr "执行MyPy检查" #: thonny/plugins/assistant_config_page.py:31 #, fuzzy msgid "Disabled checks (one id per line)" msgstr "禁用检查(one id per line)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 #, fuzzy msgid "Assistant" msgstr "助手" #: thonny/plugins/autocomplete.py:316 #, fuzzy msgid "Auto-complete" msgstr "自动补全" #: thonny/plugins/backend_config_page.py:43 #, fuzzy msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Thonny应该使用哪个解释器或\n" "设备运行你的代码?" #: thonny/plugins/backend_config_page.py:127 #, fuzzy msgid "Interpreter" msgstr "解释器" #: thonny/plugins/birdseye_frontend.py:32 #, fuzzy msgid "About Birdseye" msgstr "关于Birdseye" #: thonny/plugins/birdseye_frontend.py:33 #, fuzzy msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye是一个python的调试器,需要独立安装.\n" "你想打开帮助页了解更多吗?" #: thonny/plugins/birdseye_frontend.py:60 #, fuzzy msgid "Debug current script (birdseye)" msgstr "调试当前脚本(birdseye)" #: thonny/plugins/commenting_indenting.py:143 #, fuzzy msgid "Toggle comment" msgstr "注释切换" #: thonny/plugins/commenting_indenting.py:153 #, fuzzy msgid "Comment out" msgstr "转为注释" #: thonny/plugins/commenting_indenting.py:163 #, fuzzy msgid "Uncomment" msgstr "取消注释" #: thonny/plugins/common_editing_commands.py:20 #, fuzzy msgid "Undo" msgstr "撤销" #: thonny/plugins/common_editing_commands.py:32 #, fuzzy msgid "Redo" msgstr "恢复撤销" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 #, fuzzy msgid "Cut" msgstr "剪切" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 #, fuzzy msgid "Copy" msgstr "复制" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 #, fuzzy msgid "Paste" msgstr "粘贴" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 #, fuzzy msgid "Select all" msgstr "全选" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 #, fuzzy msgid "Run to cursor" msgstr "运行至光标" #: thonny/plugins/debugger.py:863 #, fuzzy msgid "Can't close yet" msgstr "未能关闭" #: thonny/plugins/debugger.py:864 #, fuzzy msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "如果你想停止调试,请使用\"停止\"指令" #: thonny/plugins/dock_user_windows_frontend.py:27 #, fuzzy msgid "Dock user windows" msgstr "停靠用户窗口" #: thonny/plugins/editor_config_page.py:14 #, fuzzy msgid "Highlight matching names" msgstr "高亮匹配名称" #: thonny/plugins/editor_config_page.py:20 #, fuzzy msgid "Highlight local variables" msgstr "斜体显示局部变量" #: thonny/plugins/editor_config_page.py:25 #, fuzzy msgid "Highlight parentheses" msgstr "高亮显示括号" #: thonny/plugins/editor_config_page.py:26 #, fuzzy msgid "Highlight syntax elements" msgstr "高亮显示语法元素" #: thonny/plugins/editor_config_page.py:29 #, fuzzy msgid "Highlight current line (requires reopening the editor)" msgstr "高亮显示当前行(需要重启编辑器)" #: thonny/plugins/editor_config_page.py:34 #, fuzzy msgid "Allow code completion with Tab-key in editors" msgstr "允许在编辑器中使用Tab键补全" #: thonny/plugins/editor_config_page.py:40 #, fuzzy msgid "Allow code completion with Tab-key in Shell" msgstr "允许在shell中使用Tab键补全" #: thonny/plugins/editor_config_page.py:44 #, fuzzy msgid "Show line numbers" msgstr "显示行号" #: thonny/plugins/editor_config_page.py:47 #, fuzzy msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "建议最大代码长度(0表示关闭边界线)" #: thonny/plugins/editor_config_page.py:68 #, fuzzy msgid "Editor" msgstr "编辑器" #: thonny/plugins/event_logging.py:197 #, fuzzy msgid "Export usage logs..." msgstr "导出使用日志" #: thonny/plugins/event_view.py:38 #, fuzzy msgid "Events" msgstr "事件" #: thonny/plugins/files.py:307 #, fuzzy msgid "Files" msgstr "文件" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 #, fuzzy msgid "Find & Replace" msgstr "查找&替换" #: thonny/plugins/find_replace.py:62 #, fuzzy msgid "Find:" msgstr "查找:" #: thonny/plugins/find_replace.py:73 #, fuzzy msgid "Replace with:" msgstr "替代项:" #: thonny/plugins/find_replace.py:91 #, fuzzy msgid "Case sensitive" msgstr "区分大小写" #: thonny/plugins/find_replace.py:98 #, fuzzy msgid "Up" msgstr "向上" #: thonny/plugins/find_replace.py:102 #, fuzzy msgid "Down" msgstr "向下" #: thonny/plugins/find_replace.py:111 #, fuzzy msgid "Find" msgstr "查找" #: thonny/plugins/find_replace.py:121 #, fuzzy msgid "Replace" msgstr "替换" #: thonny/plugins/find_replace.py:129 #, fuzzy msgid "Replace+Find" msgstr "替换+查找" #: thonny/plugins/find_replace.py:138 #, fuzzy msgid "Replace all" msgstr "全部替换" #: thonny/plugins/find_replace.py:232 #, fuzzy msgid "Enter string to be replaced." msgstr "输入替换的字符串" #: thonny/plugins/find_replace.py:316 #, fuzzy msgid "The specified text was not found!" msgstr "找不到替换的文字!" #: thonny/plugins/general_config_page.py:13 #, fuzzy msgid "Allow only single Thonny instance" msgstr "只允许运行一个Thonny." #: thonny/plugins/general_config_page.py:20 #, fuzzy msgid "Reopen all files from previous session" msgstr "重新打开上一个会话中的所有文件" #: thonny/plugins/general_config_page.py:26 #, fuzzy msgid "Disable notification sound" msgstr "禁用通知声" #: thonny/plugins/general_config_page.py:75 #, fuzzy msgid "Font scaling mode" msgstr "字体缩放模式" #: thonny/plugins/heap.py:35 #, fuzzy msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "堆模式已开启.\n" "在视图中可关闭." #: thonny/plugins/heap.py:83 #, fuzzy msgid "Heap" msgstr "堆" #: thonny/plugins/general_config_page.py:42 #, fuzzy msgid "Language" msgstr "语言" #: thonny/plugins/notes.py:33 #, fuzzy msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "这里您可以记录你的笔记 (文档,代码段,等等)。\n" "所有内容都会自动保存并下次打开Thonny时加载。\n" "您可以随意删除此文本,为自己的笔记腾出空间。" #: thonny/plugins/notes.py:61 #, fuzzy msgid "Notes" msgstr "笔记本" #: thonny/plugins/object_inspector.py:108 #, fuzzy msgid "Previous object" msgstr "上一个对象" #: thonny/plugins/object_inspector.py:111 #, fuzzy msgid "Next object" msgstr "下一个对象" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "实例检查" #: thonny/plugins/outline.py:137 #, fuzzy msgid "Outline" msgstr "大纲" #: thonny/plugins/pgzero_frontend.py:26 #, fuzzy msgid "Pygame Zero mode" msgstr "Pygame Zero模式\n" "" #: thonny/plugins/pip_gui.py:78 #, fuzzy msgid "Find package from PyPI" msgstr "从PyPI安装包" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 #, fuzzy msgid "Uninstall" msgstr "卸载" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 #, fuzzy msgid "Close" msgstr "关闭" #: thonny/plugins/pip_gui.py:382 #, fuzzy msgid "Click " msgstr "点击" #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 #, fuzzy msgid "here" msgstr "这里" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 #, fuzzy msgid "Upgrade" msgstr "升级" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 #, fuzzy msgid "Install" msgstr "安装" #: thonny/plugins/pip_gui.py:505 #, fuzzy msgid "Could not find the package from PyPI." msgstr "没有从PyPI找到此包" #: thonny/plugins/pip_gui.py:515 #, fuzzy msgid "exact package name" msgstr "确切的包名" #: thonny/plugins/pip_gui.py:533 #, fuzzy msgid "Latest stable version" msgstr "最新的稳定版本" #: thonny/plugins/pip_gui.py:535 #, fuzzy msgid "Latest version" msgstr "最新的版本" #: thonny/plugins/pip_gui.py:536 #, fuzzy msgid "Summary" msgstr "摘要" #: thonny/plugins/pip_gui.py:537 #, fuzzy msgid "Author" msgstr "作者" #: thonny/plugins/pip_gui.py:538 #, fuzzy msgid "Homepage" msgstr "网站主页" #: thonny/plugins/pip_gui.py:540 #, fuzzy msgid "Bugtracker" msgstr "问题追踪" #: thonny/plugins/pip_gui.py:542 #, fuzzy msgid "Documentation" msgstr "文档" #: thonny/plugins/pip_gui.py:544 #, fuzzy msgid "PyPI page" msgstr "PyPI页面" #: thonny/plugins/pip_gui.py:548 #, fuzzy msgid "Requires" msgstr "依赖项" #: thonny/plugins/pip_gui.py:614 #, fuzzy msgid "Really uninstall?" msgstr "真的卸载吗?" #: thonny/plugins/pip_gui.py:619 #, fuzzy msgid "Are you sure you want to uninstall it?" msgstr "你确定你想要卸载吗?" #: thonny/plugins/variables.py:19 #, fuzzy msgid "Back to\n" "current frame" msgstr "回到当前frame" #: thonny/plugins/variables.py:131 #, fuzzy msgid "Variables" msgstr "变量" #: thonny/base_file_browser.py:30 #, fuzzy msgid "This computer" msgstr "此电脑" #: thonny/base_file_browser.py:568 #, fuzzy msgid "Refresh" msgstr "刷新" #: thonny/base_file_browser.py:572 #, fuzzy msgid "Focus into" msgstr "切换" #: thonny/base_file_browser.py:1001 #, fuzzy msgid "Error" msgstr "错误" #: thonny/base_file_browser.py:1001 #, fuzzy msgid "You need to select a file!" msgstr "你需要选择一个文件" #: thonny/base_file_browser.py:1005 #, fuzzy msgid "Overwrite?" msgstr "覆盖?" #: thonny/base_file_browser.py:1005 #, fuzzy msgid "Do you want to overwrite '%s' ?" msgstr "你想要覆盖掉'%s'?" #: thonny/code.py:513 thonny/code.py:515 #, fuzzy msgid "New" msgstr "新文件" #: thonny/code.py:526 #, fuzzy msgid "Open..." msgstr "打开..." #: thonny/code.py:528 #, fuzzy msgid "Load" msgstr "加载" #: thonny/code.py:537 #, fuzzy msgid "Recent files" msgstr "最近的文件" #: thonny/code.py:559 thonny/ui_utils.py:369 #, fuzzy msgid "Close all" msgstr "全部关闭" #: thonny/code.py:569 thonny/code.py:571 #, fuzzy msgid "Save" msgstr "保存" #: thonny/code.py:583 #, fuzzy msgid "Save as..." msgstr "另存为..." #: thonny/code.py:594 #, fuzzy msgid "Save copy..." msgstr "保存一个副本..." #: thonny/code.py:603 #, fuzzy msgid "Rename..." msgstr "重命名..." #: thonny/config_ui.py:17 #, fuzzy msgid "Thonny options" msgstr "Thonny 设置" #: thonny/running.py:94 #, fuzzy msgid "Run current script" msgstr "运行当前脚本" #: thonny/running.py:125 #, fuzzy msgid "Run current script in terminal" msgstr "在终端运行当前脚本" #: thonny/running.py:138 #, fuzzy msgid "Stop/Restart backend" msgstr "停止/重启后端进程" #: thonny/running.py:139 #, fuzzy msgid "Stop" msgstr "停止" #: thonny/running.py:150 #, fuzzy msgid "Interrupt execution" msgstr "中断执行" #: thonny/running.py:161 #, fuzzy msgid "Send EOF / Soft reboot" msgstr "发送 EOF/软重启" #: thonny/running.py:172 #, fuzzy msgid "Disconnect" msgstr "断开" #: thonny/running_config_page.py:23 #, fuzzy msgid "Known interpreters" msgstr "已知的解释器" #: thonny/running_config_page.py:36 #, fuzzy msgid "Your interpreter isn't in the list?" msgstr "你的解释器不在此列表里?" #: thonny/running_config_page.py:43 #, fuzzy msgid "Locate another" msgstr "选择另一个?" #: thonny/running_config_page.py:45 #, fuzzy msgid "python executable" msgstr "python可执行软件" #: thonny/running_config_page.py:47 #, fuzzy msgid "NB! Thonny only supports Python 3.5 and later" msgstr "注意!Thonny仅支持Python3.5和之后的版本" #: thonny/running_config_page.py:56 #, fuzzy msgid "Create new virtual environment" msgstr "生成新的虚拟环境" #: thonny/running_config_page.py:59 #, fuzzy msgid "Select existing or create a new empty directory" msgstr "选择已存在或创建新的文件夹" #: thonny/running_config_page.py:74 #, fuzzy msgid "Python interpreters" msgstr "Python解释器" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 #, fuzzy msgid "all files" msgstr "全部文件" #: thonny/running_config_page.py:89 #, fuzzy msgid "Select empty directory for new virtual environment" msgstr "为新的虚拟环境选择一个新的文件夹" #: thonny/running_config_page.py:96 #, fuzzy msgid "Bad directory" msgstr "无效的文件夹" #: thonny/running_config_page.py:97 #, fuzzy msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "选择的文件夹非空,\n" "请选择另一个或取消." #: thonny/running_config_page.py:112 #, fuzzy msgid "Creating virtual environment" msgstr "新的虚拟环境" #: thonny/shell.py:72 #, fuzzy msgid "Clear shell" msgstr "清空shell" #: thonny/shell.py:126 #, fuzzy msgid "Plotter" msgstr "绘图器" #: thonny/shell.py:245 #, fuzzy msgid "Clear" msgstr "清空" #: thonny/shell.py:258 #, fuzzy msgid "Show Plotter" msgstr "显示绘图器" #: thonny/shell.py:1389 #, fuzzy msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "出于性能原因,Shell避免显示非常长的行(请参阅 工具 => 设置 => Shell).\n" "在这里,您可以与原始文本片段进行交互." #: thonny/shell.py:1400 #, fuzzy msgid "Wrap text (may be slow)" msgstr "换行文字(可能很慢)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 #, fuzzy msgid "Copy to clipboard" msgstr "复制文本" #: thonny/shell.py:1431 #, fuzzy msgid "Expand in Shell" msgstr "Shell中展开" #: thonny/shell.py:1442 #, fuzzy msgid "Squeezed text (%d characters)" msgstr "提取的文本(%d 个字符)" #: thonny/shell.py:1611 #, fuzzy msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "绘图器数字可视化到Shell" #: thonny/shell.py:1613 #, fuzzy msgid "See Help for details." msgstr "详细请查看帮助." #: thonny/ui_utils.py:368 #, fuzzy msgid "Close others" msgstr "关闭其他的" #: thonny/ui_utils.py:1499 #, fuzzy msgid "Copying" msgstr "复制中" #: thonny/ui_utils.py:1502 #, fuzzy msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "复制\n" " %s\n" "到\n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 #, fuzzy msgid "Cancel" msgstr "取消" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 #, fuzzy msgid "OK" msgstr "确认" #: thonny/ui_utils.py:1783 #, fuzzy msgid "Cancel the process?" msgstr "取消这个进程?" #: thonny/ui_utils.py:1784 #, fuzzy msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "这个进程正在运行,你确定取消吗?" #: thonny/ui_utils.py:2182 #, fuzzy msgid "Select All" msgstr "全选" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 #, fuzzy msgid "Shell" msgstr "Shell" #: thonny/workbench.py:512 #, fuzzy msgid "The same interpreter which runs Thonny (default)" msgstr "Thonny的解释器(默认)" #: thonny/workbench.py:531 #, fuzzy msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "此虚拟环境由Thonny自动维护" #: thonny/workbench.py:532 #, fuzzy msgid "Location: " msgstr "位置" #: thonny/workbench.py:578 #, fuzzy msgid "Options..." msgstr "设置..." #: thonny/workbench.py:585 #, fuzzy msgid "Increase font size" msgstr "增大字体" #: thonny/workbench.py:650 #, fuzzy msgid "Change font size" msgstr "改变字体大小" #: thonny/workbench.py:651 #, fuzzy msgid "Zoom" msgstr "放大" #: thonny/workbench.py:660 #, fuzzy msgid "Exit Thonny" msgstr "退出Thonny" #: thonny/workbench.py:663 #, fuzzy msgid "Quit" msgstr "退出" #: thonny/workbench.py:1054 thonny/workbench.py:1062 #, fuzzy msgid "Overwriting theme '%s'" msgstr "重写主题 '%s'" #: thonny/workbench.py:1221 #, fuzzy msgid "Program arguments:" msgstr "程序参数:" #: thonny/workbench.py:1275 #, fuzzy msgid "Regular mode" msgstr "常规模式" #: thonny/workbench.py:1276 #, fuzzy msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "配置已更新。 重启Thonny以开始于常规模式工作。\n" "(如果您稍后改变主意,请参阅'工具→设置→通用'.)" #: thonny/plugins/ast_view.py:209 #, fuzzy msgid "Program tree" msgstr "程序树图" #: thonny/plugins/backend_config_page.py:130 #, fuzzy msgid "Select interpreter" msgstr "选择解释器" #: thonny/plugins/debugger.py:1162 #, fuzzy msgid "Resume" msgstr "恢复执行" #: thonny/plugins/debugger.py:1174 #, fuzzy msgid "Run / resume" msgstr "执行/继续" #: thonny/plugins/debugger.py:1189 #, fuzzy msgid "Debug current script" msgstr "调试当前脚本" #: thonny/plugins/debugger.py:1191 #, fuzzy msgid "Debug" msgstr "调试" #: thonny/plugins/debugger.py:1202 #, fuzzy msgid "Debug current script (nicer)" msgstr "调试当前脚本(nicer)" #: thonny/plugins/debugger.py:1214 #, fuzzy msgid "Debug current script (faster)" msgstr "调试当前脚本(faster)" #: thonny/plugins/debugger.py:1225 #, fuzzy msgid "Step over" msgstr "步过" #: thonny/plugins/debugger.py:1227 #, fuzzy msgid "Over" msgstr "步过" #: thonny/plugins/debugger.py:1238 #, fuzzy msgid "Step into" msgstr "步进" #: thonny/plugins/debugger.py:1240 #, fuzzy msgid "Into" msgstr "步进" #: thonny/plugins/debugger.py:1251 #, fuzzy msgid "Step out" msgstr "步出" #: thonny/plugins/debugger.py:1253 #, fuzzy msgid "Out" msgstr "步出" #: thonny/plugins/debugger.py:1288 #, fuzzy msgid "Step back" msgstr "回执" #: thonny/plugins/debugger.py:1290 #, fuzzy msgid "Back" msgstr "回执" #: thonny/plugins/debugger.py:1296 #, fuzzy msgid "Stack" msgstr "栈" #: thonny/plugins/debugger.py:1297 #, fuzzy msgid "Exception" msgstr "异常" #: thonny/plugins/general_config_page.py:16 #, fuzzy msgid "Log program usage events" msgstr "记录程序执行事件" #: thonny/plugins/general_config_page.py:32 #, fuzzy msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "调试模式(提供更详细的诊断日志)" #: thonny/plugins/general_config_page.py:56 #, fuzzy msgid "UI mode" msgstr "UI 模式" #: thonny/plugins/general_config_page.py:69 #, fuzzy msgid "UI scaling factor" msgstr "UI 缩放倍数" #: thonny/plugins/general_config_page.py:88 #, fuzzy msgid "NB! Restart Thonny after changing these options!" msgstr "注意,改变设置后请重启Thonny!" #: thonny/plugins/general_config_page.py:102 #, fuzzy msgid "General" msgstr "常规" #: thonny/plugins/pip_gui.py:108 #, fuzzy msgid "INSTALL" msgstr "已安装" #: thonny/plugins/pip_gui.py:352 #, fuzzy msgid "Browse the packages" msgstr "浏览包" #: thonny/plugins/pip_gui.py:355 #, fuzzy msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "当前解释器下,你只能通过'工具--->打开系统Shell...'\n" "来安装升级或卸载包" #: thonny/plugins/pip_gui.py:363 #, fuzzy msgid "Packages' directory" msgstr "包文件夹" #: thonny/plugins/pip_gui.py:368 #, fuzzy msgid "Install from PyPI" msgstr "从PyPI安装" #: thonny/plugins/pip_gui.py:371 #, fuzzy msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "如果你不知道包的来源,那么你可从PyPI\n" "中查找,在搜索框输入名字并回车进行查找" #: thonny/plugins/pip_gui.py:387 #, fuzzy msgid "to locate requirements.txt file and install the packages specified in it." msgstr "安装requirements.txt中的包" #: thonny/plugins/pip_gui.py:392 #, fuzzy msgid "Click" msgstr "点击" #: thonny/plugins/pip_gui.py:397 #, fuzzy msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "安装本地的包(扩展名通常为.whl, .tar.gz or .zip)" #: thonny/plugins/pip_gui.py:403 #, fuzzy msgid "Upgrade or uninstall" msgstr "升级或卸载" #: thonny/plugins/pip_gui.py:405 #, fuzzy msgid "Start by selecting the package from the left." msgstr "在左边选择你要操作的包" #: thonny/plugins/pip_gui.py:409 #, fuzzy msgid "Target:" msgstr "位置:" #: thonny/plugins/pip_gui.py:412 #, fuzzy msgid "virtual environment" msgstr "虚拟环境" #: thonny/plugins/pip_gui.py:416 #, fuzzy msgid "user site packages" msgstr "用户安装的包" #: thonny/plugins/pip_gui.py:421 #, fuzzy msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "这里列出了所有可用的包,但升级或卸载只能在这里" #: thonny/plugins/pip_gui.py:431 #, fuzzy msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "新的包也会安装到这个文件夹下,其他位置必须通过其他方式管理." #: thonny/plugins/pip_gui.py:456 #, fuzzy msgid "Installed version:" msgstr "已安装版本:" #: thonny/plugins/pip_gui.py:458 #, fuzzy msgid "Installed to:" msgstr "安装在:" #: thonny/plugins/pip_gui.py:510 #, fuzzy msgid "Please check your spelling!" msgstr "请检查你的拼写!" #: thonny/plugins/pip_gui.py:512 #, fuzzy msgid "You need to enter" msgstr "你需要输入" #: thonny/plugins/pip_gui.py:520 #, fuzzy msgid "Could not find the package info from PyPI." msgstr "无法从PyPI找到此包." #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 #, fuzzy msgid "Error code:" msgstr "错误代码" #: thonny/plugins/pip_gui.py:581 #, fuzzy msgid "Can't find package name from the list:" msgstr "无法从这个表中找到包的名字:" #: thonny/plugins/pip_gui.py:615 #, fuzzy msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "在安装或卸载其他包时需要用到'{}'包." #: thonny/plugins/pip_gui.py:657 #, fuzzy msgid "Package" msgstr "包" #: thonny/plugins/pip_gui.py:757 #, fuzzy msgid "Manage packages for %s" msgstr "管理%s包" #: thonny/plugins/pip_gui.py:813 #, fuzzy msgid "Confirmation" msgstr "确认" #: thonny/plugins/pip_gui.py:814 #, fuzzy msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "看起来你在安装一个与Thonny相关的包,\n" "如果你想安装一个Thonny的插件你应该通过\n" "'工具--->管理插件...'替代.\n" "你确定在后台安装 %s 吗?" #: thonny/plugins/pip_gui.py:912 #, fuzzy msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "注意!这还可能存在一个与当前Thonny兼容的版本,\n" "点击'...'可查看或选择该版本安装." #: thonny/plugins/pip_gui.py:920 #, fuzzy msgid "Thonny plugin without requirements" msgstr "没有依赖项的Thonny插件" #: thonny/plugins/pip_gui.py:921 #, fuzzy msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "看起来你正在安装过时的Thonny插件(未指定版本).\n" "假如你仍然要安装,请从命令行安装." #: thonny/plugins/pip_gui.py:935 #, fuzzy msgid "Unsuitable requirements" msgstr "不匹配的依赖项" #: thonny/plugins/pip_gui.py:936 #, fuzzy msgid "This package requires different Thonny version:" msgstr "这个包需要另一个Thonny版本:" #: thonny/plugins/pip_gui.py:940 #, fuzzy msgid "If you still want it, then please install it from the command line." msgstr "如果你需要它,那么请从命令行中安装." #: thonny/plugins/pip_gui.py:984 #, fuzzy msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(此时和Thonny后台使用相同的解释器,所以两个窗口管理相同的包.)" #: thonny/plugins/pip_gui.py:990 #, fuzzy msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "注意!你需要重启Thonny在安装/升级/卸载一个插件后" #: thonny/plugins/pip_gui.py:1000 #, fuzzy msgid "Thonny plug-ins" msgstr "Thonny插件" #: thonny/plugins/pip_gui.py:1013 #, fuzzy msgid "Advanced install / upgrade / downgrade" msgstr "高级 安装/升级/" #: thonny/plugins/pip_gui.py:1022 #, fuzzy msgid "Desired version" msgstr "需要的版本" #: thonny/plugins/pip_gui.py:1060 #, fuzzy msgid "Upgrade dependencies" msgstr "升级依赖项" #: thonny/plugins/pip_gui.py:1118 #, fuzzy msgid "Requires:" msgstr "依赖项:" #: thonny/plugins/pip_gui.py:1122 #, fuzzy msgid "Error:" msgstr "错误:" #: thonny/plugins/pip_gui.py:1232 #, fuzzy msgid "Manage packages..." msgstr "管理包..." #: thonny/plugins/pip_gui.py:1238 #, fuzzy msgid "Manage plug-ins..." msgstr "管理插件..." #: thonny/plugins/replayer.py:354 #, fuzzy msgid "Open replayer..." msgstr "打开replayer" #: thonny/plugins/run_debug_config_page.py:12 #, fuzzy msgid "Change working directory to script directory on Run / Debug" msgstr "改变工作目录为运行或调试脚本的目录" #: thonny/plugins/run_debug_config_page.py:20 #, fuzzy msgid "Show function calls (frames) in separate windows" msgstr "在单独的窗口中显示函数调用(框架)" #: thonny/plugins/run_debug_config_page.py:21 #, fuzzy msgid "Uncheck if you want more traditional experience." msgstr "如果你想要传统的体验请取消勾选" #: thonny/plugins/run_debug_config_page.py:27 #, fuzzy msgid "Open and close Stack view automatically" msgstr "自动打开和关闭栈视图" #: thonny/plugins/run_debug_config_page.py:28 #, fuzzy msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "第一次调用时打开栈试图,回到主程序关闭" #: thonny/plugins/run_debug_config_page.py:37 #, fuzzy msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "允许进入包脚本中(即主脚本之外)" #: thonny/plugins/run_debug_config_page.py:38 #, fuzzy msgid "May make debugging slower." msgstr "可能使调试变慢" #: thonny/plugins/run_debug_config_page.py:43 #, fuzzy msgid "Preferred debugger" msgstr "首选调试器" #: thonny/plugins/run_debug_config_page.py:55 #, fuzzy msgid "(used when clicking Debug toolbar button)" msgstr "(当按下调试按钮后使用)" #: thonny/plugins/run_debug_config_page.py:60 #, fuzzy msgid "Birdseye port" msgstr "Birdseye端口" #: thonny/plugins/run_debug_config_page.py:64 #, fuzzy msgid "(restart Thonny after changing this)" msgstr "(改变后重启Thonny)" #: thonny/plugins/run_debug_config_page.py:72 #, fuzzy msgid "Run & Debug" msgstr "运行&调试" #: thonny/plugins/shell_config_page.py:16 #, fuzzy msgid "Terminal emulation" msgstr "终端仿真" #: thonny/plugins/shell_config_page.py:18 #, fuzzy msgid "supports basic ANSI-colors and styles" msgstr "支持基本的ANSI颜色和样式" #: thonny/plugins/shell_config_page.py:30 #, fuzzy msgid "Maximum number of lines to keep." msgstr "可保存的最大行数" #: thonny/plugins/shell_config_page.py:32 #, fuzzy msgid "NB! Large values may cause poor performance!" msgstr "注意!该值较大可能影响运行效果" #: thonny/plugins/shell_config_page.py:47 #, fuzzy msgid "Maximum length of line fragments before squeezing" msgstr "行的最大长度.超出后提取" #: thonny/plugins/terminal_config_page.py:10 #, fuzzy msgid "Running current script in terminal" msgstr "在终端运行此脚本" #: thonny/plugins/terminal_config_page.py:15 #, fuzzy msgid "Present Python REPL after program ends" msgstr "程序执行后启动Python REPL" #: thonny/plugins/terminal_config_page.py:22 #, fuzzy msgid "Keep terminal window open after Python process ends" msgstr "程序执行后保持终端开启" #: thonny/plugins/terminal_config_page.py:29 #, fuzzy msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "注意!自动关闭终端需要自行设置\n" "(Shell ->当Shell退出时)" #: thonny/plugins/terminal_config_page.py:38 #, fuzzy msgid "Terminal" msgstr "终端" #: thonny/plugins/theme_and_font_config_page.py:39 #, fuzzy msgid "UI theme" msgstr "UI主题" #: thonny/plugins/theme_and_font_config_page.py:52 #, fuzzy msgid "Syntax theme" msgstr "语法主题" #: thonny/plugins/theme_and_font_config_page.py:84 #, fuzzy msgid "Editor font" msgstr "编辑器字体" #: thonny/plugins/theme_and_font_config_page.py:107 #, fuzzy msgid "IO font" msgstr "IO 字体" #: thonny/plugins/theme_and_font_config_page.py:132 #, fuzzy msgid "Preview" msgstr "预览" #: thonny/plugins/theme_and_font_config_page.py:144 #, fuzzy msgid "This is a comment" msgstr "这是一个注释" #: thonny/plugins/theme_and_font_config_page.py:147 #, fuzzy msgid "The answer is" msgstr "The answer is" #: thonny/plugins/theme_and_font_config_page.py:151 #, fuzzy msgid "unclosed_string" msgstr "unclosed_string" #: thonny/plugins/theme_and_font_config_page.py:153 #, fuzzy msgid "blah, blah" msgstr "blah,blah" #: thonny/plugins/theme_and_font_config_page.py:176 #, fuzzy msgid "NB! Some style elements change only after restarting Thonny!" msgstr "注意!改变一些风格在重启Thonny后生效!" #: thonny/plugins/theme_and_font_config_page.py:215 #, fuzzy msgid "Enter an integer" msgstr "请输入一个整数" #: thonny/plugins/theme_and_font_config_page.py:228 #, fuzzy msgid "Theme & Font" msgstr "主题&字体" #: thonny/plugins/thonny_folders.py:18 #, fuzzy msgid "Open Thonny program folder..." msgstr "打开Thonny安装目录..." #: thonny/plugins/thonny_folders.py:23 #, fuzzy msgid "Open Thonny data folder..." msgstr "打开Thonny日志目录..." #: thonny/plugins/help/__init__.py:58 #, fuzzy msgid "Home" msgstr "主页" #: thonny/plugins/help/__init__.py:69 #, fuzzy msgid "Help contents" msgstr "帮助内容" #: thonny/plugins/micropython/__init__.py:175 #, fuzzy msgid "CircuitPython device" msgstr "CircuitPython设备" #: thonny/plugins/micropython/__init__.py:179 #, fuzzy msgid "MicroPython device" msgstr "MicroPython设备" #: thonny/plugins/micropython/__init__.py:191 #, fuzzy msgid "Connect your device to the computer and select corresponding port below" msgstr "连接你的设备到电脑,并在下方选择响应端口" #: thonny/plugins/micropython/__init__.py:194 #, fuzzy msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "查找你的设备名字,\"USB Serial\"或\"UART\"" #: thonny/plugins/micropython/__init__.py:196 #, fuzzy msgid "If you can't find it, you may need to install proper USB driver first." msgstr "如果未找到,你可能需要安装相应的USB驱动程序" #: thonny/plugins/micropython/__init__.py:220 #, fuzzy msgid "Port" msgstr "端口" #: thonny/plugins/micropython/__init__.py:229 #, fuzzy msgid "Try to detect port automatically" msgstr "自动探测端口" #: thonny/plugins/micropython/__init__.py:417 #, fuzzy msgid "MicroPython (generic)" msgstr "MicroPython(一般)" #: thonny/plugins/printing/__init__.py:79 #, fuzzy msgid "Print..." msgstr "打印..." #: thonny/plugins/system_shell/__init__.py:59 #, fuzzy msgid "Open system shell..." msgstr "打开系统shell..." #: thonny/plugins/backend_config_page.py:61 #, fuzzy msgid "Details" msgstr "详细" #: thonny/plugins/pip_gui.py:380 #, fuzzy msgid "Install from requirements file" msgstr "从requirements文件中安装" #: thonny/plugins/pip_gui.py:391 #, fuzzy msgid "Install from local file" msgstr "从本地文件中安装" #: thonny/plugins/pip_gui.py:970 #, fuzzy msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "此窗口是为了管理Thonny的插件和插件的依赖项.\n" "如果你想为你的程序安装包请选择'工具 ->管理包...'" #: thonny/plugins/circuitpython/__init__.py:47 #, fuzzy msgid "CircuitPython (generic)" msgstr "CircuitPython(一般)" #: thonny/plugins/commenting_indenting.py:123 #, fuzzy msgid "Indent selected lines" msgstr "缩进选择的行" #: thonny/plugins/commenting_indenting.py:133 #, fuzzy msgid "Dedent selected lines" msgstr "反缩进选择的行" #: thonny/workbench.py:1264 #, fuzzy msgid "Switch to\n" "regular\n" "mode" msgstr "切换至一般模式" #: thonny/plugins/microbit/__init__.py:54 #, fuzzy msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "确认MicroPython已经安装到你的micro:bit上" #: thonny/plugins/microbit/__init__.py:56 #, fuzzy msgid "Don't forget that main.py only works without embedded main script." msgstr "不要忘记main.py没有被主要脚本导入才能运行" #: thonny/plugins/microbit/__init__.py:102 #, fuzzy msgid "Install latest MicroPython to BBC micro:bit" msgstr "安装最新的MicroPython到BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 #, fuzzy msgid "micro:bit location:" msgstr "micro:bit位置:" #: thonny/plugins/microbit/__init__.py:109 #, fuzzy msgid "Version to be installed:" msgstr "要安装的版本:" #: thonny/plugins/microbit/__init__.py:111 #, fuzzy msgid "please wait" msgstr "请等待" #: thonny/plugins/microbit/__init__.py:115 #, fuzzy msgid "NB! All files on micro:bit will be deleted!" msgstr "注意!所有在micro:bit上的文件将被删除" #: thonny/plugins/microbit/__init__.py:195 #, fuzzy msgid "Installing ..." msgstr "安装中..." #: thonny/plugins/microbit/__init__.py:199 #, fuzzy msgid "Done!" msgstr "完成!" #: thonny/plugins/microbit/__init__.py:199 #, fuzzy msgid "You can now close this dialog." msgstr "你现在可以关闭此提示." #: thonny/plugins/micropython/__init__.py:298 #, fuzzy msgid "Firmware" msgstr "固件" #: thonny/plugins/micropython/__init__.py:301 #, fuzzy msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "打开对话框用于安装或升级你设备的MicroPython" #: thonny/plugins/microbit/__init__.py:67 #, fuzzy msgid "Could not find disk '%s'." msgstr "无法找到磁盘'%s'" #: thonny/plugins/microbit/__init__.py:69 #, fuzzy msgid "Make sure you have micro:bit plugged in!" msgstr "请确定micro:bit已经插入!" #: thonny/plugins/microbit/__init__.py:71 #, fuzzy msgid "Do you want to continue and locate the disk yourself?" msgstr "你确定要自己选定磁盘吗?" #: thonny/misc_utils.py:120 #, fuzzy msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "无法找到磁盘 '%s'.你想自己找到它吗?" #: thonny/misc_utils.py:123 #, fuzzy msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "找到多个'%s'磁盘.你想自己选择一个吗?" #: thonny/misc_utils.py:137 #, fuzzy msgid "Can't find suitable disk" msgstr "无法找到合适的磁盘" #: thonny/base_file_browser.py:259 #, fuzzy msgid "%d items" msgstr "%d 个品目" #: thonny/base_file_browser.py:581 #, fuzzy msgid "Move to Recycle Bin" msgstr "移动到回收站" #: thonny/base_file_browser.py:583 #, fuzzy msgid "Move to Trash" msgstr "移至废纸篓" #: thonny/base_file_browser.py:586 #, fuzzy msgid "Delete" msgstr "删除" #: thonny/base_file_browser.py:589 #, fuzzy msgid "New directory" msgstr "新文件夹" #: thonny/base_file_browser.py:592 #, fuzzy msgid "Properties" msgstr "属性" #: thonny/base_file_browser.py:593 #, fuzzy msgid "Storage space" msgstr "存储空间" #: thonny/base_file_browser.py:603 #, fuzzy msgid "Path" msgstr "路径" #: thonny/base_file_browser.py:605 #, fuzzy msgid "Directory properties" msgstr "文件夹属性" #: thonny/base_file_browser.py:607 #, fuzzy msgid "File properties" msgstr "文件属性" #: thonny/base_file_browser.py:609 #, fuzzy msgid "bytes" msgstr "字节" #: thonny/base_file_browser.py:612 #, fuzzy msgid "Size" msgstr "大小" #: thonny/base_file_browser.py:623 #, fuzzy msgid "Modified" msgstr "修改时间" #: thonny/base_file_browser.py:679 #, fuzzy msgid "Deleting %s" msgstr "删除 %s" #: thonny/base_file_browser.py:701 #, fuzzy msgid "Moving %s to %s" msgstr "移动 %s 到 %s" #: thonny/code.py:203 #, fuzzy msgid "Loading" msgstr "加载中" #: thonny/code.py:297 #, fuzzy msgid "Saving" msgstr "保存中" #: thonny/running.py:1408 #, fuzzy msgid "Working..." msgstr "工作中" #: thonny/plugins/files.py:199 #, fuzzy msgid "Uploading %s to %s" msgstr "上载 %s 到 %s" #: thonny/plugins/files.py:206 #, fuzzy msgid "Upload to %s" msgstr "上载到 %s" #: thonny/plugins/files.py:261 #, fuzzy msgid "Downloading %s to %s" msgstr "下载 %s 到 %s" #: thonny/plugins/files.py:267 #, fuzzy msgid "Download to %s" msgstr "下载到 %s " thonny-3.2.7/thonny/locale/pt_PT/0000755000175000017500000000000013611777205017671 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/pt_PT/LC_MESSAGES/0000755000175000017500000000000013611777205021456 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/pt_PT/LC_MESSAGES/thonny.mo0000644000175000017500000006451313611773167023346 0ustar annamaaannamaa00000000000000V |}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/;<v<.5=@d='===;=3)>7]>)>_>9?%Y? ??????t?E@W@l@@7@0@A A&!AHAHaAAAAAAAB BB'B0B BIB2C%9C_ChC*CIC.C=$DbDDDDD D$D'EF/EvEEE EEEE"E.F DF/PFFFFQF GG%G9GRGYG`GxG#GGGGG GGGG#H(H1H JHTH]HsH HH HH H HH8I IIIQIGJMJ>aJJJJJK KK%Kd:KK?OLLLLL&L+M4:M oM}M M MMMHMN.N5NNN^N gNrNN,NNO_P>P,"QOQeQvQQ>Q#Q%QR7R ORZRrRR?RR:bS>SMS*T:T]U_U dUvoUUUUVIVOcV#V&V/V.WBWH\WWnW X)X.X7X =XGX^XHeXXXXX,XY 0YA;Y}YY7Y YY YYZ&Z :ZGZWZhZZZZPZZ [ [ [.%[ T[_[o[[[[[[[[[[#\'\/?\o\w\\ \&\ \ \4\,]H]=a]]]]<]^.^ 6^W^)]^ ^^^^^^^^^__(_1_ H_AV_8_)__ `a.ataNb3ebb=Sccccc c(cd!=d_d9qd dd ddd dde*e9e6Me eeeePeff ffg'g(Egngwg gggg9gg hh%/haUhTh ii:i%d items(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)(restart Thonny after changing this)(used when clicking Debug toolbar button)A special virtual environment (deprecated)About BirdseyeAbout ThonnyAdvanced install / upgrade / downgradeAllow code completion with Tab-key in ShellAllow code completion with Tab-key in editorsAllow only single Thonny instanceAllow stepping into libraries (ie. outside of main script directory)Alternative Python 3 interpreter or virtual environmentAre you sure you want to uninstall it?AssistantAuthorAuto-completeBackBack to current frameBad directoryBirdseye is a Python debugger which needs to be installed separately. Do you want to open the help page and learn more?Birdseye portBrowse the packagesBugtrackerCan't close yetCan't find package name from the list:Can't find suitable diskCancelCancel the process?Case sensitiveChange font sizeChange working directory to script directory on Run / DebugCircuitPython (generic)CircuitPython deviceClearClear shellClickClick CloseClose allClose othersComment outConfiguration has been updated. Restart Thonny to start working in regular mode. (See 'Tools → Options → General' if you change your mind later.)ConfirmationConnect your device to the computer and select corresponding port belowCopyCopy to clipboardCopyingCopying %s to %sCould not find disk '%s'.Could not find disk '%s'. Do you want to locate it yourself?Could not find the package from PyPI.Could not find the package info from PyPI.Create new virtual environmentCreating virtual environmentCutDebugDebug current scriptDebug current script (birdseye)Debug current script (faster)Debug current script (nicer)Debug mode (provides more detailed diagnostic logs)Decrease font sizeDedent selected linesDeleteDeleting %sDesired versionDetailsDirectory propertiesDisable notification soundDisabled checks (one id per line)DisconnectDo you want to continue and locate the disk yourself?Do you want to overwrite '%s' ?Dock user windowsDocumentationDon't forget that main.py only works without embedded main script.Done!DownDownload to %sDownloading %s to %sEditEditorEditor fontEnter an integerEnter string to be replaced.ErrorError code:Error:EventsExceptionExitExit ThonnyExpand in ShellExport usage logs...FileFile propertiesFilesFindFind & ReplaceFind package from PyPIFind:FirmwareFocus editorFocus intoFocus shellFont scaling modeFor performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentProject-Id-Version: Thonny Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2019-08-24 13:36+0300 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: pt Language-Team: pt Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.7.0 %d itens(neste caso a infra-estrutura do Thonny usa o mesmo interpretador, portanto ambas as janelas gerem os mesmos pacotes).(reinicie o Thonny depois de mudar este valor)(usado ao clicar no botão do Depurador na barra de ferramentas)Um ambiente virtual especial (obsoleto)Sobre o BirdseyeSobre o ThonnyInstalação / actualização / desactualização avançadaPermitir completar código com a tecla Tab na ShellPermitir completar código com a tecla Tab nos editoresPermitir somente uma instância do ThonnyPermitir entrar nas bibliotecas (ou seja, tudo o que está fora da pasta da listagem principal)Interpretador de Python 3 alternativo ou ambiente virtualTem a certeza que o quer desinstalar?AssistenteAutorAuto-completarAtrásVoltar ao quadro presentePasta inválidaBirdseye é um depurador Python que tem de ser instalado separadamente. Quer abrir a página de ajuda e saber mais?Porto do birdseyeConsultar os pacotesRastreador de errosAinda não se pode fecharNão foi possível encontrar o nome do pacote na lista:Não foi possível encontrar um disco apropriadoCancelarCancelar o processo?Diferenciar maiúsculas de minúsculasMudar o tamanho da letraMudar a pasta de trabalho para a pasta da listagem ao Executar / DepurarCircuitPython (genérico)Dispositivo CircuitPythonLimparLimpar a shellCliqueClique FecharFechar tudoFechar os outrosComentarA configuração foi modificada. Reinicie o Thonny para começar a trabalhar no modo normal. (Vá a 'Ferramentas → Opções → Geral' se mais tarde mudar de ideias).ConfirmaçãoLigue o dispositivo ao computador e escolha o porto correspondente abaixoCopiarCopiar para a área de transferênciaCopiandoCopiando %s para %sNão foi possível encontrar o disco '%s'.Não foi possível encontrar o disco '%s'. Quer ser você a localizá-lo?Não foi possível encontrar o pacote no PyPi.Não foi possível encontrar a informação do pacote no PyPiCriar um novo ambiente virtualCriando o ambiente virtualCortarDepurarDepurar esta listagemDepurar esta listagem (birdseye)Depurar esta listagem (mais rápido)Depurar esta listagem (mais agradável)Modo de depuração (fornece registos de diagnóstico mais detalhados)Reduzir tamanho da letraDesindentar linhas marcadasEliminarEliminando %sVersão desejadaDetalhesPropriedades da pastaDesabilitar som nas notificaçõesVerificações desabilitadas (um id por linha)DesconectarQuer continuar e ser você a localizar o disco?Quer sobrepor '%s'?Fixar as janelas do utilizadorDocumentaçãoNão se esqueça que o main.py apenas funciona sem a listagem principal embutida.Terminado!BaixoDescarregar para %sDescarregando %s para %sEditarEditorTipo de letra do editorEscreva um inteiroEscreva o texto a ser substituído.ErroCódigo de erro:Erro:EventosExcepçãoSairSair do ThonnyExpandir na ShellExportar registo de utilização...FicheiroPropriedades do ficheiroFicheirosProcurarProcurar e substituirProcurar pacotes no PyPiProcurar:FirmwareFocar editorFocar emFocar shellModo de dimensionamento do textoPor razões de desempenho, a Shell evita mostrar o excedente das linhas muito longas (ver Ferramentas → Opções → Shell). Aqui pode interagir com o fragmento de texto original.Foram encontrados vários discos '%s'. Quer escolher um?Ecrã inteiroGeralMemória 'heap'Modo de Memória 'heap' ligado. Feche a vista de Memória 'heap' para o desligar.AjudaConteúdos da ajudaRealçar a linha do cursor (é necessário reiniciar o editor)Realçar variáveis locaisRealçar nomes iguaisRealçar parêntesisRealçar elementos da sintaxeInícioPágina inicialINSTALARTipo de letra de E/SSe não conseguir encontrá-lo, pode ser necessário instalar primeiro o controlador USB apropriado.Se não sabe onde obter os pacotes, o mais certo é que queira procurar no Python Package Index. Comece por escrever o nome do pacote na caixa de pesquisa e carregue em ENTER.Se mesmo assim o quer, instale-o a partir da linha de comandos.Aumentar o tamanho da letraIndentar linhas marcadasInstalarInstalar a partir do PyPiInstalar a partir de um ficheiro localInstalar a partir do ficheiro de requisitosInstalar o mais recente MicroPython no BBC micro:bitInstalado em:Versão instalada:Instalando...InterpretadorInterromper execuçãoEntrarManter a janela do terminal aberta depois do processo em Python terminarInterpretadores conhecidosIdiomaÚltima versão estávelÚltima versãoCarregarCarregandoLocalizar outroLocal: Registar eventos de utilização do programaParece que está a instalar um pacote relacionado com o Thonny. Se pretendia instalar um extra do Thonny, então deveria era escolher 'Ferramentas → Gerir extras...' Tem a certeza que quer instalar %s para a infra-estrutura?Parece que está a tentar instalar um extra do Thonny que está obsoleto (não especifica a versão do Thonny que precisa). Se mesmo assim o quer, então instale-o a partir da linha de comandos.Criado na Universidade de Tartu, Estonia, com a ajuda da comunidade de código aberto, a Fundação Raspberry Pi e a Cybernetica ASCertifique-se que o MicroPython for instalado no seu micro:bitCertifique-se que tem o micro:bit conectado!Gerir pacotes para %sGerir pacotes...Gerir extras...Maximizar vistaComprimento máximo dos fragmentos de linha antes de comprimirNúmero máximo de linhas a manter.Pode tornar mais lenta a depuração.MicroPython (genérico)Dispositivo MicroPythonModificadoMover para a ReciclagemMover para o LixoMovendo %s para %sATENÇÃO! Todos os ficheiros no micro:bit vão ser eliminados!ATENÇÃO! O encerramento automático tem que ser habilitado nas configurações do Terminal (Perfis → Shell → Quando a shell encerra)ATENÇÃO! Valores grandes podem comprometer o desempenho!ATENÇÃO! Reinicie o Thonny depois de alterar estas opções!ATENÇÃO! Alguns elementos de estilo só mudam depois de reiniciar o Thonny!ATENÇÃO! Pode haver outra versão disponível que seja compatível com esta versão do Thonny. Clique no botão '...' para escolher a versão a instalar.ATENÇÃO! O Thonny apenas suporta Python 3.5 ou posteriorATENÇÃO! Tem que reiniciar o Thonny depois de instalar / actualizar / desinstalar um extra.NovoNova pastaPacotes novos serão também instalados nesta pasta. Outras localizações têm de ser geridas por meios alternativos.Próximo elementoNotasOKExaminador de elementosAbrir o Assistente automaticamente quando tiver avisos para o seu códigoAbrir o Assistente automaticamente quando o programa estoira com uma excepçãoAbrir a pasta de dados do Thonny...Abrir a pasta de programa do Thonny...Abrir e fechar a vista da Pilha automaticamenteAbrir reprodutor...Abrir terminal do sistemaAbrir a janela que instala ou actualiza o MicroPython no seu dispositivoAbrir...Abre a vista da Pilha ao ser feita a primeira chamada e fecha-a quando o programa retorna ao quadro principal.Opções...SairPanoramaSobreSobrepor?Sobrepondo o tema '%s'PacoteO pacote '{}' é necessário para instalar e desinstalar outros pacotes.Pasta dos pacotesColarCaminhoExecutar verificações MyPyExecutar as verificações Pylint escolhidasVerifique a ortografia!DesenhadorO Desenhador visualiza séries de números apresentados na Shell.PortoDepurador preferidoApresentar o REPL do Python depois do programa terminarPrevisãoElemento anteriorImprimir...Argumentos do programaArgumentos do programa:Árvore do programaPropriedadesPágina no PyPiModo Pygame ZeroInterpretadores PythonSairDesinstalar mesmo?Ficheiros recentesComprimento máximo de linha recomendado (use 0 para desligar a linha de margem)RefazerRefrescarModo normalRenomear...Reabrir todos os ficheiros da sessão anteriorSubstituirSubstituir tudoSubstituir por:Substituir+ProcurarReportar problemasRequerRequer:RetomarExecutarExecutar e DepurarExecutar / retomarExecutar esta listagemExecutar esta listagem num terminalExecutar até ao cursorQuando executar a listagem corrente no terminalGuardarGuardar como...Guardar uma cópia...GuardandoConsulte a Ajuda para ver os detalhes.Marcar tudoMarcar tudoEscolha uma pasta vazia para o novo ambiente virtualescolha uma pasta existente ou crie uma novaEscolher o interpretadorA pasta escolhida não está vazia. Escolha outra ou cancele.Enviar EOF / Reinício suaveShellMostrar o DesenhadorMostrar chamadas de funções (quadros) em janelas separadasMostrar números de linhaTamanhoTexto comprimido (%d caracteres)PilhaComece por escolher o pacote à esquerda.Passo atrásEntrarSairSaltar por cimaPararParar/Reiniciar infra-estruturaEspaço de armazenamentoSumárioMudar para modo normalTema da sintaxeDestino:TerminalEmulação de terminalA resposta éO processo ainda está a correr. Tem a certeza que quer cancelar?O mesmo interpretador que executa o Thonny (predefinido)O texto especificado não foi encontrado!Tema e Tipo de letraEsta caixa é para os seus rascunhos -- instruções dos trabalhos, exemplos de código, etc. Tudo será guardado automaticamente e carregado quando abrir o Thonny da próxima vez. Esteja à vontade para apagar este texto e criar espaço para as suas próprias notas.Este computadorEsta janela serve para gerir extras do Thonny e as suas dependências. Se quiser instalar pacotes para os seus próprios programas, use 'Ferramentas → Gerir pacotes...'Esta janela lista todos os pacotes disponíveis mas apenas permite actualizar e desinstalar os pacotes instalados emIsto é um comentárioEste pacote requer uma versão diferente do Thonny:Este programa vem SEM QUALQUER GARANTIA! É software livre e está à vontade para o redistribuir sob certas condições. Visite https://opensource.org/licenses/MIT para ver os detalhesEste ambiente virtual é mantido automaticamente pelo Thonny.Opções do ThonnyExtras do ThonnyExtra do Thonny sem requisitosComutar comentárioFerramentasTentar encontrar o porto automaticamenteModo da interface do utilizadorEscala da interface do utilizadorTema da interfaceDesmarque se pretender uma experiência mais tradicional.DescomentarDesfazerDesinstalarRequisitos desadequadosCimaActualizarActualizar as dependênciasActualizar ou desinstalarEnviar para %sEnviando %s para %sUse o comando "Parar" se quiser cancelar a depuraçãoVariáveisHistórico de versõesVersão a ser instalada:VerQue interpretador ou dispositivo deve o Thonny usar para executar o seu código?Com o interpretador que está definido, aqui só vai poder consultar os pacotes. Use 'Ferramentas → Abrir terminal do sistema...' para os instalar, actualizar ou desinstalar.Trabalhando...Enrolar o texto (pode ser lento)Agora pode fechar esta janela.Tem que escrever oTem que escolher um ficheiro!O seu interpretador não está na lista?Aumentartodos os ficheirosblá, blábytesnome fiel do pacoteaquiprocure o nome do seu dispositivo, "USB Serial" ou "UART"localização do micro:bit:por favor aguardeexecutável pythonsuporta cores e estilos ANSI básicospara localizar e instalar o ficheiro do pacote (normalmente com extensão .whl, .tar.gz ou .zip).para localizar o ficheiro requirements.txt e instalar os pacotes especificados nele.texto_por_fecharpacotes locais do utilizadorambiente virtualthonny-3.2.7/thonny/locale/pt_PT/LC_MESSAGES/thonny.po0000644000175000017500000012002513611773167023340 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: pt\n" #: thonny/workbench.py:355 msgid "File" msgstr "Ficheiro" #: thonny/workbench.py:356 msgid "Edit" msgstr "Editar" #: thonny/workbench.py:357 msgid "View" msgstr "Ver" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Executar" #: thonny/workbench.py:360 msgid "Tools" msgstr "Ferramentas" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Ajuda" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Interpretador de Python 3 alternativo ou ambiente virtual" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Um ambiente virtual especial (obsoleto)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Sair" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Reduzir tamanho da letra" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Focar editor" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Focar shell" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Maximizar vista" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Ecrã inteiro" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Argumentos do programa" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "Sobre o Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Criado na\n" "Universidade de Tartu, Estonia,\n" "com a ajuda da comunidade de código aberto,\n" "a Fundação Raspberry Pi\n" "e a Cybernetica AS" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Este programa vem\n" "SEM QUALQUER GARANTIA!\n" "É software livre e está à vontade para o\n" "redistribuir sob certas condições. Visite\n" "https://opensource.org/licenses/MIT\n" "para ver os detalhes" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Histórico de versões" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Reportar problemas" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Abrir o Assistente automaticamente quando o programa estoira com uma excepção" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Abrir o Assistente automaticamente quando tiver avisos para o seu código" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Executar as verificações Pylint escolhidas" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Executar verificações MyPy" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Verificações desabilitadas (um id por linha)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Assistente" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Auto-completar" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Que interpretador ou dispositivo deve o Thonny usar para executar o seu código?" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Interpretador" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "Sobre o Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Birdseye é um depurador Python que tem de ser instalado separadamente.\n" "\n" "Quer abrir a página de ajuda e saber mais?" #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Depurar esta listagem (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Comutar comentário" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Comentar" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Descomentar" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Desfazer" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Refazer" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Cortar" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Copiar" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Colar" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Marcar tudo" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Executar até ao cursor" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Ainda não se pode fechar" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Use o comando \"Parar\" se quiser cancelar a depuração" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Fixar as janelas do utilizador" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Realçar nomes iguais" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Realçar variáveis locais" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Realçar parêntesis" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Realçar elementos da sintaxe" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Realçar a linha do cursor (é necessário reiniciar o editor)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Permitir completar código com a tecla Tab nos editores" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Permitir completar código com a tecla Tab na Shell" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Mostrar números de linha" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Comprimento máximo de linha recomendado\n" "(use 0 para desligar a linha de margem)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Editor" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Exportar registo de utilização..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Eventos" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Ficheiros" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Procurar e substituir" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Procurar:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Substituir por:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Diferenciar maiúsculas de minúsculas" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Cima" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Baixo" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Procurar" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Substituir" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Substituir+Procurar" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Substituir tudo" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Escreva o texto a ser substituído." #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "O texto especificado não foi encontrado!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Permitir somente uma instância do Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Reabrir todos os ficheiros da sessão anterior" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Desabilitar som nas notificações" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Modo de dimensionamento do texto" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Modo de Memória 'heap' ligado.\n" "Feche a vista de Memória 'heap' para o desligar." #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Memória 'heap'" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Idioma" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Esta caixa é para os seus rascunhos -- instruções dos trabalhos, exemplos de código, etc.\n" "\n" "Tudo será guardado automaticamente e carregado quando abrir o Thonny da próxima vez.\n" "\n" "Esteja à vontade para apagar este texto e criar espaço para as suas próprias notas." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Notas" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Elemento anterior" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Próximo elemento" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Examinador de elementos" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "Panorama" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Modo Pygame Zero" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Procurar pacotes no PyPi" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Desinstalar" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Fechar" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Clique " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "aqui" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Actualizar" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Instalar" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Não foi possível encontrar o pacote no PyPi." #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "nome fiel do pacote" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Última versão estável" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Última versão" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Sumário" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Autor" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Página inicial" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Rastreador de erros" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Documentação" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "Página no PyPi" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Requer" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Desinstalar mesmo?" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Tem a certeza que o quer desinstalar?" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Voltar ao\n" "quadro presente" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Variáveis" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Este computador" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Refrescar" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Focar em" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Erro" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Tem que escolher um ficheiro!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Sobrepor?" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Quer sobrepor '%s'?" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Novo" #: thonny/code.py:526 msgid "Open..." msgstr "Abrir..." #: thonny/code.py:528 msgid "Load" msgstr "Carregar" #: thonny/code.py:537 msgid "Recent files" msgstr "Ficheiros recentes" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Fechar tudo" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Guardar" #: thonny/code.py:583 msgid "Save as..." msgstr "Guardar como..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Guardar uma cópia..." #: thonny/code.py:603 msgid "Rename..." msgstr "Renomear..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Opções do Thonny" #: thonny/running.py:94 msgid "Run current script" msgstr "Executar esta listagem" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Executar esta listagem num terminal" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Parar/Reiniciar infra-estrutura" #: thonny/running.py:139 msgid "Stop" msgstr "Parar" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Interromper execução" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Enviar EOF / Reinício suave" #: thonny/running.py:172 msgid "Disconnect" msgstr "Desconectar" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Interpretadores conhecidos" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "O seu interpretador não está na lista?" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Localizar outro" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "executável python" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "ATENÇÃO! O Thonny apenas suporta Python 3.5 ou posterior" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Criar um novo ambiente virtual" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "escolha uma pasta existente ou crie uma nova" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Interpretadores Python" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "todos os ficheiros" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Escolha uma pasta vazia para o novo ambiente virtual" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Pasta inválida" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "A pasta escolhida não está vazia.\n" "Escolha outra ou cancele." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Criando o ambiente virtual" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Limpar a shell" #: thonny/shell.py:126 msgid "Plotter" msgstr "Desenhador" #: thonny/shell.py:245 msgid "Clear" msgstr "Limpar" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Mostrar o Desenhador" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Por razões de desempenho, a Shell evita mostrar o excedente das linhas muito longas (ver Ferramentas → Opções → Shell).\n" "Aqui pode interagir com o fragmento de texto original." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "Enrolar o texto (pode ser lento)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Copiar para a área de transferência" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Expandir na Shell" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Texto comprimido (%d caracteres)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "O Desenhador visualiza séries de\n" "números apresentados na Shell." #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Consulte a Ajuda para ver os detalhes." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Fechar os outros" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Copiando" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Copiando\n" " %s\n" "para\n" " %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Cancelar" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "OK" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Cancelar o processo?" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "O processo ainda está a correr.\n" "Tem a certeza que quer cancelar?" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Marcar tudo" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Shell" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "O mesmo interpretador que executa o Thonny (predefinido)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Este ambiente virtual é mantido automaticamente pelo Thonny." #: thonny/workbench.py:532 msgid "Location: " msgstr "Local: " #: thonny/workbench.py:578 msgid "Options..." msgstr "Opções..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Aumentar o tamanho da letra" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Mudar o tamanho da letra" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Aumentar" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Sair do Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "Sair" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "Sobrepondo o tema '%s'" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Argumentos do programa:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Modo normal" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "A configuração foi modificada. Reinicie o Thonny para começar a trabalhar no modo normal.\n" "\n" "(Vá a 'Ferramentas → Opções → Geral' se mais tarde mudar de ideias)." #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Árvore do programa" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Escolher o interpretador" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Retomar" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Executar / retomar" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Depurar esta listagem" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Depurar" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Depurar esta listagem (mais agradável)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Depurar esta listagem (mais rápido)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Saltar por cima" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "Sobre" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "Entrar" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "Entrar" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Sair" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "Sair" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Passo atrás" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Atrás" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Pilha" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Excepção" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Registar eventos de utilização do programa" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Modo de depuração (fornece registos de diagnóstico mais detalhados)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "Modo da interface do utilizador" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "Escala da interface do utilizador" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "ATENÇÃO! Reinicie o Thonny depois de alterar estas opções!" #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Geral" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "INSTALAR" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Consultar os pacotes" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Com o interpretador que está definido, aqui só vai poder consultar os pacotes.\n" "Use 'Ferramentas → Abrir terminal do sistema...' para os instalar, actualizar ou desinstalar." #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Pasta dos pacotes" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Instalar a partir do PyPi" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Se não sabe onde obter os pacotes, o mais certo é que queira procurar no Python Package Index. Comece por escrever o nome do pacote na caixa de pesquisa e carregue em ENTER." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "para localizar o ficheiro requirements.txt e instalar os pacotes especificados nele." #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Clique" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "para localizar e instalar o ficheiro do pacote (normalmente com extensão .whl, .tar.gz ou .zip)." #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Actualizar ou desinstalar" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Comece por escolher o pacote à esquerda." #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Destino:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "ambiente virtual" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "pacotes locais do utilizador" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "Esta janela lista todos os pacotes disponíveis mas apenas permite actualizar e desinstalar os pacotes instalados em" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Pacotes novos serão também instalados nesta pasta. Outras localizações têm de ser geridas por meios alternativos." #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Versão instalada:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Instalado em:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Verifique a ortografia!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "Tem que escrever o" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Não foi possível encontrar a informação do pacote no PyPi" #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Código de erro:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Não foi possível encontrar o nome do pacote na lista:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "O pacote '{}' é necessário para instalar e desinstalar outros pacotes." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Pacote" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Gerir pacotes para %s" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Confirmação" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Parece que está a instalar um pacote relacionado com o Thonny.\n" "Se pretendia instalar um extra do Thonny, então deveria era escolher 'Ferramentas → Gerir extras...'\n" "\n" "Tem a certeza que quer instalar %s para a infra-estrutura?" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "ATENÇÃO! Pode haver outra versão disponível que seja compatível com esta versão do Thonny. Clique no botão '...' para escolher a versão a instalar." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Extra do Thonny sem requisitos" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Parece que está a tentar instalar um extra do Thonny que está obsoleto (não especifica a versão do Thonny que precisa).\n" "\n" "Se mesmo assim o quer, então instale-o a partir da linha de comandos." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Requisitos desadequados" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "Este pacote requer uma versão diferente do Thonny:" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Se mesmo assim o quer, instale-o a partir da linha de comandos." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(neste caso a infra-estrutura do Thonny usa o mesmo interpretador, portanto ambas as janelas gerem os mesmos pacotes)." #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "ATENÇÃO! Tem que reiniciar o Thonny depois de instalar / actualizar / desinstalar um extra." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Extras do Thonny" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Instalação / actualização / desactualização avançada" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Versão desejada" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Actualizar as dependências" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Requer:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Erro:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Gerir pacotes..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Gerir extras..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "Abrir reprodutor..." #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Mudar a pasta de trabalho para a pasta da listagem ao Executar / Depurar" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Mostrar chamadas de funções (quadros) em janelas separadas" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "Desmarque se pretender uma experiência mais tradicional." #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "Abrir e fechar a vista da Pilha automaticamente" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "Abre a vista da Pilha ao ser feita a primeira chamada e fecha-a quando o programa retorna ao quadro principal." #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "Permitir entrar nas bibliotecas (ou seja, tudo o que está fora da pasta da listagem principal)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Pode tornar mais lenta a depuração." #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Depurador preferido" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(usado ao clicar no botão do Depurador na barra de ferramentas)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Porto do birdseye" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(reinicie o Thonny depois de mudar este valor)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Executar e Depurar" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Emulação de terminal" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "suporta cores e estilos ANSI básicos" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Número máximo de linhas a manter." #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "ATENÇÃO! Valores grandes podem comprometer o desempenho!" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Comprimento máximo dos fragmentos de linha antes de comprimir" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Quando executar a listagem corrente no terminal" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Apresentar o REPL do Python depois do programa terminar" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Manter a janela do terminal aberta depois do processo em Python terminar" #: thonny/plugins/terminal_config_page.py:29 msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "ATENÇÃO! O encerramento automático tem que ser habilitado nas configurações do Terminal (Perfis → Shell → Quando a shell encerra)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Terminal" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "Tema da interface" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Tema da sintaxe" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Tipo de letra do editor" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "Tipo de letra de E/S" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Previsão" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "Isto é um comentário" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "A resposta é" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "texto_por_fechar" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "blá, blá" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "ATENÇÃO! Alguns elementos de estilo só mudam depois de reiniciar o Thonny!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Escreva um inteiro" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Tema e Tipo de letra" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Abrir a pasta de programa do Thonny..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Abrir a pasta de dados do Thonny..." #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Início" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Conteúdos da ajuda" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "Dispositivo CircuitPython" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "Dispositivo MicroPython" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Ligue o dispositivo ao computador e escolha o porto correspondente abaixo" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "procure o nome do seu dispositivo, \"USB Serial\" ou \"UART\"" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Se não conseguir encontrá-lo, pode ser necessário instalar primeiro\n" "o controlador USB apropriado." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Porto" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Tentar encontrar o porto automaticamente" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython (genérico)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Imprimir..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Abrir terminal do sistema" #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Detalhes" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Instalar a partir do ficheiro de requisitos" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Instalar a partir de um ficheiro local" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "Esta janela serve para gerir extras do Thonny e as suas dependências.\n" "Se quiser instalar pacotes para os seus próprios programas, use 'Ferramentas → Gerir pacotes...'" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (genérico)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Indentar linhas marcadas" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Desindentar linhas marcadas" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Mudar\n" "para modo\n" "normal" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "Certifique-se que o MicroPython for instalado no seu micro:bit" #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "Não se esqueça que o main.py apenas funciona sem a listagem principal embutida." #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "Instalar o mais recente MicroPython no BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "localização do micro:bit:" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Versão a ser instalada:" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "por favor aguarde" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "ATENÇÃO! Todos os ficheiros no micro:bit vão ser eliminados!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Instalando..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Terminado!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Agora pode fechar esta janela." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Firmware" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "Abrir a janela que instala ou actualiza o MicroPython no seu dispositivo" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "Não foi possível encontrar o disco '%s'." #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "Certifique-se que tem o micro:bit conectado!" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Quer continuar e ser você a localizar o disco?" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "Não foi possível encontrar o disco '%s'. Quer ser você a localizá-lo?" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Foram encontrados vários discos '%s'. Quer escolher um?" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Não foi possível encontrar um disco apropriado" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d itens" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Mover para a Reciclagem" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Mover para o Lixo" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Eliminar" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Nova pasta" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Propriedades" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Espaço de armazenamento" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "Caminho" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Propriedades da pasta" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Propriedades do ficheiro" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "bytes" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "Tamanho" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Modificado" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "Eliminando %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Movendo %s para %s" #: thonny/code.py:203 msgid "Loading" msgstr "Carregando" #: thonny/code.py:297 msgid "Saving" msgstr "Guardando" #: thonny/running.py:1408 msgid "Working..." msgstr "Trabalhando..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Enviando %s para %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Enviar para %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "Descarregando %s para %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Descarregar para %s" thonny-3.2.7/thonny/locale/el_GR/0000755000175000017500000000000013611777205017633 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/el_GR/LC_MESSAGES/0000755000175000017500000000000013611777205021420 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny/locale/el_GR/LC_MESSAGES/thonny.mo0000644000175000017500000011127013611773167023301 0ustar annamaaannamaa00000000000000V ||}]$) *3^ m&z+-!D7b&   x   &);:v     G <%%b*.L3i !! C5N B !6; BN_|    "( 1 > IUg= C O W 0\  6    ! !:!?!H!P!FX!!Cg""""""#+%# Q#_#r# ###3#### $$ $($ 7$B$[$0%z%;^&(&&&& '1' @'a'|'''' ''+'n (,{(0(<()-)U).* 2*n@* ****?*C+Y+t+'+++F+',T/, ,,,, ,,,H,-'---2-F-e--:---&-. ..$.6. I. V. a.k.|... .B... / /&/B/ J/ V/ d/q// /// / /// /"/0 0 +080?0 U0 `02k0/00:0131 910F1w1111-1 1 11 12 2 !2/272 N2[2c2l2 2>202!2 3,3 4+4b435/E5u5@/6p66"666 66670 7 <7F7 K7U7m7p7x77 7727 778(8D-8r8 9 9%9D9V9#q99 9 9999199 ::%1:VW:I::;;/;;;W<0=a= .>O>[o>s>??J?@_@Y A zAA%AA*A-A"BB&B'B2CLICPCC-C.$D:SDD QErEE$EE EEE"F3FESFGGHH*[HH.HFHI;IfIK:JBJJJFJQ:KYKYK@L:L?MOM`MtMM%MFMaN|NlN=N4 Options => Shell). Here you can interact with the original text fragment.Found several '%s' disks. Do you want to choose one yourself?Full screenGeneralHeapHeap mode is on. Close Heap view to turn it off.HelpHelp contentsHighlight current line (requires reopening the editor)Highlight local variablesHighlight matching namesHighlight parenthesesHighlight syntax elementsHomeHomepageINSTALLIO fontIf you can't find it, you may need to install proper USB driver first.If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER.If you still want it, then please install it from the command line.Increase font sizeIndent selected linesInstallInstall from PyPIInstall from local fileInstall from requirements fileInstall latest MicroPython to BBC micro:bitInstalled to:Installed version:Installing ...InterpreterInterrupt executionIntoKeep terminal window open after Python process endsKnown interpretersLanguageLatest stable versionLatest versionLoadLoadingLocate anotherLocation: Log program usage eventsLooks like you are installing a Thonny-related package. If you meant to install a Thonny plugin, then you should choose 'Tools → Manage plugins...' instead Are you sure you want to install %s for the back-end?Looks like you are trying to install an outdated Thonny plug-in (it doesn't specify required Thonny version). If you still want it, then please install it from the command line.Made in University of Tartu, Estonia, with the help from open-source community, Raspberry Pi Foundation and Cybernetica ASMake sure MicroPython has been installed to your micro:bit.Make sure you have micro:bit plugged in!Manage packages for %sManage packages...Manage plug-ins...Maximize viewMaximum length of line fragments before squeezingMaximum number of lines to keep.May make debugging slower.MicroPython (generic)MicroPython deviceModifiedMove to Recycle BinMove to TrashMoving %s to %sNB! All files on micro:bit will be deleted!NB! Automatic closing needs to be enabled in Terminal's settings (Profiles → Shell → When the shell exits)NB! Large values may cause poor performance!NB! Restart Thonny after changing these options!NB! Some style elements change only after restarting Thonny!NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install.NB! Thonny only supports Python 3.5 and laterNB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in.NewNew directoryNew packages will be also installed into this directory. Other locations must be managed by alternative means.Next objectNotesOKObject inspectorOpen Assistant automatically when it has warnings for your codeOpen Assistant automatically when program crashes with an exceptionOpen Thonny data folder...Open Thonny program folder...Open and close Stack view automaticallyOpen replayer...Open system shell...Open the dialog for installing or upgrading MicroPython on your deviceOpen...Opens the Stack view on first call and closes it when program returns to main frame.Options...OutOutlineOverOverwrite?Overwriting theme '%s'PackagePackage '{}' is required for installing and uninstalling other packages.Packages' directoryPastePathPerform MyPy checksPerform selected Pylint checksPlease check your spelling!PlotterPlotter visualizes series of numbers printed to the Shell.PortPreferred debuggerPresent Python REPL after program endsPreviewPrevious objectPrint...Program argumentsProgram arguments:Program treePropertiesPyPI pagePygame Zero modePython interpretersQuitReally uninstall?Recent filesRecommended maximum line length (Set to 0 to turn off margin line)RedoRefreshRegular modeRename...Reopen all files from previous sessionReplaceReplace allReplace with:Replace+FindReport problemsRequiresRequires:ResumeRunRun & DebugRun / resumeRun current scriptRun current script in terminalRun to cursorRunning current script in terminalSaveSave as...Save copy...SavingSee Help for details.Select AllSelect allSelect empty directory for new virtual environmentSelect existing or create a new empty directorySelect interpreterSelected directory is not empty. Select another or cancel.Send EOF / Soft rebootShellShow PlotterShow function calls (frames) in separate windowsShow line numbersSizeSqueezed text (%d characters)StackStart by selecting the package from the left.Step backStep intoStep outStep overStopStop/Restart backendStorage spaceSummarySwitch to regular modeSyntax themeTarget:TerminalTerminal emulationThe answer isThe process is still running. Are you sure you want to cancel?The same interpreter which runs Thonny (default)The specified text was not found!Theme & FontThis box is meant for your working notes -- assignment instructions, code snippets, whatever. Everything will be saved automatically and loaded when you open Thonny next time. Feel free to delete this text to make room for your own notes.This computerThis dialog is for managing Thonny plug-ins and their dependencies. If you want to install packages for your own programs then choose 'Tools → Manage packages...'This dialog lists all available packages, but allows upgrading and uninstalling only packages fromThis is a commentThis package requires different Thonny version:This program comes with ABSOLUTELY NO WARRANTY! It is free software, and you are welcome to redistribute it under certain conditions, see https://opensource.org/licenses/MIT for detailsThis virtual environment is automatically maintained by Thonny. Thonny optionsThonny plug-insThonny plugin without requirementsToggle commentToolsTry to detect port automaticallyUI modeUI scaling factorUI themeUncheck if you want more traditional experience.UncommentUndoUninstallUnsuitable requirementsUpUpgradeUpgrade dependenciesUpgrade or uninstallUpload to %sUploading %s to %sUse "Stop" command if you want to cancel debuggingVariablesVersion historyVersion to be installed:ViewWhich interpreter or device should Thonny use for running your code?With current interpreter you can only browse the packages here. Use 'Tools → Open system shell...' for installing, upgrading or uninstalling.Working...Wrap text (may be slow)You can now close this dialog.You need to enterYou need to select a file!Your interpreter isn't in the list?Zoomall filesblah, blahbytesexact package nameherelook for your device name, "USB Serial" or "UART"micro:bit location:please waitpython executablesupports basic ANSI-colors and stylesto locate and install the package file (usually with .whl, .tar.gz or .zip extension).to locate requirements.txt file and install the packages specified in it.unclosed_stringuser site packagesvirtual environmentMIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: POEditor.com Project-Id-Version: Thonny Language: el %d στοιχεία(Σε αυτήν την περίπτωση, το back-end του Thonny χρησιμοποιεί τον ίδιο διερμηνευτή, επομένως και τα δύο παράθυρα διαχειρίζονται τα ίδια πακέτα.)(επανεκιννήστε το Thonny μετά από αυτήν την αλλαγή)(χρησιμοποιείται όταν κάνετε κλικ στο κουμπί Γραμμή εργαλείων εντοπισμού σφαλμάτων)Ένα ειδικό εικονικό περιβάλλον (μη χρησιμοποιούμενο)Σχετικά με τo BirdseyeΣχετικά με το ThonnyΠροχωρημένη εγκατάσταση / αναβάθμιση / υποβάθμισηΝα επιτρέπεται η συμπλήρωση κώδικα με το πλήκτρο Tab στο κέλυφοςΝα επιτρέπεται η συμπλήρωση κώδικα με το πλήκτρο Tab στον επεξεργαστή κειμένουΝα επιτρέπεται μόνο μία εκτέλεση του ThonnyΝα επιτρέπεται η μετάβαση σε βιβλιοθήκες (π.χ. εκτός του καταλόγου του κύριου προγράμματος)Εναλλακτικό διερμηνευτή Python 3 ή εικονικό περιβάλλονΕίσαι σίγουρος ότι θέλεις να το απεγκαταστήσεις;ΒοηθόςΣυντάκτηςΑυτόματη συμπλήρωσηΠίσωΠίσω στο τρέχoν πλαίσιοΠροβληματικός κατάλογοςΤο Birdseye είναι ένας αποσφαλματωτής της Python που πρέπει να εγκατασταθεί ξεχωριστά.Θύρα BirdseyeΠεριήγηση στα πακέταΑνιχνευτής σφαλμάτωνΔεν μπορεί να κλείσει ακόμηΔεν βρέθηκε το όνομα πακέτου από τη λίστα:Δεν είναι δυνατή η εύρεση κατάλληλου δίσκουΑκύρωσηΑκύρωση της διαδικασίας;Διάκριση πεζών-κεφαλαίωνΑλλαγή μεγέθους γραμματοσειράςΑλλαγή από τον τρέχοντα κατάλογο εργασίας στον κατάλογο του προγράμματος κατά την Eκτέλεση/ΑποσφαλμάτωσηCircuitPython (γενόσημο)Συσκευή CircuitPythonΚαθάρισμαΚαθάρισε το κέλυφοςΚάντε κλικΚλικ ΚλείσιμοΚλείσιμο όλωνΚλείσε τα υπόλοιπαΠροσθήκη σχολίουΟι ρυθμίσεις έχουν ενημερωθεί. Κάντε επανεκκίνηση του Thonny για να αρχίσετε να εργάζεστε σε κανονική λειτουργία. (Δείτε 'Εργαλεία → Επιλογές → Γενικά' αν αλλάξετε γνώμη αργότερα.)ΕπιβεβαίωσηΣυνδέστε τη συσκευή σας στον υπολογιστή και επιλέξτε την αντίστοιχη θύρα παρακάτωΑντιγραφήΑντιγραφή στο πρόχειροΑντιγραφήΑντιγραφή από   %s στο   %sΔεν ήταν δυνατή η εύρεση του δίσκου '%s'.Δεν ήταν δυνατή η εύρεση του δίσκου '%s'. Θέλετε να τον εντοπίσετε μόνοι σας;Αδυναμία εύρεσης πακέτου από PyPl.Δεν ήταν δυνατή η εύρεση των πληροφοριών πακέτου από PyPI.Δημιουργία νέου εικονικού περιβάλλοντοςΔημιουργία εικονικού περιβάλλοντοςΑποκοπήΑποσφαλμάτωσηΑποσφαλμάτωση τρέχοντος προγράμματοςΑποσφαλμάτωση τρέχοντος προγράμματος (birdseye)Αποσφαλμάτωση τρέχοντος προγράμματος (ταχύτερη)Αποσφαλμάτωση τρέχοντος προγράμματος (καλύτερη)Λειτουργία εντοπισμού σφαλμάτων (παρέχει πιο λεπτομερή καταγραφή διαγνωστικών)Μείωση μεγέθους γραμματοσειράςΜείωση εσοχής επιλεγμένων γραμμώνΔιαγραφήΔιαγραφή %sΕπιθυμητή έκδοσηΛεπτομέρειεςΙδιότητες καταλόγουΑπενεργοποίηση ηχητικών ειδοποιήσεωνΑπενεργοποιημένοι έλεγχοι (μία ταυτότητα ανά γραμμή)ΑποσύνδεσηΘέλετε να συνεχίσετε και να εντοπίσετε μόνοι σας τον δίσκο;Θέλεις να αντικαταστήσειςς το '%s';Ενσωμάτωση παραθύρων χρήστηΒιβλιογραφίαΜην ξεχνάτε ότι το main.py λειτουργεί μόνο χωρίς ενσωματωμένο κύριο πρόγραμμα.Ολοκληρώθηκε!ΚάτωΜεταφόρτωση στο %sΛήψη του %s στο %sΕπεξεργασίαΕπεξεργαστής κειμένουΓραμματοσειρά επεξεργαστή κειμένουΠληκτρολογήστε έναν ακέραιο αριθμόΕισάγετε συμβολοσειρά για αντικατάστασηΣφάλμαΚωδικός σφάλματος:Σφάλμα:ΓεγονόταΕξαίρεσηΈξοδοςΈξοδος από το ThonnyΕπέκτεινε το κέλυφοςΕξαγωγή αρχείων καταγραφής χρήσης ...ΑρχείοΙδιότητες αρχείουΑρχείαΕύρεσηΕύρεση & ΑντικατάστασηΕύρεση πακέτου από PyPlΕύρεση:YλικολογισμικόΕστίαση στον επεξεργαστή κειμένουΕστίαση σεΕστίαση στο κέλυφοςΛειτουργία κλιμάκωσης γραμματοσειρώνΓια λόγους απόδοσης, το κέλυφος αποφεύγει να εμφανίζει πλήρως τις μεγάλες γραμμές (βλ. Εργαλεία=> Επιλογές=> Κέλυφος). Εδώ μπορείτε να αλληλεπιδράσετε με το αρχικό κειμένο.Βρέθηκαν διάφοροι δίσκοι '%s'. Θέλετε να επιλέξετε έναν εσείς;Πλήρης οθόνηΓενικάΣωρόςΗ λειτουργία Σωρού είναι ενεργοποιημένη. Κλείστε την προβολή Σωρού για να την απενεργοποιήσετε.ΒοήθειαΠεριεχόμενα ΒοήθειαςΕπισήμανε την τρέχουσα γραμμή (απαιτεί εκ νέου άνοιγμα του επεξεργαστή κειμένου)Επισήμανε τοπικές μεταβλητέςΕπισήμανε ονόματα που ταιριάζουνΕπισήμανε παρανθέσειςΕπισήμανε στοιχεία συντακτικούΑρχικήΑρχική σελίδαΕΓΚΑΤΑΣΤΑΣΗΓραμματοσειρά IOΑν δεν μπορείτε να το βρείτε, ίσως χρειαστεί να εγκαταστήσετε πρώτα τον κατάλληλο οδηγό USB.Εάν δεν γνωρίζετε από πού να κατεβάσετε το πακέτο, τότε κατά πάσα πιθανότητα πρέπει να κάνετε αναζήτηση στον κατάλογο πακέτων Python. Ξεκινήστε εισάγοντας το όνομα του πακέτου στο πλαίσιο αναζήτησης παραπάνω και πατώντας ENTER.Εάν το θέλετε ακόμα, τότε εγκαταστήστε το από τη γραμμή εντολών.Αύξηση μεγέθους γραμματοσειράςΑύξηση εσοχής επιλεγμένων γραμμώνΕγκατάστασηΕγκατάσταση από PyPIΕγκατάσταση από τοπικό αρχείοΕγκατάσταση από το αρχείο προδιαγραφώνΕγκαταστήστε την τελευταία έκδοση MicroPython στο BBC micro:bitΕγκαταστήθηκε σε:Εγκατεστημένη έκδοση:Εγκατάσταση ...ΔιερμηνευτήςΔιακοπή εκτέλεσηςΠρόςΔιατήρησε το τερματικό ανοικτό μετά την ολοκλήρωση της διεργασίας PythonΓνωστοί διερμηνευτέςΓλώσσαΤελευταία σταθερή έκδοσηΤελευταία έκδοσηΦόρτωσηΦόρτωσηΕύρεση άλλουΤοποθεσία:Καταγραφή συμβάντων κατά την χρήση του προγράμματοςΦαίνεται ότι εγκαθιστάτε ένα πακέτο που σχετίζεται με το Thonny. Εάν σκοπεύατε να εγκαταστήσετε ένα πρόσθετο στο Thonny, τότε θα έπρεπε να επιλέξτε "Εργαλεία → Διαχείριση πρόσθετων ..." Είστε βέβαιοι ότι θέλετε να εγκαταστήσετε το %s για το back-end;Φαίνεται ότι προσπαθείτε να εγκαταστήσετε ένα παλιό πρόσθετο του Thonny (δεν καθορίζει την απαιτούμενη έκδοση Thonny). Εάν το θέλετε ακόμα, τότε εγκαταστήστε το από τη γραμμή εντολών.Δημιουργήθηκε στο Πανεπιστήμιο Tartu της Εσθονίας με την βοήθεια της κοινότητας λογισμικού ανοιχτού κώδικα, του Raspberry Pi Foundation και της Cybernetica ASΒεβαιωθείτε ότι το MicroPython έχει εγκατασταθεί στο micro:bit σας.Βεβαιωθείτε ότι έχετε συνδέσει το micro:bit συνδεδεμένο!Διαχείριση πακέτων για %sΔιαχείριση πακέτων ...Διαχείριση προσθέτων...ΜεγιστοποίησηΜέγιστο μήκος τμήματων γραμμής πριν την συμπίεσηΜέγιστος αριθμός διατηρητέων γραμμώνΜπορεί να κάνει την αποσφαλμάτωση πιο αργή.MicroPython (γενόσημο)Συσκευή MicroPythonΤροποποιήθηκεΜετακίνηση στον Κάδο ΑνακύκλωσηςΜετακίνηση στα ΆχρησταΜετακίνηση του %s στο %sΥπενθύμιση! Όλα τα αρχεία σε αυτό το micro:bit θα διαγραφούν!Υπενθύμιση! Το αυτόματο κλείσιμο πρέπει να ενεργοποιηθεί στις ρυθμίσεις του τερματικού (Τερματικό → Προτιμήσεις → Προφίλ → Κέλυφος → Όταν το κέλυφος εξέρχεται)Υπενθύμιση! Μεγάλες τιμές μπορεί να προκαλέσουν αργή απόδοση!Yπενθύμιση! Επανεκκινήστε το Thonny μετά την αλλαγή αυτών των επιλογών!Υπενθύμιση! Ορισμένα στοιχεία στυλ αλλάζουν μόνο μετά την επανεκκίνηση του Thonny!Υπενθύμιση! Μπορεί να υπάρχει άλλη διαθέσιμη έκδοση που είναι συμβατή με την τρέχουσα έκδοση Thonny. Κάντε κλικ στο κουμπί '...' για να επιλέξετε την έκδοση που θα εγκατασταθεί.Υπενθύμιση! Το Thonny υποστηρίζει μόνο Python 3.5 και νεότερη έκδοσηΥπενθύμιση! Πρέπει να κάνετε επανεκκίνηση του Thonny μετά την εγκατάσταση / αναβάθμιση / κατάργηση της εγκατάστασης ενός πρόσθετου.ΝέοΝέος κατάλογοςΝέα πακέτα θα εγκατασταθούν επίσης σε αυτόν τον κατάλογο. Οι άλλες τοποθεσίεςα διαχειρίζονται με εναλλακτικά μέσα.Επόμενο αντικείμενοΣημειώσειςOKΕπιθεωρητής αντικειμένουΆνοιγμα του Βοηθού αυτόματα όταν υπάρχουν προειδοποιήσεις για τον κώδικαΆνοιγμα του Βοηθού αυτόματα όταν το πρόγραμμα τερματιστεί με εξαίρεσηΆνοιξε τον φάκελο δεδομένων του Thonny ...Άνοιξε τον φάκελο προγραμμάτων του Thonny...Αυτόματο άνοιγμα και κλείσιμο της προβολής της ΣτοίβαςΆνοιγμα αναπαραγωγής ...Άνοιξε το κέλυφος συστήματοςΑνοίξτε το παράθυρο διαλόγου για την εγκατάσταση ή την αναβάθμιση του MicroPython στη συσκευή σαςΆνοιγμαΑνοίγει την προβολή στοίβας κατά την πρώτη κλήση και κλείνει όταν το πρόγραμμα επιστρέψει στο κύριο πλαίσιο.Επιλογές...ΈξωΠεριεχόμεναπάνω απόΑντικατάσταση;Αντικατάσταση θέματος '%s'ΠακέτοΤο πακέτο '{}' είναι απαραίτητο για την εγκατάσταση και την απεγκατάσταση άλλων πακέτων.Κατάλογος πακέτωνΕπικόλλησηΜονοπάτιΕκτέλεση ελέγχων MyPyΕκτέλεση των επιλεγμένων ελέγχων PylintΕλέγξτε την ορθογραφία σας!ΣχεδιογράφοςΟ σχεδιαστής απεικονίζει μια σειρά από αριθμούς που εκτυπώνονται στο κέλυφος.ΘύραΠροτιμώμενο πρόγραμμα αποσφαλμάτωσηςΠαρουσίαση του Python REPL μετά το τέλος του προγράμματοςΠροεπισκόπησηΠροηγούμενο αντικείμενοΕκτύπωση...Παράμετροι προγράμματοςΠαράμετροι προγράμματος:Δέντρο ΠρογράμματοςΙδιότητεςΣελίδα PyPlΛειτουργία Pygame ZeroΔιερμηνευτές PythonΤερματισμόςΣίγουρα απεγκατάσταση;Πρόσφατα αρχείαΣυνιστώμενο μέγιστο μήκος γραμμής (Ρυθμίστε στο 0 για να απενεργοποιήσετε τη γραμμή περιθωρίου)ΕπανάληψηΑνανέωσηΚανονική λειτουργίαΜετονομασία...Άνοιγμα όλων των αρχείων από προηγούμενη συνεδρίαΑντικατάστασηΑντικατάσταση όλωνΑντικατάσταση με:Αντικαταστάση+ΕύρεσηΑναφορά προβλήματοςΑπαιτείΑπαιτεί:ΣυνέχειαΕκτέλεσηΕκτέλεση & ΑποσφαλμάτωσηΕκτέλεση / ΣυνέχειαΕκτέλεση τρέχοντος προγράμματοςΕκτέλεση τρέχοντος προγράμματος στο τερματικόEκτέλεση μέχρι τον κέρσοραΤρέχον εκτελέσιμο πρόγραμμα στο τερματικόΑποθήκευσηΑποθήκευση ως...Αποθήκευση αντιγράφου...ΑποθήκευσηΑνατρέξτε στη Βοήθεια για λεπτομέρειες.Επιλογή ΌλωνΕπιλογή όλωνΕπιλέξτε κενό κατάλογο για νέο εικονικό περιβάλλονΕπιλογή υπάρχοντος ή δημιουργία νέου καταλόγουΕπιλογή διερμηνευτήΟ επιλεγμένος κατάλογος δεν είναι κενός. Επιλέξτε άλλο ή ακυρώστε.Αποστολή Τέλους Αρχείου (EOF) / Επανεκκίνηση μέσω λογισμικούΚέλυφοςΕμφάνιση σχεδιογράφουΕμφάνιση κλήσεων συναρτήσεων (πλαισίων) σε ξεχωριστά παράθυραΕμφάνιση αριθμού γραμμώνΜεγέθοςΣυμπιεσμένο κείμενο (%d χαρακτήρες)ΣτοίβαΞεκινήστε επιλέγοντας το πακέτο από τα αριστερά.ΟπισθοδρόμησηΕίσοδοςΈξοδοςΠροσπέραση ΣταμάτημαΣταμάτημα/Επανεκκίνηση backendΧώρος αποθήκευσηςΠερίληψηΑλλαγή σε κανονική λειτουργίαΘεματικό σύνταξηςΣτόχος:ΤερματικόΠροσομοίωση τερματικούΗ απάντηση είναιΗ διεργασία είναι σε εξέλιξη. Είσαι σίγουρος ότι θέλεις να ακυρώσεις;Τον ίδιο διερμηνευτή που χρησιμοποιεί τοThonny (προεπιλογή)Το ζητούμενο κειμενο δεν βρέθηκε!Θεματικό & ΓραμματοσειράΑυτό το πλαίσιο προορίζεται για τις σημειώσεις εργασίας σας - οδηγίες ανάθεσης, αποσπάσματα κώδικα, οτιδήποτε άλλο. Όλα θα αποθηκευτούν αυτόματα και θα φορτωθούν όταν ανοίξετε το Thonny την επόμενη φορά. Διαγράψτε ελεύθερα αυτό το κείμενο για να κάνετε χώρο για τις σημειώσεις σας.Αυτός ο υπολογιστήςΑυτός ο διάλογος είναι για τη διαχείριση των προσθηκών Thonny και των εξαρτήσεων τους. Αν θέλετε να εγκαταστήσετε πακέτα για τα δικά σας προγράμματα, επιλέξτε "Εργαλεία → Διαχείριση πακέτων ..."Αυτό το παράθυρο διαλόγου εμφανίζει όλα τα διαθέσιμα πακέτα, αλλά επιτρέπει την αναβάθμιση και την απεγκατάσταση μόνο των πακέτων απόΑυτό είναι ένα σχόλιοΑυτό το πακέτο απαιτεί διαφορετική έκδοση του Thonny:Αυτό το πρόγραμμα δεν παρέχει ΑΠΟΛΥΤΩΣ ΚΑΜΙΑ ΕΓΓΥΗΣΗ! Είναι ελεύθερο λογισμικό και είστε ευπρόσδεκτοι να το αναδιανείμετε υπό ορισμένες προϋποθέσεις, βλ https://opensource.org/licenses/MIT για λεπτομέρειεςΑυτό το εικονικό περιβάλλον συντηρείται αυτόματα από το Thonny.Επιλογές ThonnyΠρόσθετα του ThonnyΠρόσθετο του Thonny χωρίς προδιαγραφέςΕναλλαγή σχολίουΕργαλείαΠροσπαθήστε να εντοπίσετε αυτόματα τη θύραΛειτουργία UIΠαράγοντας κλιμάκωσης UIΘεματικό UIΑποεπιλέξτε εάν θέλετε μια πιο παραδοσιακή εμπειρία.Αφαίρεση σχολίουΑναίρεσηΑπεγκατάστασηΑκατάλληλες προδιαγραφέςΕπάνωΑναβάθμισηΑναβάθμιση εξαρτήσεωνΑναβάθμιση ή απεγκατάστασηΑνέβασμα στο %sΑνέβασμα του %s στο %sΧρησιμοποίηστε την εντολή "Stop" αν θέλετε να σταματήσετε την αποσφαλμάτωσηΜεταβλητέςΙστορικό έκδοσηςΈκδοση που πρόκειται να εγκατασταθεί:ΠροβολήΠοιον διερμηνευτή ή συσκευή να χρησιμοποιήσει το Thonny για να τρέξει τον κώδικά σου;Με τον τρέχοντα διερμηνευή μπορείτε μόνο να περιηγηθείτε στα πακέτα. Μεταβείτε σε: 'Εργαλεία → Άνοιξε το κέλυφος συστήματος ...' για εγκατάσταση, αναβάθμιση ή απεγκατάσταση.Επεξεργάζεται...Αναδίπλωση κειμένου (ενδέχεται να είναι αργή)Τώρα μπορείτε να κλείσετε αυτό το παράθυρο διάλογου.Πρέπει να εισέλθετεΠρέπει να επιλέξεις ενα αρχείο!Ο διερμηνευτής σου δεν είναι στην λίστα;Μεγέθυνσηόλα τα αρχείαΜπλα, μπλαbytesΑκριβές όνομα πακέτουΕδώαναζητήστε το όνομα της συσκευής σας, "USB Serial" ή "UART"τοποθεσία micro:bitΠαρακαλώ περιμένετεεκτελέσιμο Pythonυποστηρίζει βασικά χρώματα ANSI και στυλγια να εντοπίσετε και να εγκαταστήσετε το πακέτου(συνήθως με επέκταση .whl, .tar.gz ή .zip).για να εντοπίσετε το αρχείο requirements.txt και να εγκαταστήσετε τα πακέτα που ορίζονται από αυτό.ανοιχτή_συμβολοσειράπακέτα ιστότοπου χρήστηεικονικό περιβάλλονthonny-3.2.7/thonny/locale/el_GR/LC_MESSAGES/thonny.po0000644000175000017500000014521513611773167023312 0ustar annamaaannamaa00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: POEditor.com\n" "Project-Id-Version: Thonny\n" "Language: el\n" #: thonny/workbench.py:355 msgid "File" msgstr "Αρχείο" #: thonny/workbench.py:356 msgid "Edit" msgstr "Επεξεργασία" #: thonny/workbench.py:357 msgid "View" msgstr "Προβολή" #: thonny/running.py:95 thonny/workbench.py:358 msgid "Run" msgstr "Εκτέλεση" #: thonny/workbench.py:360 msgid "Tools" msgstr "Εργαλεία" #: thonny/plugins/help/__init__.py:68 thonny/workbench.py:361 msgid "Help" msgstr "Βοήθεια" #: thonny/workbench.py:522 msgid "Alternative Python 3 interpreter or virtual environment" msgstr "Εναλλακτικό διερμηνευτή Python 3 ή εικονικό περιβάλλον" #: thonny/workbench.py:530 msgid "A special virtual environment (deprecated)" msgstr "Ένα ειδικό εικονικό περιβάλλον (μη χρησιμοποιούμενο)" #: thonny/workbench.py:568 msgid "Exit" msgstr "Έξοδος" #: thonny/workbench.py:595 msgid "Decrease font size" msgstr "Μείωση μεγέθους γραμματοσειράς" #: thonny/workbench.py:607 msgid "Focus editor" msgstr "Εστίαση στον επεξεργαστή κειμένου" #: thonny/workbench.py:616 msgid "Focus shell" msgstr "Εστίαση στο κέλυφος" #: thonny/workbench.py:627 msgid "Maximize view" msgstr "Μεγιστοποίηση" #: thonny/workbench.py:639 msgid "Full screen" msgstr "Πλήρης οθόνη" #: thonny/workbench.py:1250 msgid "Program arguments" msgstr "Παράμετροι προγράμματος" #: thonny/plugins/about.py:25 thonny/plugins/about.py:157 msgid "About Thonny" msgstr "Σχετικά με το Thonny" #: thonny/plugins/about.py:77 msgid "Made in\n" "University of Tartu, Estonia,\n" "with the help from\n" "open-source community,\n" "Raspberry Pi Foundation\n" "and Cybernetica AS" msgstr "Δημιουργήθηκε\n" "στο Πανεπιστήμιο Tartu της Εσθονίας\n" "με την βοήθεια της κοινότητας λογισμικού ανοιχτού κώδικα,\n" "του Raspberry Pi Foundation \n" "και της Cybernetica AS" #: thonny/plugins/about.py:103 msgid "This program comes with\n" "ABSOLUTELY NO WARRANTY!\n" "It is free software, and you are welcome to\n" "redistribute it under certain conditions, see\n" "https://opensource.org/licenses/MIT\n" "for details" msgstr "Αυτό το πρόγραμμα δεν παρέχει\n" "ΑΠΟΛΥΤΩΣ ΚΑΜΙΑ ΕΓΓΥΗΣΗ!\n" "Είναι ελεύθερο λογισμικό και είστε ευπρόσδεκτοι\n" "να το αναδιανείμετε υπό ορισμένες προϋποθέσεις, βλ\n" "https://opensource.org/licenses/MIT\n" "για λεπτομέρειες" #: thonny/plugins/about.py:146 msgid "Version history" msgstr "Ιστορικό έκδοσης" #: thonny/plugins/about.py:153 msgid "Report problems" msgstr "Αναφορά προβλήματος" #: thonny/plugins/assistant_config_page.py:15 msgid "Open Assistant automatically when program crashes with an exception" msgstr "Άνοιγμα του Βοηθού αυτόματα όταν το πρόγραμμα τερματιστεί με εξαίρεση" #: thonny/plugins/assistant_config_page.py:21 msgid "Open Assistant automatically when it has warnings for your code" msgstr "Άνοιγμα του Βοηθού αυτόματα όταν υπάρχουν προειδοποιήσεις για τον κώδικα" #: thonny/plugins/assistant_config_page.py:26 msgid "Perform selected Pylint checks" msgstr "Εκτέλεση των επιλεγμένων ελέγχων Pylint" #: thonny/plugins/assistant_config_page.py:29 msgid "Perform MyPy checks" msgstr "Εκτέλεση ελέγχων MyPy" #: thonny/plugins/assistant_config_page.py:31 msgid "Disabled checks (one id per line)" msgstr "Απενεργοποιημένοι έλεγχοι (μία ταυτότητα ανά γραμμή)" #: thonny/assistance.py:962 thonny/plugins/assistant_config_page.py:68 msgid "Assistant" msgstr "Βοηθός" #: thonny/plugins/autocomplete.py:316 msgid "Auto-complete" msgstr "Αυτόματη συμπλήρωση" #: thonny/plugins/backend_config_page.py:43 msgid "Which interpreter or device should Thonny use for running your code?" msgstr "Ποιον διερμηνευτή ή συσκευή να χρησιμοποιήσει το Thonny για να τρέξει τον κώδικά σου;" #: thonny/plugins/backend_config_page.py:127 msgid "Interpreter" msgstr "Διερμηνευτής" #: thonny/plugins/birdseye_frontend.py:32 msgid "About Birdseye" msgstr "Σχετικά με τo Birdseye" #: thonny/plugins/birdseye_frontend.py:33 msgid "Birdseye is a Python debugger which needs to be installed separately.\n" "\n" "Do you want to open the help page and learn more?" msgstr "Το Birdseye είναι ένας αποσφαλματωτής της Python που πρέπει να εγκατασταθεί ξεχωριστά." #: thonny/plugins/birdseye_frontend.py:60 msgid "Debug current script (birdseye)" msgstr "Αποσφαλμάτωση τρέχοντος προγράμματος (birdseye)" #: thonny/plugins/commenting_indenting.py:143 msgid "Toggle comment" msgstr "Εναλλαγή σχολίου" #: thonny/plugins/commenting_indenting.py:153 msgid "Comment out" msgstr "Προσθήκη σχολίου" #: thonny/plugins/commenting_indenting.py:163 msgid "Uncomment" msgstr "Αφαίρεση σχολίου" #: thonny/plugins/common_editing_commands.py:20 msgid "Undo" msgstr "Αναίρεση" #: thonny/plugins/common_editing_commands.py:32 msgid "Redo" msgstr "Επανάληψη" #: thonny/plugins/common_editing_commands.py:48 thonny/ui_utils.py:2176 msgid "Cut" msgstr "Αποκοπή" #: thonny/plugins/common_editing_commands.py:60 thonny/ui_utils.py:2177 msgid "Copy" msgstr "Αντιγραφή" #: thonny/plugins/common_editing_commands.py:72 thonny/ui_utils.py:2178 msgid "Paste" msgstr "Επικόλληση" #: thonny/plugins/common_editing_commands.py:84 thonny/plugins/debugger.py:124 msgid "Select all" msgstr "Επιλογή όλων" #: thonny/plugins/debugger.py:117 thonny/plugins/debugger.py:1276 msgid "Run to cursor" msgstr "Eκτέλεση μέχρι τον κέρσορα" #: thonny/plugins/debugger.py:863 msgid "Can't close yet" msgstr "Δεν μπορεί να κλείσει ακόμη" #: thonny/plugins/debugger.py:864 msgid "Use \"Stop\" command if you want to cancel debugging" msgstr "Χρησιμοποίηστε την εντολή \"Stop\" αν θέλετε να σταματήσετε την αποσφαλμάτωση" #: thonny/plugins/dock_user_windows_frontend.py:27 msgid "Dock user windows" msgstr "Ενσωμάτωση παραθύρων χρήστη" #: thonny/plugins/editor_config_page.py:14 msgid "Highlight matching names" msgstr "Επισήμανε ονόματα που ταιριάζουν" #: thonny/plugins/editor_config_page.py:20 msgid "Highlight local variables" msgstr "Επισήμανε τοπικές μεταβλητές" #: thonny/plugins/editor_config_page.py:25 msgid "Highlight parentheses" msgstr "Επισήμανε παρανθέσεις" #: thonny/plugins/editor_config_page.py:26 msgid "Highlight syntax elements" msgstr "Επισήμανε στοιχεία συντακτικού" #: thonny/plugins/editor_config_page.py:29 msgid "Highlight current line (requires reopening the editor)" msgstr "Επισήμανε την τρέχουσα γραμμή (απαιτεί εκ νέου άνοιγμα του επεξεργαστή κειμένου)" #: thonny/plugins/editor_config_page.py:34 msgid "Allow code completion with Tab-key in editors" msgstr "Να επιτρέπεται η συμπλήρωση κώδικα με το πλήκτρο Tab στον επεξεργαστή κειμένου" #: thonny/plugins/editor_config_page.py:40 msgid "Allow code completion with Tab-key in Shell" msgstr "Να επιτρέπεται η συμπλήρωση κώδικα με το πλήκτρο Tab στο κέλυφος" #: thonny/plugins/editor_config_page.py:44 msgid "Show line numbers" msgstr "Εμφάνιση αριθμού γραμμών" #: thonny/plugins/editor_config_page.py:47 msgid "Recommended maximum line length\n" "(Set to 0 to turn off margin line)" msgstr "Συνιστώμενο μέγιστο μήκος γραμμής\n" "(Ρυθμίστε στο 0 για να απενεργοποιήσετε τη γραμμή περιθωρίου)" #: thonny/plugins/editor_config_page.py:68 msgid "Editor" msgstr "Επεξεργαστής κειμένου" #: thonny/plugins/event_logging.py:197 msgid "Export usage logs..." msgstr "Εξαγωγή αρχείων καταγραφής χρήσης ..." #: thonny/plugins/event_view.py:38 msgid "Events" msgstr "Γεγονότα" #: thonny/plugins/files.py:307 msgid "Files" msgstr "Αρχεία" #: thonny/plugins/find_replace.py:56 thonny/plugins/find_replace.py:412 msgid "Find & Replace" msgstr "Εύρεση & Αντικατάσταση" #: thonny/plugins/find_replace.py:62 msgid "Find:" msgstr "Εύρεση:" #: thonny/plugins/find_replace.py:73 msgid "Replace with:" msgstr "Αντικατάσταση με:" #: thonny/plugins/find_replace.py:91 msgid "Case sensitive" msgstr "Διάκριση πεζών-κεφαλαίων" #: thonny/plugins/find_replace.py:98 msgid "Up" msgstr "Επάνω" #: thonny/plugins/find_replace.py:102 msgid "Down" msgstr "Κάτω" #: thonny/plugins/find_replace.py:111 msgid "Find" msgstr "Εύρεση" #: thonny/plugins/find_replace.py:121 msgid "Replace" msgstr "Αντικατάσταση" #: thonny/plugins/find_replace.py:129 msgid "Replace+Find" msgstr "Αντικαταστάση+Εύρεση" #: thonny/plugins/find_replace.py:138 msgid "Replace all" msgstr "Αντικατάσταση όλων" #: thonny/plugins/find_replace.py:232 msgid "Enter string to be replaced." msgstr "Εισάγετε συμβολοσειρά για αντικατάσταση" #: thonny/plugins/find_replace.py:316 msgid "The specified text was not found!" msgstr "Το ζητούμενο κειμενο δεν βρέθηκε!" #: thonny/plugins/general_config_page.py:13 msgid "Allow only single Thonny instance" msgstr "Να επιτρέπεται μόνο μία εκτέλεση του Thonny" #: thonny/plugins/general_config_page.py:20 msgid "Reopen all files from previous session" msgstr "Άνοιγμα όλων των αρχείων από προηγούμενη συνεδρία" #: thonny/plugins/general_config_page.py:26 msgid "Disable notification sound" msgstr "Απενεργοποίηση ηχητικών ειδοποιήσεων" #: thonny/plugins/general_config_page.py:75 msgid "Font scaling mode" msgstr "Λειτουργία κλιμάκωσης γραμματοσειρών" #: thonny/plugins/heap.py:35 msgid "Heap mode is on.\n" "Close Heap view to turn it off." msgstr "Η λειτουργία Σωρού είναι ενεργοποιημένη.\n" "Κλείστε την προβολή Σωρού για να την απενεργοποιήσετε." #: thonny/plugins/heap.py:83 msgid "Heap" msgstr "Σωρός" #: thonny/plugins/general_config_page.py:42 msgid "Language" msgstr "Γλώσσα" #: thonny/plugins/notes.py:33 msgid "This box is meant for your working notes -- assignment instructions, code snippets, whatever.\n" "\n" "Everything will be saved automatically and loaded when you open Thonny next time.\n" "\n" "Feel free to delete this text to make room for your own notes." msgstr "Αυτό το πλαίσιο προορίζεται για τις σημειώσεις εργασίας σας - οδηγίες ανάθεσης, αποσπάσματα κώδικα, οτιδήποτε άλλο.\n" "\n" "Όλα θα αποθηκευτούν αυτόματα και θα φορτωθούν όταν ανοίξετε το Thonny την επόμενη φορά.\n" "\n" "Διαγράψτε ελεύθερα αυτό το κείμενο για να κάνετε χώρο για τις σημειώσεις σας." #: thonny/plugins/notes.py:61 msgid "Notes" msgstr "Σημειώσεις" #: thonny/plugins/object_inspector.py:108 msgid "Previous object" msgstr "Προηγούμενο αντικείμενο" #: thonny/plugins/object_inspector.py:111 msgid "Next object" msgstr "Επόμενο αντικείμενο" #: thonny/plugins/object_inspector.py:601 msgid "Object inspector" msgstr "Επιθεωρητής αντικειμένου" #: thonny/plugins/outline.py:137 msgid "Outline" msgstr "Περιεχόμενα" #: thonny/plugins/pgzero_frontend.py:26 msgid "Pygame Zero mode" msgstr "Λειτουργία Pygame Zero" #: thonny/plugins/pip_gui.py:78 msgid "Find package from PyPI" msgstr "Εύρεση πακέτου από PyPl" #: thonny/plugins/pip_gui.py:188 thonny/plugins/pip_gui.py:190 msgid "Uninstall" msgstr "Απεγκατάσταση" #: thonny/code.py:548 thonny/plugins/microbit/__init__.py:200 #: thonny/plugins/pip_gui.py:204 thonny/running.py:1457 thonny/ui_utils.py:367 #: thonny/ui_utils.py:1643 msgid "Close" msgstr "Κλείσιμο" #: thonny/plugins/pip_gui.py:382 msgid "Click " msgstr "Κλικ " #: thonny/plugins/pip_gui.py:383 thonny/plugins/pip_gui.py:393 msgid "here" msgstr "Εδώ" #: thonny/plugins/pip_gui.py:181 thonny/plugins/pip_gui.py:478 msgid "Upgrade" msgstr "Αναβάθμιση" #: thonny/plugins/microbit/__init__.py:123 thonny/plugins/pip_gui.py:483 #: thonny/plugins/pip_gui.py:1064 msgid "Install" msgstr "Εγκατάσταση" #: thonny/plugins/pip_gui.py:505 msgid "Could not find the package from PyPI." msgstr "Αδυναμία εύρεσης πακέτου από PyPl." #: thonny/plugins/pip_gui.py:515 msgid "exact package name" msgstr "Ακριβές όνομα πακέτου" #: thonny/plugins/pip_gui.py:533 msgid "Latest stable version" msgstr "Τελευταία σταθερή έκδοση" #: thonny/plugins/pip_gui.py:535 msgid "Latest version" msgstr "Τελευταία έκδοση" #: thonny/plugins/pip_gui.py:536 msgid "Summary" msgstr "Περίληψη" #: thonny/plugins/pip_gui.py:537 msgid "Author" msgstr "Συντάκτης" #: thonny/plugins/pip_gui.py:538 msgid "Homepage" msgstr "Αρχική σελίδα" #: thonny/plugins/pip_gui.py:540 msgid "Bugtracker" msgstr "Ανιχνευτής σφαλμάτων" #: thonny/plugins/pip_gui.py:542 msgid "Documentation" msgstr "Βιβλιογραφία" #: thonny/plugins/pip_gui.py:544 msgid "PyPI page" msgstr "Σελίδα PyPl" #: thonny/plugins/pip_gui.py:548 msgid "Requires" msgstr "Απαιτεί" #: thonny/plugins/pip_gui.py:614 msgid "Really uninstall?" msgstr "Σίγουρα απεγκατάσταση;" #: thonny/plugins/pip_gui.py:619 msgid "Are you sure you want to uninstall it?" msgstr "Είσαι σίγουρος ότι θέλεις να το απεγκαταστήσεις;" #: thonny/plugins/variables.py:19 msgid "Back to\n" "current frame" msgstr "Πίσω στο τρέχoν πλαίσιο" #: thonny/plugins/variables.py:131 msgid "Variables" msgstr "Μεταβλητές" #: thonny/base_file_browser.py:30 msgid "This computer" msgstr "Αυτός ο υπολογιστής" #: thonny/base_file_browser.py:568 msgid "Refresh" msgstr "Ανανέωση" #: thonny/base_file_browser.py:572 msgid "Focus into" msgstr "Εστίαση σε" #: thonny/base_file_browser.py:1001 msgid "Error" msgstr "Σφάλμα" #: thonny/base_file_browser.py:1001 msgid "You need to select a file!" msgstr "Πρέπει να επιλέξεις ενα αρχείο!" #: thonny/base_file_browser.py:1005 msgid "Overwrite?" msgstr "Αντικατάσταση;" #: thonny/base_file_browser.py:1005 msgid "Do you want to overwrite '%s' ?" msgstr "Θέλεις να αντικαταστήσειςς το '%s';" #: thonny/code.py:513 thonny/code.py:515 msgid "New" msgstr "Νέο" #: thonny/code.py:526 msgid "Open..." msgstr "Άνοιγμα" #: thonny/code.py:528 msgid "Load" msgstr "Φόρτωση" #: thonny/code.py:537 msgid "Recent files" msgstr "Πρόσφατα αρχεία" #: thonny/code.py:559 thonny/ui_utils.py:369 msgid "Close all" msgstr "Κλείσιμο όλων" #: thonny/code.py:569 thonny/code.py:571 msgid "Save" msgstr "Αποθήκευση" #: thonny/code.py:583 msgid "Save as..." msgstr "Αποθήκευση ως..." #: thonny/code.py:594 msgid "Save copy..." msgstr "Αποθήκευση αντιγράφου..." #: thonny/code.py:603 msgid "Rename..." msgstr "Μετονομασία..." #: thonny/config_ui.py:17 msgid "Thonny options" msgstr "Επιλογές Thonny" #: thonny/running.py:94 msgid "Run current script" msgstr "Εκτέλεση τρέχοντος προγράμματος" #: thonny/running.py:125 msgid "Run current script in terminal" msgstr "Εκτέλεση τρέχοντος προγράμματος στο τερματικό" #: thonny/running.py:138 msgid "Stop/Restart backend" msgstr "Σταμάτημα/Επανεκκίνηση backend" #: thonny/running.py:139 msgid "Stop" msgstr "Σταμάτημα" #: thonny/running.py:150 msgid "Interrupt execution" msgstr "Διακοπή εκτέλεσης" #: thonny/running.py:161 msgid "Send EOF / Soft reboot" msgstr "Αποστολή Τέλους Αρχείου (EOF) / Επανεκκίνηση μέσω λογισμικού" #: thonny/running.py:172 msgid "Disconnect" msgstr "Αποσύνδεση" #: thonny/running_config_page.py:23 msgid "Known interpreters" msgstr "Γνωστοί διερμηνευτές" #: thonny/running_config_page.py:36 msgid "Your interpreter isn't in the list?" msgstr "Ο διερμηνευτής σου δεν είναι στην λίστα;" #: thonny/running_config_page.py:43 msgid "Locate another" msgstr "Εύρεση άλλου" #: thonny/running_config_page.py:45 msgid "python executable" msgstr "εκτελέσιμο Python" #: thonny/running_config_page.py:47 msgid "NB! Thonny only supports Python 3.5 and later" msgstr "Υπενθύμιση! Το Thonny υποστηρίζει μόνο Python 3.5 και νεότερη έκδοση" #: thonny/running_config_page.py:56 msgid "Create new virtual environment" msgstr "Δημιουργία νέου εικονικού περιβάλλοντος" #: thonny/running_config_page.py:59 msgid "Select existing or create a new empty directory" msgstr "Επιλογή υπάρχοντος ή δημιουργία νέου καταλόγου" #: thonny/running_config_page.py:74 msgid "Python interpreters" msgstr "Διερμηνευτές Python" #: thonny/plugins/pip_gui.py:657 thonny/plugins/pip_gui.py:669 #: thonny/running_config_page.py:75 msgid "all files" msgstr "όλα τα αρχεία" #: thonny/running_config_page.py:89 msgid "Select empty directory for new virtual environment" msgstr "Επιλέξτε κενό κατάλογο για νέο εικονικό περιβάλλον" #: thonny/running_config_page.py:96 msgid "Bad directory" msgstr "Προβληματικός κατάλογος" #: thonny/running_config_page.py:97 msgid "Selected directory is not empty.\n" "Select another or cancel." msgstr "Ο επιλεγμένος κατάλογος δεν είναι κενός.\n" "Επιλέξτε άλλο ή ακυρώστε." #: thonny/running_config_page.py:112 msgid "Creating virtual environment" msgstr "Δημιουργία εικονικού περιβάλλοντος" #: thonny/shell.py:72 msgid "Clear shell" msgstr "Καθάρισε το κέλυφος" #: thonny/shell.py:126 msgid "Plotter" msgstr "Σχεδιογράφος" #: thonny/shell.py:245 msgid "Clear" msgstr "Καθάρισμα" #: thonny/shell.py:258 msgid "Show Plotter" msgstr "Εμφάνιση σχεδιογράφου" #: thonny/shell.py:1389 msgid "For performance reasons, Shell avoids showing very long lines in full (see Tools => Options => Shell).\n" "Here you can interact with the original text fragment." msgstr "Για λόγους απόδοσης, το κέλυφος αποφεύγει να εμφανίζει πλήρως τις μεγάλες γραμμές (βλ. Εργαλεία=> Επιλογές=> Κέλυφος).\n" "Εδώ μπορείτε να αλληλεπιδράσετε με το αρχικό κειμένο." #: thonny/shell.py:1400 msgid "Wrap text (may be slow)" msgstr "Αναδίπλωση κειμένου (ενδέχεται να είναι αργή)" #: thonny/shell.py:1425 thonny/ui_utils.py:1639 msgid "Copy to clipboard" msgstr "Αντιγραφή στο πρόχειρο" #: thonny/shell.py:1431 msgid "Expand in Shell" msgstr "Επέκτεινε το κέλυφος" #: thonny/shell.py:1442 msgid "Squeezed text (%d characters)" msgstr "Συμπιεσμένο κείμενο (%d χαρακτήρες)" #: thonny/shell.py:1611 msgid "Plotter visualizes series of\n" "numbers printed to the Shell." msgstr "Ο σχεδιαστής απεικονίζει μια σειρά από\n" "αριθμούς που εκτυπώνονται στο κέλυφος." #: thonny/shell.py:1613 msgid "See Help for details." msgstr "Ανατρέξτε στη Βοήθεια για λεπτομέρειες." #: thonny/ui_utils.py:368 msgid "Close others" msgstr "Κλείσε τα υπόλοιπα" #: thonny/ui_utils.py:1499 msgid "Copying" msgstr "Αντιγραφή" #: thonny/ui_utils.py:1502 msgid "Copying\n" " %s\n" "to\n" " %s" msgstr "Αντιγραφή από\n" "  %s\n" "στο\n" "  %s" #: thonny/config_ui.py:31 thonny/plugins/microbit/__init__.py:127 #: thonny/plugins/pip_gui.py:1066 thonny/running.py:1424 #: thonny/ui_utils.py:1510 thonny/ui_utils.py:1712 msgid "Cancel" msgstr "Ακύρωση" #: thonny/config_ui.py:30 thonny/ui_utils.py:1764 msgid "OK" msgstr "OK" #: thonny/ui_utils.py:1783 msgid "Cancel the process?" msgstr "Ακύρωση της διαδικασίας;" #: thonny/ui_utils.py:1784 msgid "The process is still running.\n" "Are you sure you want to cancel?" msgstr "Η διεργασία είναι σε εξέλιξη.\n" "Είσαι σίγουρος ότι θέλεις να ακυρώσεις;" #: thonny/ui_utils.py:2182 msgid "Select All" msgstr "Επιλογή Όλων" #: thonny/plugins/shell_config_page.py:61 thonny/workbench.py:162 msgid "Shell" msgstr "Κέλυφος" #: thonny/workbench.py:512 msgid "The same interpreter which runs Thonny (default)" msgstr "Τον ίδιο διερμηνευτή που χρησιμοποιεί τοThonny (προεπιλογή)" #: thonny/workbench.py:531 msgid "This virtual environment is automatically maintained by Thonny.\n" "" msgstr "Αυτό το εικονικό περιβάλλον συντηρείται αυτόματα από το Thonny." #: thonny/workbench.py:532 msgid "Location: " msgstr "Τοποθεσία:" #: thonny/workbench.py:578 msgid "Options..." msgstr "Επιλογές..." #: thonny/workbench.py:585 msgid "Increase font size" msgstr "Αύξηση μεγέθους γραμματοσειράς" #: thonny/workbench.py:650 msgid "Change font size" msgstr "Αλλαγή μεγέθους γραμματοσειράς" #: thonny/workbench.py:651 msgid "Zoom" msgstr "Μεγέθυνση" #: thonny/workbench.py:660 msgid "Exit Thonny" msgstr "Έξοδος από το Thonny" #: thonny/workbench.py:663 msgid "Quit" msgstr "Τερματισμός" #: thonny/workbench.py:1054 thonny/workbench.py:1062 msgid "Overwriting theme '%s'" msgstr "Αντικατάσταση θέματος '%s'" #: thonny/workbench.py:1221 msgid "Program arguments:" msgstr "Παράμετροι προγράμματος:" #: thonny/workbench.py:1275 msgid "Regular mode" msgstr "Κανονική λειτουργία" #: thonny/workbench.py:1276 msgid "Configuration has been updated. Restart Thonny to start working in regular mode.\n" "\n" "(See 'Tools → Options → General' if you change your mind later.)" msgstr "Οι ρυθμίσεις έχουν ενημερωθεί. Κάντε επανεκκίνηση του Thonny για να αρχίσετε να εργάζεστε σε κανονική λειτουργία.\n" "\n" "(Δείτε 'Εργαλεία → Επιλογές → Γενικά' αν αλλάξετε γνώμη αργότερα.)" #: thonny/plugins/ast_view.py:209 msgid "Program tree" msgstr "Δέντρο Προγράμματος" #: thonny/plugins/backend_config_page.py:130 msgid "Select interpreter" msgstr "Επιλογή διερμηνευτή" #: thonny/plugins/debugger.py:1162 msgid "Resume" msgstr "Συνέχεια" #: thonny/plugins/debugger.py:1174 msgid "Run / resume" msgstr "Εκτέλεση / Συνέχεια" #: thonny/plugins/debugger.py:1189 msgid "Debug current script" msgstr "Αποσφαλμάτωση τρέχοντος προγράμματος" #: thonny/plugins/debugger.py:1191 msgid "Debug" msgstr "Αποσφαλμάτωση" #: thonny/plugins/debugger.py:1202 msgid "Debug current script (nicer)" msgstr "Αποσφαλμάτωση τρέχοντος προγράμματος (καλύτερη)" #: thonny/plugins/debugger.py:1214 msgid "Debug current script (faster)" msgstr "Αποσφαλμάτωση τρέχοντος προγράμματος (ταχύτερη)" #: thonny/plugins/debugger.py:1225 msgid "Step over" msgstr "Προσπέραση\n" "" #: thonny/plugins/debugger.py:1227 msgid "Over" msgstr "πάνω από" #: thonny/plugins/debugger.py:1238 msgid "Step into" msgstr "Είσοδος" #: thonny/plugins/debugger.py:1240 msgid "Into" msgstr "Πρός" #: thonny/plugins/debugger.py:1251 msgid "Step out" msgstr "Έξοδος" #: thonny/plugins/debugger.py:1253 msgid "Out" msgstr "Έξω" #: thonny/plugins/debugger.py:1288 msgid "Step back" msgstr "Οπισθοδρόμηση" #: thonny/plugins/debugger.py:1290 msgid "Back" msgstr "Πίσω" #: thonny/plugins/debugger.py:1296 msgid "Stack" msgstr "Στοίβα" #: thonny/plugins/debugger.py:1297 msgid "Exception" msgstr "Εξαίρεση" #: thonny/plugins/general_config_page.py:16 msgid "Log program usage events" msgstr "Καταγραφή συμβάντων κατά την χρήση του προγράμματος" #: thonny/plugins/general_config_page.py:32 msgid "Debug mode (provides more detailed diagnostic logs)" msgstr "Λειτουργία εντοπισμού σφαλμάτων (παρέχει πιο λεπτομερή καταγραφή διαγνωστικών)" #: thonny/plugins/general_config_page.py:56 msgid "UI mode" msgstr "Λειτουργία UI" #: thonny/plugins/general_config_page.py:69 msgid "UI scaling factor" msgstr "Παράγοντας κλιμάκωσης UI" #: thonny/plugins/general_config_page.py:88 msgid "NB! Restart Thonny after changing these options!" msgstr "Yπενθύμιση! Επανεκκινήστε το Thonny μετά την αλλαγή αυτών των επιλογών!" #. αλλαγή 1/11 #: thonny/plugins/general_config_page.py:102 msgid "General" msgstr "Γενικά" #: thonny/plugins/pip_gui.py:108 msgid "INSTALL" msgstr "ΕΓΚΑΤΑΣΤΑΣΗ" #: thonny/plugins/pip_gui.py:352 msgid "Browse the packages" msgstr "Περιήγηση στα πακέτα" #: thonny/plugins/pip_gui.py:355 msgid "With current interpreter you can only browse the packages here.\n" "Use 'Tools → Open system shell...' for installing, upgrading or uninstalling." msgstr "Με τον τρέχοντα διερμηνευή μπορείτε μόνο να περιηγηθείτε στα πακέτα.\n" "Μεταβείτε σε: 'Εργαλεία → Άνοιξε το κέλυφος συστήματος ...' για εγκατάσταση, αναβάθμιση ή απεγκατάσταση." #: thonny/plugins/pip_gui.py:363 msgid "Packages' directory" msgstr "Κατάλογος πακέτων" #: thonny/plugins/pip_gui.py:368 msgid "Install from PyPI" msgstr "Εγκατάσταση από PyPI" #: thonny/plugins/pip_gui.py:371 msgid "If you don't know where to get the package from, then most likely you'll want to search the Python Package Index. Start by entering the name of the package in the search box above and pressing ENTER." msgstr "Εάν δεν γνωρίζετε από πού να κατεβάσετε το πακέτο, τότε κατά πάσα πιθανότητα πρέπει να κάνετε αναζήτηση στον κατάλογο πακέτων Python. Ξεκινήστε εισάγοντας το όνομα του πακέτου στο πλαίσιο αναζήτησης παραπάνω και πατώντας ENTER." #: thonny/plugins/pip_gui.py:387 msgid "to locate requirements.txt file and install the packages specified in it." msgstr "για να εντοπίσετε το αρχείο requirements.txt και να εγκαταστήσετε τα πακέτα που ορίζονται από αυτό." #: thonny/plugins/pip_gui.py:392 msgid "Click" msgstr "Κάντε κλικ" #: thonny/plugins/pip_gui.py:397 msgid "to locate and install the package file (usually with .whl, .tar.gz or .zip extension)." msgstr "για να εντοπίσετε και να εγκαταστήσετε το πακέτου(συνήθως με επέκταση .whl, .tar.gz ή .zip)." #: thonny/plugins/pip_gui.py:403 msgid "Upgrade or uninstall" msgstr "Αναβάθμιση ή απεγκατάσταση" #: thonny/plugins/pip_gui.py:405 msgid "Start by selecting the package from the left." msgstr "Ξεκινήστε επιλέγοντας το πακέτο από τα αριστερά." #: thonny/plugins/pip_gui.py:409 msgid "Target:" msgstr "Στόχος:" #: thonny/plugins/pip_gui.py:412 msgid "virtual environment" msgstr "εικονικό περιβάλλον" #: thonny/plugins/pip_gui.py:416 msgid "user site packages" msgstr "πακέτα ιστότοπου χρήστη" #: thonny/plugins/pip_gui.py:421 msgid "This dialog lists all available packages, but allows upgrading and uninstalling only packages from" msgstr "Αυτό το παράθυρο διαλόγου εμφανίζει όλα τα διαθέσιμα πακέτα, αλλά επιτρέπει την αναβάθμιση και την απεγκατάσταση μόνο των πακέτων από" #: thonny/plugins/pip_gui.py:431 msgid "New packages will be also installed into this directory. Other locations must be managed by alternative means." msgstr "Νέα πακέτα θα εγκατασταθούν επίσης σε αυτόν τον κατάλογο. Οι άλλες τοποθεσίεςα διαχειρίζονται με εναλλακτικά μέσα." #: thonny/plugins/pip_gui.py:456 msgid "Installed version:" msgstr "Εγκατεστημένη έκδοση:" #: thonny/plugins/pip_gui.py:458 msgid "Installed to:" msgstr "Εγκαταστήθηκε σε:" #: thonny/plugins/pip_gui.py:510 msgid "Please check your spelling!" msgstr "Ελέγξτε την ορθογραφία σας!" #: thonny/plugins/pip_gui.py:512 msgid "You need to enter" msgstr "Πρέπει να εισέλθετε" #: thonny/plugins/pip_gui.py:520 msgid "Could not find the package info from PyPI." msgstr "Δεν ήταν δυνατή η εύρεση των πληροφοριών πακέτου από PyPI." #: thonny/plugins/pip_gui.py:522 thonny/plugins/pip_gui.py:1120 msgid "Error code:" msgstr "Κωδικός σφάλματος:" #: thonny/plugins/pip_gui.py:581 msgid "Can't find package name from the list:" msgstr "Δεν βρέθηκε το όνομα πακέτου από τη λίστα:" #: thonny/plugins/pip_gui.py:615 msgid "Package '{}' is required for installing and uninstalling other packages." msgstr "Το πακέτο '{}' είναι απαραίτητο για την εγκατάσταση και την απεγκατάσταση άλλων πακέτων." #: thonny/plugins/pip_gui.py:657 msgid "Package" msgstr "Πακέτο" #: thonny/plugins/pip_gui.py:757 msgid "Manage packages for %s" msgstr "Διαχείριση πακέτων για %s" #: thonny/plugins/pip_gui.py:813 msgid "Confirmation" msgstr "Επιβεβαίωση" #: thonny/plugins/pip_gui.py:814 msgid "Looks like you are installing a Thonny-related package.\n" "If you meant to install a Thonny plugin, then you should\n" "choose 'Tools → Manage plugins...' instead\n" "\n" "Are you sure you want to install %s for the back-end?" msgstr "Φαίνεται ότι εγκαθιστάτε ένα πακέτο που σχετίζεται με το Thonny.\n" "Εάν σκοπεύατε να εγκαταστήσετε ένα πρόσθετο στο Thonny, τότε \n" "θα έπρεπε να επιλέξτε \"Εργαλεία → Διαχείριση πρόσθετων ...\"\n" "\n" "Είστε βέβαιοι ότι θέλετε να εγκαταστήσετε το %s για το back-end;" #: thonny/plugins/pip_gui.py:912 msgid "NB! There may be another version available which is compatible with current Thonny version. Click on '...' button to choose the version to install." msgstr "Υπενθύμιση! Μπορεί να υπάρχει άλλη διαθέσιμη έκδοση που είναι συμβατή με την τρέχουσα έκδοση Thonny. Κάντε κλικ στο κουμπί '...' για να επιλέξετε την έκδοση που θα εγκατασταθεί." #: thonny/plugins/pip_gui.py:920 msgid "Thonny plugin without requirements" msgstr "Πρόσθετο του Thonny χωρίς προδιαγραφές" #: thonny/plugins/pip_gui.py:921 msgid "Looks like you are trying to install an outdated Thonny\n" "plug-in (it doesn't specify required Thonny version).\n" "\n" "If you still want it, then please install it from the command line." msgstr "Φαίνεται ότι προσπαθείτε να εγκαταστήσετε ένα παλιό πρόσθετο\n" "του Thonny (δεν καθορίζει την απαιτούμενη έκδοση Thonny).\n" "\n" "Εάν το θέλετε ακόμα, τότε εγκαταστήστε το από τη γραμμή εντολών." #: thonny/plugins/pip_gui.py:935 msgid "Unsuitable requirements" msgstr "Ακατάλληλες προδιαγραφές" #: thonny/plugins/pip_gui.py:936 msgid "This package requires different Thonny version:" msgstr "Αυτό το πακέτο απαιτεί διαφορετική έκδοση του Thonny:" #: thonny/plugins/pip_gui.py:940 msgid "If you still want it, then please install it from the command line." msgstr "Εάν το θέλετε ακόμα, τότε εγκαταστήστε το από τη γραμμή εντολών." #: thonny/plugins/pip_gui.py:984 msgid "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)" msgstr "(Σε αυτήν την περίπτωση, το back-end του Thonny χρησιμοποιεί τον ίδιο διερμηνευτή, επομένως και τα δύο παράθυρα διαχειρίζονται τα ίδια πακέτα.)" #: thonny/plugins/pip_gui.py:990 msgid "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in." msgstr "Υπενθύμιση! Πρέπει να κάνετε επανεκκίνηση του Thonny μετά την εγκατάσταση / αναβάθμιση / κατάργηση της εγκατάστασης ενός πρόσθετου." #: thonny/plugins/pip_gui.py:1000 msgid "Thonny plug-ins" msgstr "Πρόσθετα του Thonny" #: thonny/plugins/pip_gui.py:1013 msgid "Advanced install / upgrade / downgrade" msgstr "Προχωρημένη εγκατάσταση / αναβάθμιση / υποβάθμιση" #: thonny/plugins/pip_gui.py:1022 msgid "Desired version" msgstr "Επιθυμητή έκδοση" #: thonny/plugins/pip_gui.py:1060 msgid "Upgrade dependencies" msgstr "Αναβάθμιση εξαρτήσεων" #: thonny/plugins/pip_gui.py:1118 msgid "Requires:" msgstr "Απαιτεί:" #: thonny/plugins/pip_gui.py:1122 msgid "Error:" msgstr "Σφάλμα:" #: thonny/plugins/pip_gui.py:1232 msgid "Manage packages..." msgstr "Διαχείριση πακέτων ..." #: thonny/plugins/pip_gui.py:1238 msgid "Manage plug-ins..." msgstr "Διαχείριση προσθέτων..." #: thonny/plugins/replayer.py:354 msgid "Open replayer..." msgstr "Άνοιγμα αναπαραγωγής ..." #: thonny/plugins/run_debug_config_page.py:12 msgid "Change working directory to script directory on Run / Debug" msgstr "Αλλαγή από τον τρέχοντα κατάλογο εργασίας στον κατάλογο του προγράμματος κατά την Eκτέλεση/Αποσφαλμάτωση" #: thonny/plugins/run_debug_config_page.py:20 msgid "Show function calls (frames) in separate windows" msgstr "Εμφάνιση κλήσεων συναρτήσεων (πλαισίων) σε ξεχωριστά παράθυρα" #: thonny/plugins/run_debug_config_page.py:21 msgid "Uncheck if you want more traditional experience." msgstr "Αποεπιλέξτε εάν θέλετε μια πιο παραδοσιακή εμπειρία." #: thonny/plugins/run_debug_config_page.py:27 msgid "Open and close Stack view automatically" msgstr "Αυτόματο άνοιγμα και κλείσιμο της προβολής της Στοίβας" #: thonny/plugins/run_debug_config_page.py:28 msgid "Opens the Stack view on first call and closes it when program returns to main frame." msgstr "Ανοίγει την προβολή στοίβας κατά την πρώτη κλήση και κλείνει όταν το πρόγραμμα επιστρέψει στο κύριο πλαίσιο." #: thonny/plugins/run_debug_config_page.py:37 msgid "Allow stepping into libraries (ie. outside of main script directory)" msgstr "Να επιτρέπεται η μετάβαση σε βιβλιοθήκες (π.χ. εκτός του καταλόγου του κύριου προγράμματος)" #: thonny/plugins/run_debug_config_page.py:38 msgid "May make debugging slower." msgstr "Μπορεί να κάνει την αποσφαλμάτωση πιο αργή." #: thonny/plugins/run_debug_config_page.py:43 msgid "Preferred debugger" msgstr "Προτιμώμενο πρόγραμμα αποσφαλμάτωσης" #: thonny/plugins/run_debug_config_page.py:55 msgid "(used when clicking Debug toolbar button)" msgstr "(χρησιμοποιείται όταν κάνετε κλικ στο κουμπί Γραμμή εργαλείων εντοπισμού σφαλμάτων)" #: thonny/plugins/run_debug_config_page.py:60 msgid "Birdseye port" msgstr "Θύρα Birdseye" #: thonny/plugins/run_debug_config_page.py:64 msgid "(restart Thonny after changing this)" msgstr "(επανεκιννήστε το Thonny μετά από αυτήν την αλλαγή)" #: thonny/plugins/run_debug_config_page.py:72 msgid "Run & Debug" msgstr "Εκτέλεση & Αποσφαλμάτωση" #: thonny/plugins/shell_config_page.py:16 msgid "Terminal emulation" msgstr "Προσομοίωση τερματικού" #: thonny/plugins/shell_config_page.py:18 msgid "supports basic ANSI-colors and styles" msgstr "υποστηρίζει βασικά χρώματα ANSI και στυλ" #: thonny/plugins/shell_config_page.py:30 msgid "Maximum number of lines to keep." msgstr "Μέγιστος αριθμός διατηρητέων γραμμών" #: thonny/plugins/shell_config_page.py:32 msgid "NB! Large values may cause poor performance!" msgstr "Υπενθύμιση! Μεγάλες τιμές μπορεί να προκαλέσουν αργή απόδοση!" #: thonny/plugins/shell_config_page.py:47 msgid "Maximum length of line fragments before squeezing" msgstr "Μέγιστο μήκος τμήματων γραμμής πριν την συμπίεση" #: thonny/plugins/terminal_config_page.py:10 msgid "Running current script in terminal" msgstr "Τρέχον εκτελέσιμο πρόγραμμα στο τερματικό" #: thonny/plugins/terminal_config_page.py:15 msgid "Present Python REPL after program ends" msgstr "Παρουσίαση του Python REPL μετά το τέλος του προγράμματος" #: thonny/plugins/terminal_config_page.py:22 msgid "Keep terminal window open after Python process ends" msgstr "Διατήρησε το τερματικό ανοικτό μετά την ολοκλήρωση της διεργασίας Python" #: thonny/plugins/terminal_config_page.py:29 #, fuzzy msgid "NB! Automatic closing needs to be enabled in Terminal's settings\n" "(Profiles → Shell → When the shell exits)" msgstr "Υπενθύμιση! Το αυτόματο κλείσιμο πρέπει να ενεργοποιηθεί στις ρυθμίσεις του τερματικού\n" "(Τερματικό → Προτιμήσεις → Προφίλ → Κέλυφος → Όταν το κέλυφος εξέρχεται)" #: thonny/plugins/terminal_config_page.py:38 msgid "Terminal" msgstr "Τερματικό" #: thonny/plugins/theme_and_font_config_page.py:39 msgid "UI theme" msgstr "Θεματικό UI" #: thonny/plugins/theme_and_font_config_page.py:52 msgid "Syntax theme" msgstr "Θεματικό σύνταξης" #: thonny/plugins/theme_and_font_config_page.py:84 msgid "Editor font" msgstr "Γραμματοσειρά επεξεργαστή κειμένου" #: thonny/plugins/theme_and_font_config_page.py:107 msgid "IO font" msgstr "Γραμματοσειρά IO" #: thonny/plugins/theme_and_font_config_page.py:132 msgid "Preview" msgstr "Προεπισκόπηση" #: thonny/plugins/theme_and_font_config_page.py:144 msgid "This is a comment" msgstr "Αυτό είναι ένα σχόλιο" #: thonny/plugins/theme_and_font_config_page.py:147 msgid "The answer is" msgstr "Η απάντηση είναι" #: thonny/plugins/theme_and_font_config_page.py:151 msgid "unclosed_string" msgstr "ανοιχτή_συμβολοσειρά" #: thonny/plugins/theme_and_font_config_page.py:153 msgid "blah, blah" msgstr "Μπλα, μπλα" #: thonny/plugins/theme_and_font_config_page.py:176 msgid "NB! Some style elements change only after restarting Thonny!" msgstr "Υπενθύμιση! Ορισμένα στοιχεία στυλ αλλάζουν μόνο μετά την επανεκκίνηση του Thonny!" #: thonny/plugins/theme_and_font_config_page.py:215 msgid "Enter an integer" msgstr "Πληκτρολογήστε έναν ακέραιο αριθμό" #: thonny/plugins/theme_and_font_config_page.py:228 msgid "Theme & Font" msgstr "Θεματικό & Γραμματοσειρά" #: thonny/plugins/thonny_folders.py:18 msgid "Open Thonny program folder..." msgstr "Άνοιξε τον φάκελο προγραμμάτων του Thonny..." #: thonny/plugins/thonny_folders.py:23 msgid "Open Thonny data folder..." msgstr "Άνοιξε τον φάκελο δεδομένων του Thonny ..." #: thonny/plugins/help/__init__.py:58 msgid "Home" msgstr "Αρχική" #: thonny/plugins/help/__init__.py:69 msgid "Help contents" msgstr "Περιεχόμενα Βοήθειας" #: thonny/plugins/micropython/__init__.py:175 msgid "CircuitPython device" msgstr "Συσκευή CircuitPython" #: thonny/plugins/micropython/__init__.py:179 msgid "MicroPython device" msgstr "Συσκευή MicroPython" #: thonny/plugins/micropython/__init__.py:191 msgid "Connect your device to the computer and select corresponding port below" msgstr "Συνδέστε τη συσκευή σας στον υπολογιστή και επιλέξτε την αντίστοιχη θύρα παρακάτω" #: thonny/plugins/micropython/__init__.py:194 msgid "look for your device name, \"USB Serial\" or \"UART\"" msgstr "αναζητήστε το όνομα της συσκευής σας, \"USB Serial\" ή \"UART\"" #: thonny/plugins/micropython/__init__.py:196 msgid "If you can't find it, you may need to install proper USB driver first." msgstr "Αν δεν μπορείτε να το βρείτε, ίσως χρειαστεί να εγκαταστήσετε πρώτα τον κατάλληλο οδηγό USB." #: thonny/plugins/micropython/__init__.py:220 msgid "Port" msgstr "Θύρα" #: thonny/plugins/micropython/__init__.py:229 msgid "Try to detect port automatically" msgstr "Προσπαθήστε να εντοπίσετε αυτόματα τη θύρα" #: thonny/plugins/micropython/__init__.py:417 msgid "MicroPython (generic)" msgstr "MicroPython (γενόσημο)" #: thonny/plugins/printing/__init__.py:79 msgid "Print..." msgstr "Εκτύπωση..." #: thonny/plugins/system_shell/__init__.py:59 msgid "Open system shell..." msgstr "Άνοιξε το κέλυφος συστήματος" #: thonny/plugins/backend_config_page.py:61 msgid "Details" msgstr "Λεπτομέρειες" #: thonny/plugins/pip_gui.py:380 msgid "Install from requirements file" msgstr "Εγκατάσταση από το αρχείο προδιαγραφών" #: thonny/plugins/pip_gui.py:391 msgid "Install from local file" msgstr "Εγκατάσταση από τοπικό αρχείο" #: thonny/plugins/pip_gui.py:970 msgid "This dialog is for managing Thonny plug-ins and their dependencies.\n" "If you want to install packages for your own programs then choose 'Tools → Manage packages...'" msgstr "Αυτός ο διάλογος είναι για τη διαχείριση των προσθηκών Thonny και των εξαρτήσεων τους.\n" "Αν θέλετε να εγκαταστήσετε πακέτα για τα δικά σας προγράμματα, επιλέξτε \"Εργαλεία → Διαχείριση πακέτων ...\"" #: thonny/plugins/circuitpython/__init__.py:47 msgid "CircuitPython (generic)" msgstr "CircuitPython (γενόσημο)" #: thonny/plugins/commenting_indenting.py:123 msgid "Indent selected lines" msgstr "Αύξηση εσοχής επιλεγμένων γραμμών" #: thonny/plugins/commenting_indenting.py:133 msgid "Dedent selected lines" msgstr "Μείωση εσοχής επιλεγμένων γραμμών" #: thonny/workbench.py:1264 msgid "Switch to\n" "regular\n" "mode" msgstr "Αλλαγή σε\n" "κανονική\n" "λειτουργία" #: thonny/plugins/microbit/__init__.py:54 msgid "Make sure MicroPython has been installed to your micro:bit." msgstr "Βεβαιωθείτε ότι το MicroPython έχει εγκατασταθεί στο micro:bit σας." #: thonny/plugins/microbit/__init__.py:56 msgid "Don't forget that main.py only works without embedded main script." msgstr "Μην ξεχνάτε ότι το main.py λειτουργεί μόνο χωρίς ενσωματωμένο κύριο πρόγραμμα." #: thonny/plugins/microbit/__init__.py:102 msgid "Install latest MicroPython to BBC micro:bit" msgstr "Εγκαταστήστε την τελευταία έκδοση MicroPython στο BBC micro:bit" #: thonny/plugins/microbit/__init__.py:104 msgid "micro:bit location:" msgstr "τοποθεσία micro:bit" #: thonny/plugins/microbit/__init__.py:109 msgid "Version to be installed:" msgstr "Έκδοση που πρόκειται να εγκατασταθεί:" #: thonny/plugins/microbit/__init__.py:111 msgid "please wait" msgstr "Παρακαλώ περιμένετε" #: thonny/plugins/microbit/__init__.py:115 msgid "NB! All files on micro:bit will be deleted!" msgstr "Υπενθύμιση! Όλα τα αρχεία σε αυτό το micro:bit θα διαγραφούν!" #: thonny/plugins/microbit/__init__.py:195 msgid "Installing ..." msgstr "Εγκατάσταση ..." #: thonny/plugins/microbit/__init__.py:199 msgid "Done!" msgstr "Ολοκληρώθηκε!" #: thonny/plugins/microbit/__init__.py:199 msgid "You can now close this dialog." msgstr "Τώρα μπορείτε να κλείσετε αυτό το παράθυρο διάλογου." #: thonny/plugins/micropython/__init__.py:298 msgid "Firmware" msgstr "Yλικολογισμικό" #: thonny/plugins/micropython/__init__.py:301 msgid "Open the dialog for installing or upgrading MicroPython on your device" msgstr "Ανοίξτε το παράθυρο διαλόγου για την εγκατάσταση ή την αναβάθμιση του MicroPython στη συσκευή σας" #: thonny/plugins/microbit/__init__.py:67 msgid "Could not find disk '%s'." msgstr "Δεν ήταν δυνατή η εύρεση του δίσκου '%s'." #: thonny/plugins/microbit/__init__.py:69 msgid "Make sure you have micro:bit plugged in!" msgstr "Βεβαιωθείτε ότι έχετε συνδέσει το micro:bit συνδεδεμένο!" #: thonny/plugins/microbit/__init__.py:71 msgid "Do you want to continue and locate the disk yourself?" msgstr "Θέλετε να συνεχίσετε και να εντοπίσετε μόνοι σας τον δίσκο;" #: thonny/misc_utils.py:120 msgid "Could not find disk '%s'. Do you want to locate it yourself?" msgstr "Δεν ήταν δυνατή η εύρεση του δίσκου '%s'. Θέλετε να τον εντοπίσετε μόνοι σας;" #: thonny/misc_utils.py:123 msgid "Found several '%s' disks. Do you want to choose one yourself?" msgstr "Βρέθηκαν διάφοροι δίσκοι '%s'. Θέλετε να επιλέξετε έναν εσείς;" #: thonny/misc_utils.py:137 msgid "Can't find suitable disk" msgstr "Δεν είναι δυνατή η εύρεση κατάλληλου δίσκου" #: thonny/base_file_browser.py:259 msgid "%d items" msgstr "%d στοιχεία" #: thonny/base_file_browser.py:581 msgid "Move to Recycle Bin" msgstr "Μετακίνηση στον Κάδο Ανακύκλωσης" #: thonny/base_file_browser.py:583 msgid "Move to Trash" msgstr "Μετακίνηση στα Άχρηστα" #: thonny/base_file_browser.py:586 msgid "Delete" msgstr "Διαγραφή" #: thonny/base_file_browser.py:589 msgid "New directory" msgstr "Νέος κατάλογος" #: thonny/base_file_browser.py:592 msgid "Properties" msgstr "Ιδιότητες" #: thonny/base_file_browser.py:593 msgid "Storage space" msgstr "Χώρος αποθήκευσης" #: thonny/base_file_browser.py:603 msgid "Path" msgstr "Μονοπάτι" #: thonny/base_file_browser.py:605 msgid "Directory properties" msgstr "Ιδιότητες καταλόγου" #: thonny/base_file_browser.py:607 msgid "File properties" msgstr "Ιδιότητες αρχείου" #: thonny/base_file_browser.py:609 msgid "bytes" msgstr "bytes" #: thonny/base_file_browser.py:612 msgid "Size" msgstr "Μεγέθος" #: thonny/base_file_browser.py:623 msgid "Modified" msgstr "Τροποποιήθηκε" #: thonny/base_file_browser.py:679 msgid "Deleting %s" msgstr "Διαγραφή %s" #: thonny/base_file_browser.py:701 msgid "Moving %s to %s" msgstr "Μετακίνηση του %s στο %s" #: thonny/code.py:203 msgid "Loading" msgstr "Φόρτωση" #: thonny/code.py:297 msgid "Saving" msgstr "Αποθήκευση" #: thonny/running.py:1408 msgid "Working..." msgstr "Επεξεργάζεται..." #: thonny/plugins/files.py:199 msgid "Uploading %s to %s" msgstr "Ανέβασμα του %s στο %s" #: thonny/plugins/files.py:206 msgid "Upload to %s" msgstr "Ανέβασμα στο %s" #: thonny/plugins/files.py:261 msgid "Downloading %s to %s" msgstr "Λήψη του %s στο %s" #: thonny/plugins/files.py:267 msgid "Download to %s" msgstr "Μεταφόρτωση στο %s" thonny-3.2.7/thonny/ui_utils.py0000644000175000017500000022453713611773167017633 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import collections import logging import os import platform import re import shutil import signal import subprocess import textwrap import threading import time import tkinter as tk import tkinter.font import traceback from tkinter import filedialog, messagebox, ttk from typing import Callable, List, Optional, Tuple, Union # @UnusedImport from thonny import get_workbench, misc_utils, tktextext from thonny.common import TextRange from thonny.misc_utils import ( running_on_linux, running_on_mac_os, running_on_windows, running_on_rpi, ) from thonny.tktextext import TweakableText import sys from _tkinter import TclError import webbrowser from thonny.languages import get_button_padding PARENS_REGEX = re.compile(r"[\(\)\{\}\[\]]") class CommonDialog(tk.Toplevel): def __init__(self, master=None, cnf={}, **kw): super().__init__(master=master, cnf=cnf, **kw) self.bind("", self._unlock_on_focus_in, True) def _unlock_on_focus_in(self, event): if not self.winfo_ismapped(): focussed_widget = self.focus_get() self.deiconify() if focussed_widget: focussed_widget.focus_set() class CommonDialogEx(CommonDialog): def __init__(self, master=None, cnf={}, **kw): super().__init__(master=master, cnf=cnf, **kw) # Need to fill the dialog with a frame to gain theme support self.main_frame = ttk.Frame(self) self.main_frame.grid(row=0, column=0, sticky="nsew") self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.bind("", self.on_close, True) self.protocol("WM_DELETE_WINDOW", self.on_close) def on_close(self, event=None): self.destroy() class CustomMenubar(ttk.Frame): def __init__(self, master): ttk.Frame.__init__(self, master, style="CustomMenubar.TFrame") self._menus = [] self._opened_menu = None ttk.Style().map( "CustomMenubarLabel.TLabel", background=[ ("!active", lookup_style_option("Menubar", "background", "gray")), ("active", lookup_style_option("Menubar", "activebackground", "LightYellow")), ], foreground=[ ("!active", lookup_style_option("Menubar", "foreground", "black")), ("active", lookup_style_option("Menubar", "activeforeground", "black")), ], ) def add_cascade(self, label, menu): label_widget = ttk.Label( self, style="CustomMenubarLabel.TLabel", text=label, padding=[6, 3, 6, 2], font="TkDefaultFont", ) if len(self._menus) == 0: padx = (6, 0) else: padx = 0 label_widget.grid(row=0, column=len(self._menus), padx=padx) def enter(event): label_widget.state(("active",)) # Don't know how to open this menu when another menu is open # another tk_popup just doesn't work unless old menu is closed by click or Esc # https://stackoverflow.com/questions/38081470/is-there-a-way-to-know-if-tkinter-optionmenu-dropdown-is-active # unpost doesn't work in Win and Mac: https://www.tcl.tk/man/tcl8.5/TkCmd/menu.htm#M62 # print("ENTER", menu, self._opened_menu) if self._opened_menu is not None: self._opened_menu.unpost() click(event) def leave(event): label_widget.state(("!active",)) def click(event): try: # print("Before") self._opened_menu = menu menu.tk_popup( label_widget.winfo_rootx(), label_widget.winfo_rooty() + label_widget.winfo_height(), ) finally: # print("After") self._opened_menu = None label_widget.bind("", enter, True) label_widget.bind("", leave, True) label_widget.bind("<1>", click, True) self._menus.append(menu) class AutomaticPanedWindow(tk.PanedWindow): """ Enables inserting panes according to their position_key-s. Automatically adds/removes itself to/from its master AutomaticPanedWindow. Fixes some style glitches. """ def __init__(self, master, position_key=None, preferred_size_in_pw=None, **kwargs): tk.PanedWindow.__init__(self, master, **kwargs) self._pane_minsize = 100 self.position_key = position_key self._restoring_pane_sizes = False self._last_window_size = (0, 0) self._full_size_not_final = True self._configure_binding = self.bind("", self._on_window_resize, True) self._update_appearance_binding = self.bind( "<>", self._update_appearance, True ) self.bind("", self._on_mouse_dragged, True) self._update_appearance() # should be in the end, so that it can be detected when # constructor hasn't completed yet self.preferred_size_in_pw = preferred_size_in_pw def insert(self, pos, child, **kw): kw.setdefault("minsize", self._pane_minsize) if pos == "auto": # According to documentation I should use self.panes() # but this doesn't return expected widgets for sibling in sorted( self.pane_widgets(), key=lambda p: p.position_key if hasattr(p, "position_key") else 0, ): if ( not hasattr(sibling, "position_key") or sibling.position_key == None or sibling.position_key > child.position_key ): pos = sibling break else: pos = "end" if isinstance(pos, tk.Widget): kw["before"] = pos self.add(child, **kw) def add(self, child, **kw): kw.setdefault("minsize", self._pane_minsize) tk.PanedWindow.add(self, child, **kw) self._update_visibility() self._check_restore_preferred_sizes() def remove(self, child): tk.PanedWindow.remove(self, child) self._update_visibility() self._check_restore_preferred_sizes() def forget(self, child): tk.PanedWindow.forget(self, child) self._update_visibility() self._check_restore_preferred_sizes() def destroy(self): self.unbind("", self._configure_binding) self.unbind("<>", self._update_appearance_binding) tk.PanedWindow.destroy(self) def is_visible(self): if not isinstance(self.master, AutomaticPanedWindow): return self.winfo_ismapped() else: return self in self.master.pane_widgets() def pane_widgets(self): result = [] for pane in self.panes(): # pane is not the widget but some kind of reference object assert not isinstance(pane, tk.Widget) result.append(self.nametowidget(str(pane))) return result def _on_window_resize(self, event): if event.width < 10 or event.height < 10: return window = self.winfo_toplevel() window_size = (window.winfo_width(), window.winfo_height()) initializing = hasattr(window, "initializing") and window.initializing if ( not initializing and not self._restoring_pane_sizes and (window_size != self._last_window_size or self._full_size_not_final) ): self._check_restore_preferred_sizes() self._last_window_size = window_size def _on_mouse_dragged(self, event): if event.widget == self and not self._restoring_pane_sizes: self._update_preferred_sizes() def _update_preferred_sizes(self): for pane in self.pane_widgets(): if getattr(pane, "preferred_size_in_pw", None) is not None: if self.cget("orient") == "horizontal": current_size = pane.winfo_width() else: current_size = pane.winfo_height() if current_size > 20: pane.preferred_size_in_pw = current_size # paneconfig width/height effectively puts # unexplainable maxsize to some panes # if self.cget("orient") == "horizontal": # self.paneconfig(pane, width=current_size) # else: # self.paneconfig(pane, height=current_size) # # else: # self.paneconfig(pane, width=1000, height=1000) def _check_restore_preferred_sizes(self): window = self.winfo_toplevel() if getattr(window, "initializing", False): return try: self._restoring_pane_sizes = True self._restore_preferred_sizes() finally: self._restoring_pane_sizes = False def _restore_preferred_sizes(self): total_preferred_size = 0 panes_without_preferred_size = [] panes = self.pane_widgets() for pane in panes: if not hasattr(pane, "preferred_size_in_pw"): # child isn't fully constructed yet return if pane.preferred_size_in_pw is None: panes_without_preferred_size.append(pane) # self.paneconfig(pane, width=1000, height=1000) else: total_preferred_size += pane.preferred_size_in_pw # Without updating pane width/height attribute # the preferred size may lose effect when squeezing # non-preferred panes too small. Also zooming/unzooming # changes the supposedly fixed panes ... # # but # paneconfig width/height effectively puts # unexplainable maxsize to some panes # if self.cget("orient") == "horizontal": # self.paneconfig(pane, width=pane.preferred_size_in_pw) # else: # self.paneconfig(pane, height=pane.preferred_size_in_pw) assert len(panes_without_preferred_size) <= 1 size = self._get_size() if size is None: return leftover_size = self._get_size() - total_preferred_size used_size = 0 for i, pane in enumerate(panes[:-1]): used_size += pane.preferred_size_in_pw or leftover_size self._place_sash(i, used_size) used_size += int(str(self.cget("sashwidth"))) def _get_size(self): if self.cget("orient") == tk.HORIZONTAL: result = self.winfo_width() else: result = self.winfo_height() if result < 20: # Not ready yet return None else: return result def _place_sash(self, i, distance): if self.cget("orient") == tk.HORIZONTAL: self.sash_place(i, distance, 0) else: self.sash_place(i, 0, distance) def _update_visibility(self): if not isinstance(self.master, AutomaticPanedWindow): return if len(self.panes()) == 0 and self.is_visible(): self.master.forget(self) if len(self.panes()) > 0 and not self.is_visible(): self.master.insert("auto", self) def _update_appearance(self, event=None): self.configure(sashwidth=lookup_style_option("Sash", "sashthickness", 10)) self.configure(background=lookup_style_option("TPanedWindow", "background")) class ClosableNotebook(ttk.Notebook): def __init__(self, master, style="ButtonNotebook.TNotebook", **kw): super().__init__(master, style=style, **kw) self.tab_menu = self.create_tab_menu() self._popup_index = None self.pressed_index = None self.bind("", self._letf_btn_press, True) self.bind("", self._left_btn_release, True) if running_on_mac_os(): self.bind("", self._right_btn_press, True) self.bind("", self._right_btn_press, True) else: self.bind("", self._right_btn_press, True) # self._check_update_style() def create_tab_menu(self): menu = tk.Menu(self.winfo_toplevel(), tearoff=False, **get_style_configuration("Menu")) menu.add_command(label=_("Close"), command=self._close_tab_from_menu) menu.add_command(label=_("Close others"), command=self._close_other_tabs) menu.add_command(label=_("Close all"), command=self.close_tabs) return menu def _letf_btn_press(self, event): try: elem = self.identify(event.x, event.y) index = self.index("@%d,%d" % (event.x, event.y)) if "closebutton" in elem: self.state(["pressed"]) self.pressed_index = index except Exception: # may fail, if clicked outside of tab return def _left_btn_release(self, event): if not self.instate(["pressed"]): return try: elem = self.identify(event.x, event.y) index = self.index("@%d,%d" % (event.x, event.y)) except Exception: # may fail, when mouse is dragged return else: if "closebutton" in elem and self.pressed_index == index: self.close_tab(index) self.state(["!pressed"]) finally: self.pressed_index = None def _right_btn_press(self, event): try: index = self.index("@%d,%d" % (event.x, event.y)) self._popup_index = index self.tab_menu.tk_popup(*self.winfo_toplevel().winfo_pointerxy()) except Exception: logging.exception("Opening tab menu") def _close_tab_from_menu(self): self.close_tab(self._popup_index) def _close_other_tabs(self): self.close_tabs(self._popup_index) def close_tabs(self, except_index=None): for tab_index in reversed(range(len(self.winfo_children()))): if except_index is not None and tab_index == except_index: continue else: self.close_tab(tab_index) def close_tab(self, index): child = self.get_child_by_index(index) if hasattr(child, "close"): child.close() else: self.forget(index) child.destroy() def get_child_by_index(self, index): tab_id = self.tabs()[index] if tab_id: return self.nametowidget(tab_id) else: return None def get_current_child(self): child_id = self.select() if child_id: return self.nametowidget(child_id) else: return None def focus_set(self): editor = self.get_current_child() if editor: editor.focus_set() else: super().focus_set() def _check_update_style(self): style = ttk.Style() if "closebutton" in style.element_names(): # It's done already return # respect if required images have been defined already if "img_close" not in self.image_names(): img_dir = os.path.join(os.path.dirname(__file__), "res") ClosableNotebook._close_img = tk.PhotoImage( "img_tab_close", file=os.path.join(img_dir, "tab_close.gif") ) ClosableNotebook._close_active_img = tk.PhotoImage( "img_tab_close_active", file=os.path.join(img_dir, "tab_close_active.gif") ) style.element_create( "closebutton", "image", "img_tab_close", ("active", "pressed", "!disabled", "img_tab_close_active"), ("active", "!disabled", "img_tab_close_active"), border=8, sticky="", ) style.layout( "ButtonNotebook.TNotebook.Tab", [ ( "Notebook.tab", { "sticky": "nswe", "children": [ ( "Notebook.padding", { "side": "top", "sticky": "nswe", "children": [ ( "Notebook.focus", { "side": "top", "sticky": "nswe", "children": [ ( "Notebook.label", {"side": "left", "sticky": ""}, ), ( "Notebook.closebutton", {"side": "left", "sticky": ""}, ), ], }, ) ], }, ) ], }, ) ], ) def _check_remove_padding(self, kw): # Windows themes produce 1-pixel padding to the bottom of the pane # Don't know how to get rid of it using themes if "padding" not in kw and ttk.Style().theme_use().lower() in ( "windows", "xpnative", "vista", ): kw["padding"] = (0, 0, 0, -1) def add(self, child, **kw): self._check_remove_padding(kw) super().add(child, **kw) def insert(self, pos, child, **kw): self._check_remove_padding(kw) super().insert(pos, child, **kw) class AutomaticNotebook(ClosableNotebook): """ Enables inserting views according to their position keys. Remember its own position key. Automatically updates its visibility. """ def __init__(self, master, position_key, preferred_size_in_pw=None): if get_workbench().in_simple_mode(): style = "TNotebook" else: style = "ButtonNotebook.TNotebook" super().__init__(master, style=style, padding=0) self.position_key = position_key # should be in the end, so that it can be detected when # constructor hasn't completed yet self.preferred_size_in_pw = preferred_size_in_pw def add(self, child, **kw): super().add(child, **kw) self._update_visibility() def insert(self, pos, child, **kw): if pos == "auto": for sibling in map(self.nametowidget, self.tabs()): if ( not hasattr(sibling, "position_key") or sibling.position_key == None or sibling.position_key > child.position_key ): pos = sibling break else: pos = "end" super().insert(pos, child, **kw) self._update_visibility() def hide(self, tab_id): super().hide(tab_id) self._update_visibility() def forget(self, tab_id): if tab_id in self.tabs() or tab_id in self.winfo_children(): super().forget(tab_id) self._update_visibility() def is_visible(self): return self in self.master.pane_widgets() def get_visible_child(self): for child in self.winfo_children(): if str(child) == str(self.select()): return child return None def _update_visibility(self): if not isinstance(self.master, AutomaticPanedWindow): return if len(self.tabs()) == 0 and self.is_visible(): self.master.remove(self) if len(self.tabs()) > 0 and not self.is_visible(): self.master.insert("auto", self) class TreeFrame(ttk.Frame): def __init__( self, master, columns, displaycolumns="#all", show_scrollbar=True, borderwidth=0, relief="flat", **tree_kw ): ttk.Frame.__init__(self, master, borderwidth=borderwidth, relief=relief) # http://wiki.tcl.tk/44444#pagetoc50f90d9a self.vert_scrollbar = ttk.Scrollbar( self, orient=tk.VERTICAL, style=scrollbar_style("Vertical") ) if show_scrollbar: self.vert_scrollbar.grid(row=0, column=1, sticky=tk.NSEW) self.tree = ttk.Treeview( self, columns=columns, displaycolumns=displaycolumns, yscrollcommand=self.vert_scrollbar.set, **tree_kw ) self.tree["show"] = "headings" self.tree.grid(row=0, column=0, sticky=tk.NSEW) self.vert_scrollbar["command"] = self.tree.yview self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.tree.bind("<>", self.on_select, "+") self.tree.bind("", self.on_double_click, "+") def _clear_tree(self): for child_id in self.tree.get_children(): self.tree.delete(child_id) def clear(self): self._clear_tree() def on_select(self, event): pass def on_double_click(self, event): pass def scrollbar_style(orientation): # In mac ttk.Scrollbar uses native rendering unless style attribute is set # see http://wiki.tcl.tk/44444#pagetoc50f90d9a # Native rendering doesn't look good in dark themes if running_on_mac_os() and get_workbench().uses_dark_ui_theme(): return orientation + ".TScrollbar" else: return None def sequence_to_accelerator(sequence): """Translates Tk event sequence to customary shortcut string for showing in the menu""" if not sequence: return "" if not sequence.startswith("<"): return sequence accelerator = ( sequence.strip("<>").replace("Key-", "").replace("KeyPress-", "").replace("Control", "Ctrl") ) # Tweaking individual parts parts = accelerator.split("-") # tkinter shows shift with capital letter, but in shortcuts it's customary to include it explicitly if len(parts[-1]) == 1 and parts[-1].isupper() and not "Shift" in parts: parts.insert(-1, "Shift") # even when shift is not required, it's customary to show shortcut with capital letter if len(parts[-1]) == 1: parts[-1] = parts[-1].upper() accelerator = "+".join(parts) # Post processing accelerator = ( accelerator.replace("Minus", "-") .replace("minus", "-") .replace("Plus", "+") .replace("plus", "+") ) return accelerator def get_zoomed(toplevel): if "-zoomed" in toplevel.wm_attributes(): # Linux return bool(toplevel.wm_attributes("-zoomed")) else: # Win/Mac return toplevel.wm_state() == "zoomed" def set_zoomed(toplevel, value): if "-zoomed" in toplevel.wm_attributes(): # Linux toplevel.wm_attributes("-zoomed", str(int(value))) else: # Win/Mac if value: toplevel.wm_state("zoomed") else: toplevel.wm_state("normal") class EnhancedTextWithLogging(tktextext.EnhancedText): def __init__( self, master=None, style="Text", tag_current_line=False, indent_with_tabs=False, replace_tabs=False, cnf={}, **kw ): super().__init__( master=master, style=style, tag_current_line=tag_current_line, indent_with_tabs=indent_with_tabs, replace_tabs=replace_tabs, cnf=cnf, **kw ) self._last_event_changed_line_count = False def direct_insert(self, index, chars, tags=None, **kw): try: # try removing line numbers # TODO: shouldn't it take place only on paste? # TODO: does it occur when opening a file with line numbers in it? # if self._propose_remove_line_numbers and isinstance(chars, str): # chars = try_remove_linenumbers(chars, self) concrete_index = self.index(index) line_before = self.get(concrete_index + " linestart", concrete_index + " lineend") self._last_event_changed_line_count = "\n" in chars return tktextext.EnhancedText.direct_insert(self, index, chars, tags=tags, **kw) finally: line_after = self.get(concrete_index + " linestart", concrete_index + " lineend") trivial_for_coloring, trivial_for_parens = self._is_trivial_edit( chars, line_before, line_after ) get_workbench().event_generate( "TextInsert", index=concrete_index, text=chars, tags=tags, text_widget=self, trivial_for_coloring=trivial_for_coloring, trivial_for_parens=trivial_for_parens, ) def direct_delete(self, index1, index2=None, **kw): try: # index1 may be eg "sel.first" and it doesn't make sense *after* deletion concrete_index1 = self.index(index1) if index2 is not None: concrete_index2 = self.index(index2) else: concrete_index2 = None chars = self.get(index1, index2) self._last_event_changed_line_count = "\n" in chars line_before = self.get( concrete_index1 + " linestart", (concrete_index1 if concrete_index2 is None else concrete_index2) + " lineend", ) return tktextext.EnhancedText.direct_delete(self, index1, index2=index2, **kw) finally: line_after = self.get( concrete_index1 + " linestart", (concrete_index1 if concrete_index2 is None else concrete_index2) + " lineend", ) trivial_for_coloring, trivial_for_parens = self._is_trivial_edit( chars, line_before, line_after ) get_workbench().event_generate( "TextDelete", index1=concrete_index1, index2=concrete_index2, text_widget=self, trivial_for_coloring=trivial_for_coloring, trivial_for_parens=trivial_for_parens, ) def _is_trivial_edit(self, chars, line_before, line_after): # line is taken after edit for insertion and before edit for deletion if not chars.strip(): # linebreaks, including with automatic indent # check it doesn't break a triple-quote trivial_for_coloring = line_before.count("'''") == line_after.count( "'''" ) and line_before.count('"""') == line_after.count('"""') trivial_for_parens = trivial_for_coloring elif len(chars) > 1: # paste, cut, load or something like this trivial_for_coloring = False trivial_for_parens = False elif chars == "#": trivial_for_coloring = "''''" not in line_before and '"""' not in line_before trivial_for_parens = trivial_for_coloring and not re.search(PARENS_REGEX, line_before) elif chars in "()[]{}": trivial_for_coloring = line_before.count("'''") == line_after.count( "'''" ) and line_before.count('"""') == line_after.count('"""') trivial_for_parens = False elif chars == "'": trivial_for_coloring = "'''" not in line_before and "'''" not in line_after trivial_for_parens = False # can put parens into open string elif chars == '"': trivial_for_coloring = '"""' not in line_before and '"""' not in line_after trivial_for_parens = False # can put parens into open string elif chars == "\\": # can shorten closing quote trivial_for_coloring = '"""' not in line_before and '"""' not in line_after trivial_for_parens = False else: trivial_for_coloring = line_before.count("'''") == line_after.count( "'''" ) and line_before.count('"""') == line_after.count('"""') trivial_for_parens = trivial_for_coloring return trivial_for_coloring, trivial_for_parens class SafeScrollbar(ttk.Scrollbar): def __init__(self, master=None, **kw): super().__init__(master=master, **kw) def set(self, first, last): try: ttk.Scrollbar.set(self, first, last) except Exception: traceback.print_exc() class AutoScrollbar(SafeScrollbar): # http://effbot.org/zone/tkinter-autoscrollbar.htm # a vert_scrollbar that hides itself if it's not needed. only # works if you use the grid geometry manager. def __init__(self, master=None, **kw): super().__init__(master=master, **kw) def set(self, first, last): if float(first) <= 0.0 and float(last) >= 1.0: self.grid_remove() elif float(first) > 0.001 or float(last) < 0.009: # with >0 and <1 it occasionally made scrollbar wobble back and forth self.grid() ttk.Scrollbar.set(self, first, last) def pack(self, **kw): raise tk.TclError("cannot use pack with this widget") def place(self, **kw): raise tk.TclError("cannot use place with this widget") def update_entry_text(entry, text): original_state = entry.cget("state") entry.config(state="normal") entry.delete(0, "end") entry.insert(0, text) entry.config(state=original_state) class VerticallyScrollableFrame(ttk.Frame): # http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame def __init__(self, master): ttk.Frame.__init__(self, master) # set up scrolling with canvas vscrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL) self.canvas = tk.Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set) vscrollbar.config(command=self.canvas.yview) self.canvas.xview_moveto(0) self.canvas.yview_moveto(0) self.canvas.grid(row=0, column=0, sticky=tk.NSEW) vscrollbar.grid(row=0, column=1, sticky=tk.NSEW) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.interior = ttk.Frame(self.canvas) self.interior_id = self.canvas.create_window(0, 0, window=self.interior, anchor=tk.NW) self.bind("", self._configure_interior, "+") self.bind("", self._expose, "+") def _expose(self, event): self.update_idletasks() self.update_scrollbars() def _configure_interior(self, event): self.update_scrollbars() def update_scrollbars(self): # update the scrollbars to match the size of the inner frame size = (self.canvas.winfo_width(), self.interior.winfo_reqheight()) self.canvas.config(scrollregion="0 0 %s %s" % size) if ( self.interior.winfo_reqwidth() != self.canvas.winfo_width() and self.canvas.winfo_width() > 10 ): # update the interior's width to fit canvas # print("CAWI", self.canvas.winfo_width()) self.canvas.itemconfigure(self.interior_id, width=self.canvas.winfo_width()) class ScrollableFrame(ttk.Frame): # http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame def __init__(self, master): ttk.Frame.__init__(self, master) # set up scrolling with canvas vscrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL) hscrollbar = ttk.Scrollbar(self, orient=tk.HORIZONTAL) self.canvas = tk.Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set) vscrollbar.config(command=self.canvas.yview) hscrollbar.config(command=self.canvas.xview) self.canvas.xview_moveto(0) self.canvas.yview_moveto(0) self.canvas.grid(row=0, column=0, sticky=tk.NSEW) vscrollbar.grid(row=0, column=1, sticky=tk.NSEW) hscrollbar.grid(row=1, column=0, sticky=tk.NSEW) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.interior = ttk.Frame(self.canvas) self.interior.columnconfigure(0, weight=1) self.interior.rowconfigure(0, weight=1) self.interior_id = self.canvas.create_window(0, 0, window=self.interior, anchor=tk.NW) self.bind("", self._configure_interior, "+") self.bind("", self._expose, "+") def _expose(self, event): self.update_idletasks() self._configure_interior(event) def _configure_interior(self, event): # update the scrollbars to match the size of the inner frame size = (self.canvas.winfo_reqwidth(), self.interior.winfo_reqheight()) self.canvas.config(scrollregion="0 0 %s %s" % size) class ThemedListbox(tk.Listbox): def __init__(self, master=None, cnf={}, **kw): super().__init__(master=master, cnf=cnf, **kw) self._ui_theme_change_binding = self.bind( "<>", self._reload_theme_options, True ) self._reload_theme_options() def _reload_theme_options(self, event=None): style = ttk.Style() states = [] if self["state"] == "disabled": states.append("disabled") # Following crashes when a combobox is focused # if self.focus_get() == self: # states.append("focus") opts = {} for key in [ "background", "foreground", "highlightthickness", "highlightcolor", "highlightbackground", ]: value = style.lookup(self.get_style_name(), key, states) if value: opts[key] = value self.configure(opts) def get_style_name(self): return "Listbox" def destroy(self): self.unbind("<>", self._ui_theme_change_binding) super().destroy() class ToolTip: """Taken from http://www.voidspace.org.uk/python/weblog/arch_d7_2006_07_01.shtml""" def __init__(self, widget, options): self.widget = widget self.tipwindow = None self.id = None self.x = self.y = 0 self.options = options def showtip(self, text): "Display text in tooltip window" self.text = text if self.tipwindow or not self.text: return x, y, _, cy = self.widget.bbox("insert") x = x + self.widget.winfo_rootx() + 27 y = y + cy + self.widget.winfo_rooty() + self.widget.winfo_height() + 2 self.tipwindow = tw = tk.Toplevel(self.widget) if running_on_mac_os(): try: # Must be the first thing to do after creating window # https://wiki.tcl-lang.org/page/MacWindowStyle tw.tk.call( "::tk::unsupported::MacWindowStyle", "style", tw._w, "help", "noActivates" ) except tk.TclError: pass else: tw.wm_overrideredirect(1) tw.wm_geometry("+%d+%d" % (x, y)) if running_on_mac_os(): # TODO: maybe it's because of Tk 8.5, not because of Mac tw.wm_transient(self.widget) label = tk.Label(tw, text=self.text, **self.options) label.pack() # get_workbench().bind("WindowFocusOut", self.hidetip, True) def hidetip(self, event=None): tw = self.tipwindow self.tipwindow = None if tw: tw.destroy() # get_workbench().unbind("WindowFocusOut", self.hidetip) def create_tooltip(widget, text, **kw): options = get_style_configuration("Tooltip").copy() options.setdefault("background", "#ffffe0") options.setdefault("relief", "solid") options.setdefault("borderwidth", 1) options.setdefault("padx", 1) options.setdefault("pady", 0) options.update(kw) toolTip = ToolTip(widget, options) def enter(event): toolTip.showtip(text) def leave(event): toolTip.hidetip() widget.bind("", enter) widget.bind("", leave) class NoteBox(CommonDialog): def __init__(self, master=None, max_default_width=300, **kw): super().__init__(master=master, highlightthickness=0, **kw) self._max_default_width = max_default_width self.wm_overrideredirect(True) if running_on_mac_os(): # TODO: maybe it's because of Tk 8.5, not because of Mac self.wm_transient(master) try: # For Mac OS self.tk.call( "::tk::unsupported::MacWindowStyle", "style", self._w, "help", "noActivates" ) except tk.TclError: pass self._current_chars = "" self._click_bindings = {} self.padx = 5 self.pady = 5 self.text = TweakableText( self, background="#ffffe0", borderwidth=1, relief="solid", undo=False, read_only=True, font="TkDefaultFont", highlightthickness=0, padx=self.padx, pady=self.pady, wrap="word", ) self.text.grid(row=0, column=0, sticky="nsew") self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.text.bind("", self.close, True) # tk._default_root.bind_all("<1>", self._close_maybe, True) # tk._default_root.bind_all("", self.close, True) self.withdraw() def clear(self): for tag in self._click_bindings: self.text.tag_unbind(tag, "<1>", self._click_bindings[tag]) self.text.tag_remove(tag, "1.0", "end") self.text.direct_delete("1.0", "end") self._current_chars = "" self._click_bindings.clear() def set_content(self, *items): self.clear() for item in items: if isinstance(item, str): self.text.direct_insert("1.0", item) self._current_chars = item else: assert isinstance(item, (list, tuple)) chars, *props = item if len(props) > 0 and callable(props[-1]): tags = tuple(props[:-1]) click_handler = props[-1] else: tags = tuple(props) click_handler = None self.append_text(chars, tags, click_handler) self.text.see("1.0") def append_text(self, chars, tags=(), click_handler=None): tags = tuple(tags) if click_handler is not None: click_tag = "click_%d" % len(self._click_bindings) tags = tags + (click_tag,) binding = self.text.tag_bind(click_tag, "<1>", click_handler, True) self._click_bindings[click_tag] = binding self.text.direct_insert("end", chars, tags) self._current_chars += chars def place(self, target, focus=None): # Compute the area that will be described by this Note focus_x = target.winfo_rootx() focus_y = target.winfo_rooty() focus_height = target.winfo_height() if isinstance(focus, TextRange): assert isinstance(target, tk.Text) topleft = target.bbox("%d.%d" % (focus.lineno, focus.col_offset)) if focus.end_col_offset == 0: botright = target.bbox( "%d.%d lineend" % (focus.end_lineno - 1, focus.end_lineno - 1) ) else: botright = target.bbox("%d.%d" % (focus.end_lineno, focus.end_col_offset)) if topleft and botright: focus_x += topleft[0] focus_y += topleft[1] focus_height = botright[1] - topleft[1] + botright[3] elif isinstance(focus, (list, tuple)): focus_x += focus[0] focus_y += focus[1] focus_height = focus[3] elif focus is None: pass else: raise TypeError("Unsupported focus") # Compute dimensions of the note font = self.text["font"] if isinstance(font, str): font = tk.font.nametofont(font) lines = self._current_chars.splitlines() max_line_width = 0 for line in lines: max_line_width = max(max_line_width, font.measure(line)) width = min(max_line_width, self._max_default_width) + self.padx * 2 + 2 self.wm_geometry("%dx%d+%d+%d" % (width, 100, focus_x, focus_y + focus_height)) self.update_idletasks() line_count = int(float(self.text.index("end"))) line_height = font.metrics()["linespace"] self.wm_geometry( "%dx%d+%d+%d" % (width, line_count * line_height, focus_x, focus_y + focus_height) ) # TODO: detect the situation when note doesn't fit under # the focus box and should be placed above self.deiconify() def show_note(self, *content_items: Union[str, List], target=None, focus=None) -> None: self.set_content(*content_items) self.place(target, focus) def _close_maybe(self, event): if event.widget not in [self, self.text]: self.close(event) def close(self, event=None): self.withdraw() def get_widget_offset_from_toplevel(widget): x = 0 y = 0 toplevel = widget.winfo_toplevel() while widget != toplevel: x += widget.winfo_x() y += widget.winfo_y() widget = widget.master return x, y def create_string_var(value, modification_listener=None): """Creates a tk.StringVar with "modified" attribute showing whether the variable has been modified after creation""" return _create_var(tk.StringVar, value, modification_listener) def create_int_var(value, modification_listener=None): """See create_string_var""" return _create_var(tk.IntVar, value, modification_listener) def create_double_var(value, modification_listener=None): """See create_string_var""" return _create_var(tk.DoubleVar, value, modification_listener) def create_boolean_var(value, modification_listener=None): """See create_string_var""" return _create_var(tk.BooleanVar, value, modification_listener) def _create_var(class_, value, modification_listener): var = class_(value=value) var.modified = False def on_write(*args): var.modified = True if modification_listener: try: modification_listener() except Exception: # Otherwise whole process will be brought down # because for some reason Tk tries to call non-existing method # on variable get_workbench().report_exception() # TODO: https://bugs.python.org/issue22115 (deprecation warning) var.trace("w", on_write) return var def shift_is_pressed(event_state): # http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/event-handlers.html # http://stackoverflow.com/q/32426250/261181 return event_state & 0x0001 def control_is_pressed(event_state): # http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/event-handlers.html # http://stackoverflow.com/q/32426250/261181 return event_state & 0x0004 def sequence_to_event_state_and_keycode(sequence: str) -> Optional[Tuple[int, int]]: # remember handlers for certain shortcuts which require # different treatment on non-latin keyboards if sequence[0] != "<": return None parts = sequence.strip("<").strip(">").split("-") # support only latin letters for now if parts[-1].lower() not in list("abcdefghijklmnopqrstuvwxyz"): return None letter = parts.pop(-1) if "Key" in parts: parts.remove("Key") if "key" in parts: parts.remove("key") modifiers = {part.lower() for part in parts} if letter.isupper(): modifiers.add("shift") if modifiers not in [{"control"}, {"control", "shift"}]: # don't support others for now return None event_state = 0 # http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/event-handlers.html # https://stackoverflow.com/questions/32426250/python-documentation-and-or-lack-thereof-e-g-keyboard-event-state for modifier in modifiers: if modifier == "shift": event_state |= 0x0001 elif modifier == "control": event_state |= 0x0004 else: # unsupported modifier return None # for latin letters keycode is same as its ascii code return (event_state, ord(letter.upper())) def select_sequence(win_version, mac_version, linux_version=None): if running_on_windows(): return win_version elif running_on_mac_os(): return mac_version elif running_on_linux() and linux_version: return linux_version else: return win_version def try_remove_linenumbers(text, master): try: if has_line_numbers(text) and messagebox.askyesno( title="Remove linenumbers", message="Do you want to remove linenumbers from pasted text?", default=messagebox.YES, ): return remove_line_numbers(text) else: return text except Exception: traceback.print_exc() return text def has_line_numbers(text): lines = text.splitlines() return len(lines) > 2 and all([len(split_after_line_number(line)) == 2 for line in lines]) def split_after_line_number(s): parts = re.split(r"(^\s*\d+\.?)", s) if len(parts) == 1: return parts else: assert len(parts) == 3 and parts[0] == "" return parts[1:] def remove_line_numbers(s): cleaned_lines = [] for line in s.splitlines(): parts = split_after_line_number(line) if len(parts) != 2: return s else: cleaned_lines.append(parts[1]) return textwrap.dedent(("\n".join(cleaned_lines)) + "\n") def center_window(win, master=None): # for backward compat return assign_geometry(win, master) def assign_geometry(win, master=None, min_left=0, min_top=0): if master is None: master = tk._default_root size = get_workbench().get_option(get_size_option_name(win)) if size: width, height = size saved_size = True else: fallback_width = 600 fallback_height = 400 # need to wait until size is computed # (unfortunately this causes dialog to jump) if getattr(master, "initializing", False): # can't get reliable positions when main window is not in mainloop yet width = fallback_width height = fallback_height else: if not running_on_linux(): # better to avoid in Linux because it causes ugly jump win.update_idletasks() # looks like it doesn't take window border into account width = win.winfo_width() height = win.winfo_height() if width < 10: # ie. size measurement is not correct width = fallback_width height = fallback_height saved_size = False left = master.winfo_rootx() + master.winfo_width() // 2 - width // 2 top = master.winfo_rooty() + master.winfo_height() // 2 - height // 2 left = max(left, min_left) top = max(top, min_top) if saved_size: win.geometry("%dx%d+%d+%d" % (width, height, left, top)) else: win.geometry("+%d+%d" % (left, top)) class WaitingDialog(CommonDialog): def __init__(self, master, async_result, description, title="Please wait!", timeout=None): self._async_result = async_result super().__init__(master) if misc_utils.running_on_mac_os(): self.configure(background="systemSheetBackground") self.title(title) self.resizable(height=tk.FALSE, width=tk.FALSE) # self.protocol("WM_DELETE_WINDOW", self._close) self.desc_label = ttk.Label(self, text=description, wraplength=300) self.desc_label.grid(padx=20, pady=20) self.update_idletasks() self.timeout = timeout self.start_time = time.time() self.after(500, self._poll) def _poll(self): if self._async_result.ready(): self._close() elif self.timeout and time.time() - self.start_time > self.timeout: raise TimeoutError() else: self.after(500, self._poll) self.desc_label["text"] = self.desc_label["text"] + "." def _close(self): self.destroy() def run_with_waiting_dialog(master, action, args=(), description="Working"): # http://stackoverflow.com/a/14299004/261181 from multiprocessing.pool import ThreadPool pool = ThreadPool(processes=1) async_result = pool.apply_async(action, args) dlg = WaitingDialog(master, async_result, description=description) show_dialog(dlg, master) return async_result.get() class FileCopyDialog(CommonDialog): def __init__(self, master, source, destination, description=None, fsync=True): self._source = source self._destination = destination self._old_bytes_copied = 0 self._bytes_copied = 0 self._fsync = fsync self._done = False self._cancelled = False self._closed = False super().__init__(master) main_frame = ttk.Frame(self) # To get styled background main_frame.grid(row=0, column=0, sticky="nsew") self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.title(_("Copying")) if description is None: description = _("Copying\n %s\nto\n %s") % (source, destination) label = ttk.Label(main_frame, text=description) label.grid(row=0, column=0, columnspan=2, sticky="nw", padx=15, pady=15) self._bar = ttk.Progressbar(main_frame, maximum=os.path.getsize(source), length=200) self._bar.grid(row=1, column=0, columnspan=2, sticky="nsew", padx=15, pady=0) self._cancel_button = ttk.Button(main_frame, text=_("Cancel"), command=self._cancel) self._cancel_button.grid(row=2, column=1, sticky="ne", padx=15, pady=15) self._bar.focus_set() main_frame.columnconfigure(0, weight=1) self._update_progress() self.bind("", self._cancel, True) # escape-close only if process has completed self.protocol("WM_DELETE_WINDOW", self._cancel) self._start() def _start(self): def work(): self._copy_progess = 0 with open(self._source, "rb") as fsrc: with open(self._destination, "wb") as fdst: while True: buf = fsrc.read(16 * 1024) if not buf: break fdst.write(buf) fdst.flush() if self._fsync: os.fsync(fdst) self._bytes_copied += len(buf) self._done = True threading.Thread(target=work, daemon=True).start() def _update_progress(self): if self._done: if not self._closed: self._close() return self._bar.step(self._bytes_copied - self._old_bytes_copied) self._old_bytes_copied = self._bytes_copied self.after(100, self._update_progress) def _close(self): self.destroy() self._closed = True def _cancel(self, event=None): self._cancelled = True self._close() class ChoiceDialog(CommonDialog): def __init__( self, master=None, title="Choose one", question: str = "Choose one:", choices=[] ) -> None: super().__init__(master=master) self.title(title) self.resizable(False, False) self.columnconfigure(0, weight=1) row = 0 question_label = ttk.Label(self, text=question) question_label.grid(row=row, column=0, columnspan=2, sticky="w", padx=20, pady=20) row += 1 self.var = tk.StringVar() for choice in choices: rb = ttk.Radiobutton(self, text=choice, variable=self.var, value=choice) rb.grid(row=row, column=0, columnspan=2, sticky="w", padx=20) row += 1 ok_button = ttk.Button(self, text="OK", command=self._ok, default="active") ok_button.grid(row=row, column=0, sticky="e", pady=20) cancel_button = ttk.Button(self, text="Cancel", command=self._cancel) cancel_button.grid(row=row, column=1, sticky="e", padx=20, pady=20) self.bind("", self._cancel, True) self.bind("", self._ok, True) self.protocol("WM_DELETE_WINDOW", self._cancel) if misc_utils.running_on_mac_os(): self.configure(background="systemSheetBackground") def _ok(self): self.result = self.var.get() if not self.result: self.result = None self.destroy() def _cancel(self): self.result = None self.destroy() class LongTextDialog(CommonDialog): def __init__(self, title, text_content, parent=None): if parent is None: parent = tk._default_root super().__init__(master=parent) self.title(title) main_frame = ttk.Frame(self) main_frame.grid(row=0, column=0, sticky="nsew") self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) default_font = tk.font.nametofont("TkDefaultFont") self._text = tktextext.TextFrame( main_frame, read_only=True, wrap="none", font=default_font, width=80, height=10, relief="sunken", borderwidth=1, ) self._text.grid(row=1, column=0, columnspan=2, sticky="nsew", padx=20, pady=20) self._text.text.direct_insert("1.0", text_content) self._text.text.see("1.0") copy_button = ttk.Button( main_frame, command=self._copy, text=_("Copy to clipboard"), width=20 ) copy_button.grid(row=2, column=0, sticky="w", padx=20, pady=(0, 20)) close_button = ttk.Button(main_frame, command=self._close, text=_("Close")) close_button.grid(row=2, column=1, sticky="w", padx=20, pady=(0, 20)) main_frame.columnconfigure(0, weight=1) main_frame.rowconfigure(1, weight=1) self.protocol("WM_DELETE_WINDOW", self._close) self.bind("", self._close, True) def _copy(self, event=None): self.clipboard_clear() self.clipboard_append(self._text.text.get("1.0", "end")) def _close(self, event=None): self.destroy() def ask_one_from_choices( master=None, title="Choose one", question: str = "Choose one:", choices=[] ): dlg = ChoiceDialog(master, title, question, choices) show_dialog(dlg, master) return dlg.result class SubprocessDialog(CommonDialog): """Shows incrementally the output of given subprocess. Allows cancelling""" def __init__( self, master, proc, title, long_description=None, autoclose=True, conclusion="Done." ): self._closed = False self._proc = proc self.stdout = "" self.stderr = "" self._stdout_thread = None self._stderr_thread = None self.returncode = None self.cancelled = False self._autoclose = autoclose self._event_queue = collections.deque() self._conclusion = conclusion super().__init__(master) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) main_frame = ttk.Frame(self) # To get styled background main_frame.grid(sticky="nsew") text_font = tk.font.nametofont("TkFixedFont").copy() text_font["size"] = int(text_font["size"] * 0.9) text_font["family"] = "Courier" if running_on_mac_os() else "Courier New" text_frame = tktextext.TextFrame( main_frame, read_only=True, horizontal_scrollbar=False, background=lookup_style_option("TFrame", "background"), font=text_font, wrap="word", ) text_frame.grid(row=0, column=0, sticky=tk.NSEW, padx=15, pady=15) self.text = text_frame.text self.text["width"] = 60 self.text["height"] = 7 if long_description is not None: self.text.direct_insert("1.0", long_description + "\n\n") self.button = ttk.Button(main_frame, text=_("Cancel"), command=self._close) self.button.grid(row=1, column=0, pady=(0, 15)) main_frame.rowconfigure(0, weight=1) main_frame.columnconfigure(0, weight=1) self.title(title) if misc_utils.running_on_mac_os(): self.configure(background="systemSheetBackground") # self.resizable(height=tk.FALSE, width=tk.FALSE) self.text.focus_set() self.bind( "", self._close_if_done, True ) # escape-close only if process has completed self.protocol("WM_DELETE_WINDOW", self._close) self.update_idletasks() self._start_listening() def _start_listening(self): def listen_stream(stream_name): stream = getattr(self._proc, stream_name) while True: data = stream.readline() self._event_queue.append((stream_name, data)) setattr(self, stream_name, getattr(self, stream_name) + data) if data == "": break self.returncode = self._proc.wait() self._stdout_thread = threading.Thread(target=listen_stream, args=["stdout"], daemon=True) self._stdout_thread.start() if self._proc.stderr is not None: self._stderr_thread = threading.Thread( target=listen_stream, args=["stderr"], daemon=True ) self._stderr_thread.start() def poll_output_events(): if self._closed: return while len(self._event_queue) > 0: stream_name, data = self._event_queue.popleft() self.text.direct_insert("end", data, tags=(stream_name,)) self.text.see("end") self.returncode = self._proc.poll() if self.returncode == None: self.after(200, poll_output_events) else: self.button["text"] = _("OK") self.button.focus_set() if self.returncode != 0: self.text.direct_insert( "end", "\n\nProcess failed, return code: %s\n" % self.returncode, ("stderr",), ) self.update_idletasks() self.text.see("end") elif self._autoclose: self._close() else: self.text.direct_insert("end", "\n\n" + self._conclusion) self.update_idletasks() self.text.see("end") poll_output_events() def _close_if_done(self, event): if self._proc.poll() is not None: self._close(event) def _close(self, event=None): if self._proc.poll() is None: if messagebox.askyesno( _("Cancel the process?"), _("The process is still running.\nAre you sure you want to cancel?"), parent=None if running_on_mac_os() else self, ): # try gently first try: if running_on_windows(): os.kill(self._proc.pid, signal.CTRL_BREAK_EVENT) # @UndefinedVariable else: os.kill(self._proc.pid, signal.SIGINT) self._proc.wait(2) except subprocess.TimeoutExpired: if self._proc.poll() is None: # now let's be more concrete self._proc.kill() self.cancelled = True # Wait for threads to finish self._stdout_thread.join(2) if self._stderr_thread is not None: self._stderr_thread.join(2) # fetch output about cancelling while len(self._event_queue) > 0: stream_name, data = self._event_queue.popleft() self.text.direct_insert("end", data, tags=(stream_name,)) self.text.direct_insert("end", "\n\nPROCESS CANCELLED") self.text.see("end") else: return else: self._closed = True self.destroy() def get_busy_cursor(): if running_on_windows(): return "wait" elif running_on_mac_os(): return "spinning" else: return "watch" def get_tk_version_str(): return tk._default_root.tk.call("info", "patchlevel") def get_tk_version_info(): result = [] for part in get_tk_version_str().split("."): try: result.append(int(part)) except Exception: result.append(0) return tuple(result) def get_style_configuration(style_name, default={}): style = ttk.Style() # NB! style.configure seems to reuse the returned dict # Don't change it without copying first result = style.configure(style_name) if result is None: return default else: return result def lookup_style_option(style_name, option_name, default=None): style = ttk.Style() setting = style.lookup(style_name, option_name) if setting in [None, ""]: return default elif setting == "True": return True elif setting == "False": return False else: return setting def scale(value): return get_workbench().scale(value) def open_path_in_system_file_manager(path): if running_on_mac_os(): # http://stackoverflow.com/a/3520693/261181 # -R doesn't allow showing hidden folders subprocess.Popen(["open", path]) elif running_on_linux(): subprocess.Popen(["xdg-open", path]) else: assert running_on_windows() subprocess.Popen(["explorer", path]) def _get_dialog_provider(): if platform.system() != "Linux": return filedialog if shutil.which("zenity"): return _ZenityDialogProvider # fallback return filedialog def asksaveasfilename(**options): # https://tcl.tk/man/tcl8.6/TkCmd/getSaveFile.htm _tweak_file_dialog_parent(options) return _get_dialog_provider().asksaveasfilename(**options) def askopenfilename(**options): # https://tcl.tk/man/tcl8.6/TkCmd/getOpenFile.htm _tweak_file_dialog_parent(options) return _get_dialog_provider().askopenfilename(**options) def askopenfilenames(**options): # https://tcl.tk/man/tcl8.6/TkCmd/getOpenFile.htm _tweak_file_dialog_parent(options) return _get_dialog_provider().askopenfilenames(**options) def askdirectory(**options): # https://tcl.tk/man/tcl8.6/TkCmd/chooseDirectory.htm _tweak_file_dialog_parent(options) return _get_dialog_provider().askdirectory(**options) def _tweak_file_dialog_parent(options): if running_on_mac_os(): # used to require master/parent (https://bugs.python.org/issue34927) # but this is deprecated in Catalina (https://github.com/thonny/thonny/issues/840) if "master" in options: del options["master"] if "parent" in options: del options["parent"] else: if "parent" not in options: if "master" in options: options["parent"] = options["master"] else: options["parent"] = tk._default_root class _ZenityDialogProvider: # https://www.writebash.com/bash-gui/zenity-create-file-selection-dialog-224.html # http://linux.byexamples.com/archives/259/a-complete-zenity-dialog-examples-1/ # http://linux.byexamples.com/archives/265/a-complete-zenity-dialog-examples-2/ # another possibility is to use PyGobject: https://github.com/poulp/zenipy @classmethod def askopenfilename(cls, **options): args = cls._convert_common_options("Open file", **options) return cls._call(args) @classmethod def askopenfilenames(cls, **options): args = cls._convert_common_options("Open files", **options) return cls._call(args + ["--multiple"]).split("|") @classmethod def asksaveasfilename(cls, **options): args = cls._convert_common_options("Save as", **options) args.append("--save") if options.get("confirmoverwrite", True): args.append("--confirm-overwrite") filename = cls._call(args) if not filename: return None if "defaultextension" in options and "." not in os.path.basename(filename): filename += options["defaultextension"] return filename @classmethod def askdirectory(cls, **options): args = cls._convert_common_options("Select directory", **options) args.append("--directory") return cls._call(args) @classmethod def _convert_common_options(cls, default_title, **options): args = ["--file-selection", "--title=%s" % options.get("title", default_title)] filename = _options_to_zenity_filename(options) if filename: args.append("--filename=%s" % filename) parent = options.get("parent", options.get("master", None)) if parent is not None: args.append("--modal") args.append("--attach=%s" % hex(parent.winfo_id())) for desc, pattern in options.get("filetypes", ()): # zenity requires star before extension pattern = pattern.replace(" .", " *.") if pattern.startswith("."): pattern = "*" + pattern if pattern == "*.*": # ".*" was provided to make the pattern safe for Tk dialog # not required with Zenity pattern = "*" args.append("--file-filter=%s | %s" % (desc, pattern)) return args @classmethod def _call(cls, args): args = ["zenity", "--name=Thonny", "--class=Thonny"] + args result = subprocess.run( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True ) if result.returncode == 0: return result.stdout.strip() else: # could check stderr, but it may contain irrelevant warnings return None def _options_to_zenity_filename(options): if options.get("initialdir"): if options.get("initialfile"): return os.path.join(options["initialdir"], options["initialfile"]) else: return options["initialdir"] + os.path.sep return None def register_latin_shortcut( registry, sequence: str, handler: Callable, tester: Optional[Callable] ) -> None: res = sequence_to_event_state_and_keycode(sequence) if res is not None: if res not in registry: registry[res] = [] registry[res].append((handler, tester)) def handle_mistreated_latin_shortcuts(registry, event): # tries to handle Ctrl+LatinLetter shortcuts # given from non-Latin keyboards # See: https://bitbucket.org/plas/thonny/issues/422/edit-keyboard-shortcuts-ctrl-c-ctrl-v-etc # only consider events with Control held if not event.state & 0x04: return if running_on_mac_os(): return # consider only part of the state, # because at least on Windows, Ctrl-shortcuts' state # has something extra simplified_state = 0x04 if shift_is_pressed(event.state): simplified_state |= 0x01 # print(simplified_state, event.keycode) if (simplified_state, event.keycode) in registry: if event.keycode != ord(event.char) and event.keysym in (None, "??"): # keycode and char doesn't match, # this means non-latin keyboard for handler, tester in registry[(simplified_state, event.keycode)]: if tester is None or tester(): handler() def show_dialog(dlg, master=None, geometry=True, min_left=0, min_top=0): if getattr(dlg, "closed", False): return if master is None: master = tk._default_root get_workbench().event_generate("WindowFocusOut") # following order seems to give most smooth appearance focused_widget = master.focus_get() dlg.transient(master.winfo_toplevel()) if geometry: # dlg.withdraw() # unfortunately inhibits size calculations in assign_geometry if isinstance(geometry, str): dlg.geometry(geometry) else: assign_geometry(dlg, master, min_left, min_top) # dlg.wm_deiconify() try: dlg.grab_set() except: pass dlg.lift() dlg.focus_set() master.winfo_toplevel().wait_window(dlg) dlg.grab_release() master.winfo_toplevel().lift() master.winfo_toplevel().focus_force() master.winfo_toplevel().grab_set() if running_on_mac_os(): master.winfo_toplevel().grab_release() if focused_widget is not None: try: focused_widget.focus_force() except TclError: pass def popen_with_ui_thread_callback(*Popen_args, on_completion, poll_delay=0.1, **Popen_kwargs): if "encoding" not in Popen_kwargs: if "env" not in Popen_kwargs: Popen_kwargs["env"] = os.environ.copy() Popen_kwargs["env"]["PYTHONIOENCODING"] = "utf-8" if sys.version_info >= (3, 6): Popen_kwargs["encoding"] = "utf-8" proc = subprocess.Popen(*Popen_args, **Popen_kwargs) # Need to read in thread in order to avoid blocking because # of full pipe buffer (see https://bugs.python.org/issue1256) out_lines = [] err_lines = [] def read_stream(stream, target_list): while True: line = stream.readline() if line: target_list.append(line) else: break t_out = threading.Thread(target=read_stream, daemon=True, args=(proc.stdout, out_lines)) t_err = threading.Thread(target=read_stream, daemon=True, args=(proc.stderr, err_lines)) t_out.start() t_err.start() def poll(): if proc.poll() is not None: t_out.join(3) t_err.join(3) on_completion(proc, out_lines, err_lines) return tk._default_root.after(int(poll_delay * 1000), poll) poll() return proc class MenuEx(tk.Menu): def __init__(self, target): self._testers = {} super().__init__( target, tearoff=False, postcommand=self.on_post, **get_style_configuration("Menu") ) def on_post(self, *args): self.update_item_availability() def update_item_availability(self): for i in range(self.index("end") + 1): item_data = self.entryconfigure(i) if "label" in item_data: tester = self._testers.get(item_data["label"]) if tester and not tester(): self.entryconfigure(i, state=tk.DISABLED) else: self.entryconfigure(i, state=tk.NORMAL) def add(self, kind, cnf={}, **kw): cnf = cnf or kw tester = cnf.get("tester") if "tester" in cnf: del cnf["tester"] super().add(kind, cnf) itemdata = self.entryconfigure(self.index("end")) labeldata = itemdata.get("label") if labeldata: self._testers[labeldata] = tester class TextMenu(MenuEx): def __init__(self, target): self.text = target MenuEx.__init__(self, target) self.add_basic_items() self.add_extra_items() def add_basic_items(self): self.add_command(label=_("Cut"), command=self.on_cut, tester=self.can_cut) self.add_command(label=_("Copy"), command=self.on_copy, tester=self.can_copy) self.add_command(label=_("Paste"), command=self.on_paste, tester=self.can_paste) def add_extra_items(self): self.add_separator() self.add_command(label=_("Select All"), command=self.on_select_all) def on_cut(self): self.text.event_generate("<>") def on_copy(self): self.text.event_generate("<>") def on_paste(self): self.text.event_generate("<>") def on_select_all(self): self.text.event_generate("<>") def can_cut(self): return self.get_selected_text() and not self.selection_is_read_only() def can_copy(self): return self.get_selected_text() def can_paste(self): return not self.selection_is_read_only() def get_selected_text(self): try: return self.text.get("sel.first", "sel.last") except TclError: return "" def selection_is_read_only(self): if hasattr(self.text, "is_read_only"): return self.text.is_read_only() return False def create_url_label(master, url, text=None): url_font = tkinter.font.nametofont("TkDefaultFont").copy() url_font.configure(underline=1) url_label = ttk.Label( master, text=text if text else url, style="Url.TLabel", cursor="hand2", font=url_font ) url_label.grid() url_label.bind("", lambda _: webbrowser.open(url)) return url_label def get_size_option_name(window): return "layout." + type(window).__name__ + "_size" def get_default_theme(): if running_on_windows(): return "Windows" elif running_on_rpi(): return "Raspberry Pi" else: return "Enhanced Clam" def get_default_basic_theme(): if running_on_windows(): return "xpnative" else: return "clam" EM_WIDTH = None def ems_to_pixels(x): global EM_WIDTH if EM_WIDTH is None: EM_WIDTH = tkinter.font.nametofont("TkDefaultFont").measure("m") return int(EM_WIDTH * x) _btn_padding = None def tr_btn(s): """Translates button caption, adds padding to make sure text fits""" global _btn_padding if _btn_padding is None: _btn_padding = get_button_padding() return _btn_padding + _(s) + _btn_padding if __name__ == "__main__": root = tk.Tk() closa = ClosableNotebook(root) closa.add(ttk.Button(closa, text="B1"), text="B1") closa.add(ttk.Button(closa, text="B2"), text="B2") closa.grid() root.mainloop() thonny-3.2.7/thonny/__main__.py0000644000175000017500000000004413611773167017477 0ustar annamaaannamaa00000000000000from thonny import launch launch() thonny-3.2.7/thonny/code.py0000644000175000017500000010057113611774245016675 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import os.path import sys import tkinter as tk import traceback from logging import exception from tkinter import messagebox, ttk from thonny import get_workbench, ui_utils, get_runner from thonny.codeview import CodeView from thonny.common import ( TextRange, ToplevelResponse, normpath_with_actual_case, is_same_path, InlineCommand, ) from thonny.tktextext import rebind_control_a from thonny.ui_utils import askopenfilename, asksaveasfilename, select_sequence from thonny.misc_utils import running_on_windows, running_on_mac_os from _tkinter import TclError from thonny.base_file_browser import choose_node_for_file_operations, ask_backend_path import logging _dialog_filetypes = [("Python files", ".py .pyw"), ("text files", ".txt"), ("all files", ".*")] REMOTE_PATH_MARKER = " :: " class Editor(ttk.Frame): def __init__(self, master): ttk.Frame.__init__(self, master) assert isinstance(master, EditorNotebook) # parent of codeview will be workbench so that it can be maximized self._code_view = CodeView( get_workbench(), propose_remove_line_numbers=True, font="EditorFont", replace_tabs=True ) get_workbench().event_generate( "EditorTextCreated", editor=self, text_widget=self.get_text_widget() ) self._code_view.grid(row=0, column=0, sticky=tk.NSEW, in_=self) self._code_view.home_widget = self # don't forget home self.maximizable_widget = self._code_view self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self._filename = None self._last_known_mtime = None self._asking_about_external_change = False self._code_view.text.bind("<>", self._on_text_modified, True) self._code_view.text.bind("<>", self._on_text_change, True) self._code_view.text.bind("", self._control_tab, True) get_workbench().bind("DebuggerResponse", self._listen_debugger_progress, True) get_workbench().bind("ToplevelResponse", self._listen_for_toplevel_response, True) self.update_appearance() def get_text_widget(self): return self._code_view.text def get_code_view(self): # TODO: try to get rid of this return self._code_view def get_filename(self, try_hard=False): if self._filename is None and try_hard: self.save_file() return self._filename def get_title(self): if self.get_filename() is None: result = "" elif is_remote_path(self.get_filename()): path = extract_target_path(self.get_filename()) name = path.split("/")[-1] result = "[ " + name + " ]" else: result = os.path.basename(self.get_filename()) if self.is_modified(): result += " *" return result def check_for_external_changes(self): if self._asking_about_external_change: # otherwise method will be re-entered when focus # changes because of message box return if self._filename is None: return if is_remote_path(self._filename): return try: self._asking_about_external_change = True if self._last_known_mtime is None: return elif not os.path.exists(self._filename): self.master.select(self) if messagebox.askyesno( "File is gone", "Looks like '%s' was deleted or moved outside if the editor.\n\n" % self._filename + "Do you want to also close the editor?", ): self.master.close_editor(self) else: self.get_text_widget().edit_modified(True) self._last_known_mtime = None elif os.path.getmtime(self._filename) != self._last_known_mtime: self.master.select(self) if messagebox.askyesno( "External modification", "Looks like '%s' was modified outside the editor.\n\n" % self._filename + "Do you want to discard current editor content and reload the file from disk?", ): self._load_file(self._filename, keep_undo=True) else: self._last_known_mtime = os.path.getmtime(self._filename) finally: self._asking_about_external_change = False def get_long_description(self): if self._filename is None: result = "" else: result = self._filename try: index = self._code_view.text.index("insert") if index and "." in index: line, col = index.split(".") result += " @ {} : {}".format(line, int(col) + 1) except Exception: exception("Finding cursor location") return result def _load_file(self, filename, keep_undo=False): try: if is_remote_path(filename): self._load_remote_file(filename) else: self._load_local_file(filename, keep_undo) except SyntaxError as e: assert "encoding" in str(e).lower() messagebox.showerror( "Problem loading file", "This file seems to have problems with encoding.\n\n" + "Make sure it is in UTF-8 or contains proper encoding hint.", ) return False self.update_appearance() def _load_local_file(self, filename, keep_undo=False): with open(filename, "rb") as fp: source = fp.read() # Make sure Windows filenames have proper format filename = normpath_with_actual_case(filename) self._filename = filename self._last_known_mtime = os.path.getmtime(self._filename) get_workbench().event_generate("Open", editor=self, filename=filename) self._code_view.set_content_as_bytes(source, keep_undo) self.get_text_widget().edit_modified(False) self._code_view.focus_set() self.master.remember_recent_file(filename) def _load_remote_file(self, filename): self._filename = filename self._code_view.set_content("") self._code_view.text.set_read_only(True) target_filename = extract_target_path(self._filename) self.update_title() response = get_runner().send_command( InlineCommand( "read_file", path=target_filename, blocking=True, description=_("Loading") + "..." ) ) if response.get("error"): # TODO: make it softer raise RuntimeError(response["error"]) content = response["content_bytes"] self._code_view.text.set_read_only(False) self._code_view.set_content_as_bytes(content) self.get_text_widget().edit_modified(False) self.update_title() def is_modified(self): return self._code_view.text.edit_modified() def save_file_enabled(self): return self.is_modified() or not self.get_filename() def save_file(self, ask_filename=False, save_copy=False): if self._filename is not None and not ask_filename: save_filename = self._filename get_workbench().event_generate("Save", editor=self, filename=save_filename) else: save_filename = self.ask_new_path() if not save_filename: return None get_workbench().event_generate( "SaveAs", editor=self, filename=save_filename, save_copy=save_copy ) content_bytes = self._code_view.get_content_as_bytes() if is_remote_path(save_filename): result = self.write_remote_file(save_filename, content_bytes, save_copy) else: result = self.write_local_file(save_filename, content_bytes, save_copy) if not result: return None if not save_copy: self._filename = save_filename self.update_title() return save_filename def write_local_file(self, save_filename, content_bytes, save_copy): try: f = open(save_filename, mode="wb") f.write(content_bytes) f.flush() # Force writes on disk, see https://learn.adafruit.com/adafruit-circuit-playground-express/creating-and-editing-code#1-use-an-editor-that-writes-out-the-file-completely-when-you-save-it os.fsync(f) f.close() if not save_copy or save_filename == self._filename: self._last_known_mtime = os.path.getmtime(save_filename) get_workbench().event_generate( "LocalFileOperation", path=save_filename, operation="save" ) except PermissionError: messagebox.showerror( "Permission Error", "Looks like this file or folder is not writable." ) return False if not save_copy or save_filename == self._filename: self.master.remember_recent_file(save_filename) if not save_copy or save_filename == self._filename: self._code_view.text.edit_modified(False) return True def write_remote_file(self, save_filename, content_bytes, save_copy): if get_runner().ready_for_remote_file_operations(show_message=True): target_filename = extract_target_path(save_filename) get_runner().send_command( InlineCommand( "write_file", path=target_filename, content_bytes=content_bytes, editor_id=id(self), blocking=True, description=_("Saving") + "...", ) ) if not save_copy: self._code_view.text.edit_modified(False) self.update_title() # NB! edit_modified is not falsed yet! get_workbench().event_generate( "RemoteFileOperation", path=target_filename, operation="save" ) return True else: return False def ask_new_path(self): node = choose_node_for_file_operations(self.winfo_toplevel(), "Where to save to?") if not node: return None if node == "local": return self.ask_new_local_path() else: assert node == "remote" return self.ask_new_remote_path() def ask_new_remote_path(self): target_path = ask_backend_path(self.winfo_toplevel(), "save") if target_path: return make_remote_path(target_path) else: return None def ask_new_local_path(self): if self._filename is None: initialdir = get_workbench().get_local_cwd() initialfile = None else: initialdir = os.path.dirname(self._filename) initialfile = os.path.basename(self._filename) # http://tkinter.unpythonic.net/wiki/tkFileDialog new_filename = asksaveasfilename( filetypes=_dialog_filetypes, defaultextension=".py", initialdir=initialdir, initialfile=initialfile, ) # Different tkinter versions may return different values if new_filename in ["", (), None]: return None # Seems that in some Python versions defaultextension # acts funny if new_filename.lower().endswith(".py.py"): new_filename = new_filename[:-3] if running_on_windows(): # may have /-s instead of \-s and wrong case new_filename = os.path.join( normpath_with_actual_case(os.path.dirname(new_filename)), os.path.basename(new_filename), ) if new_filename.endswith(".py"): base = os.path.basename(new_filename) mod_name = base[:-3].lower() if running_on_windows(): mod_name = mod_name.lower() if mod_name in [ "math", "turtle", "random", "statistics", "pygame", "matplotlib", "numpy", ]: # More proper name analysis will be performed by ProgramNamingAnalyzer if not tk.messagebox.askyesno( "Potential problem", "If you name your script '%s', " % base + "you won't be able to import the library module named '%s'" % mod_name + ".\n\n" + "Do you still want to use this name for your script?", ): return self.ask_new_local_path() return new_filename def show(self): self.master.select(self) def update_appearance(self): self._code_view.set_gutter_visibility( get_workbench().get_option("view.show_line_numbers") or get_workbench().in_simple_mode() ) self._code_view.set_line_length_margin( get_workbench().get_option("view.recommended_line_length") ) self._code_view.text.event_generate("<>") def _listen_debugger_progress(self, event): # Go read-only # TODO: check whether this module is active? self._code_view.text.set_read_only(True) def _listen_for_toplevel_response(self, event: ToplevelResponse) -> None: self._code_view.text.set_read_only(False) def _control_tab(self, event): if event.state & 1: # shift was pressed direction = -1 else: direction = 1 self.master.select_next_prev_editor(direction) return "break" def _shift_control_tab(self, event): self.master.select_next_prev_editor(-1) return "break" def select_range(self, text_range): self._code_view.select_range(text_range) def select_line(self, lineno, col_offset=None): self._code_view.select_range(TextRange(lineno, 0, lineno + 1, 0)) self.see_line(lineno) if col_offset is None: col_offset = 0 self.get_text_widget().mark_set("insert", "%d.%d" % (lineno, col_offset)) def see_line(self, lineno): # first see an earlier line in order to push target line downwards self._code_view.text.see("%d.0" % max(lineno - 4, 1)) self._code_view.text.see("%d.0" % lineno) def focus_set(self): self._code_view.focus_set() def is_focused(self): return self.focus_displayof() == self._code_view.text def _on_text_modified(self, event): self.update_title() def update_title(self): try: self.master.update_editor_title(self) except Exception: traceback.print_exc() def _on_text_change(self, event): self.update_title() def destroy(self): get_workbench().unbind("DebuggerResponse", self._listen_debugger_progress) get_workbench().unbind("ToplevelResponse", self._listen_for_toplevel_response) ttk.Frame.destroy(self) class EditorNotebook(ui_utils.ClosableNotebook): """ Manages opened files / modules """ def __init__(self, master): super().__init__(master, padding=0) get_workbench().set_default("file.reopen_all_files", False) get_workbench().set_default("file.open_files", []) get_workbench().set_default("file.current_file", None) get_workbench().set_default("file.recent_files", []) get_workbench().set_default("view.highlight_current_line", False) get_workbench().set_default("view.show_line_numbers", True) get_workbench().set_default("view.recommended_line_length", 0) self._recent_menu = tk.Menu( get_workbench().get_menu("file"), postcommand=self._update_recent_menu ) self._init_commands() self.enable_traversal() # open files from last session """ TODO: they should go only to recent files for filename in prefs["open_files"].split(";"): if os.path.exists(filename): self._open_file(filename) """ self.update_appearance() # should be in the end, so that it can be detected when # constructor hasn't completed yet self.preferred_size_in_pw = None get_workbench().bind("WindowFocusIn", self.on_focus_window, True) def _init_commands(self): # TODO: do these commands have to be in EditorNotebook ?? # Create a module level function install_editor_notebook ?? # Maybe add them separately, when notebook has been installed ?? get_workbench().add_command( "new_file", "file", _("New"), self._cmd_new_file, caption=_("New"), default_sequence=select_sequence("", ""), extra_sequences=[""], group=10, image="new-file", include_in_toolbar=True, ) get_workbench().add_command( "open_file", "file", _("Open..."), self._cmd_open_file, caption=_("Load"), default_sequence=select_sequence("", ""), extra_sequences=[""], group=10, image="open-file", include_in_toolbar=True, ) get_workbench().add_command( "recents", "file", _("Recent files"), group=10, submenu=self._recent_menu ) # http://stackoverflow.com/questions/22907200/remap-default-keybinding-in-tkinter get_workbench().bind_class("Text", "", self._control_o) get_workbench().bind_class("Text", "", self._control_o) rebind_control_a(get_workbench()) get_workbench().add_command( "close_file", "file", _("Close"), self._cmd_close_file, default_sequence=select_sequence("", ""), extra_sequences=[""], tester=lambda: self.get_current_editor() is not None, group=10, ) get_workbench().add_command( "close_files", "file", _("Close all"), self.close_tabs, tester=lambda: self.get_current_editor() is not None, default_sequence=select_sequence("", ""), group=10, ) get_workbench().add_command( "save_file", "file", _("Save"), self._cmd_save_file, caption=_("Save"), default_sequence=select_sequence("", ""), extra_sequences=[""], tester=self._cmd_save_file_enabled, group=10, image="save-file", include_in_toolbar=True, ) get_workbench().add_command( "save_file_as", "file", _("Save as..."), self._cmd_save_file_as, default_sequence=select_sequence("", ""), extra_sequences=[""], tester=lambda: self.get_current_editor() is not None, group=10, ) get_workbench().add_command( "save_copy", "file", _("Save copy..."), self._cmd_save_copy, tester=lambda: self.get_current_editor() is not None, group=10, ) get_workbench().add_command( "rename_file", "file", _("Rename..."), self._cmd_rename_file, tester=self._cmd_rename_file_enabled, group=10, ) get_workbench().createcommand("::tk::mac::OpenDocument", self._mac_open_document) def load_startup_files(self): """If no filename was sent from command line then load previous files (if setting allows)""" cmd_line_filenames = [ os.path.abspath(name) for name in sys.argv[1:] if os.path.exists(name) ] if len(cmd_line_filenames) > 0: filenames = cmd_line_filenames elif get_workbench().get_option("file.reopen_all_files"): filenames = get_workbench().get_option("file.open_files") elif get_workbench().get_option("file.current_file"): filenames = [get_workbench().get_option("file.current_file")] else: filenames = [] if len(filenames) > 0: for filename in filenames: if os.path.exists(filename): self.show_file(filename) cur_file = get_workbench().get_option("file.current_file") # choose correct active file if len(cmd_line_filenames) > 0: self.show_file(cmd_line_filenames[0]) elif cur_file and os.path.exists(cur_file): self.show_file(cur_file) else: self._cmd_new_file() else: self._cmd_new_file() def save_all_named_editors(self): all_saved = True for editor in self.winfo_children(): if editor.get_filename() and editor.is_modified(): success = editor.save_file() all_saved = all_saved and success return all_saved def remember_recent_file(self, filename): recents = get_workbench().get_option("file.recent_files") if filename in recents: recents.remove(filename) recents.insert(0, filename) relevant_recents = [name for name in recents if os.path.exists(name)][:15] get_workbench().set_option("file.recent_files", relevant_recents) self._update_recent_menu() def _update_recent_menu(self): recents = get_workbench().get_option("file.recent_files") relevant_recents = [ path for path in recents if os.path.exists(path) and not self.file_is_opened(path) ] self._recent_menu.delete(0, "end") for path in relevant_recents: def load(path=path): self.show_file(path) self._recent_menu.insert_command("end", label=path, command=load) def remember_open_files(self): if ( self.get_current_editor() is not None and self.get_current_editor().get_filename() is not None ): current_file = self.get_current_editor().get_filename() else: current_file = None get_workbench().set_option("file.current_file", current_file) open_files = [ editor.get_filename() for editor in self.winfo_children() if editor.get_filename() ] get_workbench().set_option("file.open_files", open_files) def _cmd_new_file(self): new_editor = Editor(self) get_workbench().event_generate("NewFile", editor=new_editor) self.add(new_editor, text=new_editor.get_title()) self.select(new_editor) new_editor.focus_set() def _cmd_open_file(self): node = choose_node_for_file_operations(self.winfo_toplevel(), "Where to open from?") if not node: return None if node == "local": path = askopenfilename( filetypes=_dialog_filetypes, initialdir=get_workbench().get_local_cwd() ) else: assert node == "remote" target_path = ask_backend_path(self.winfo_toplevel(), "open") if not target_path: return None path = make_remote_path(target_path) if path: # self.close_single_untitled_unmodified_editor() self.show_file(path, propose_dialog=False) def _control_o(self, event): # http://stackoverflow.com/questions/22907200/remap-default-keybinding-in-tkinter self._cmd_open_file() return "break" def _close_files(self, except_index=None): for tab_index in reversed(range(len(self.winfo_children()))): if except_index is not None and tab_index == except_index: continue else: editor = self.get_child_by_index(tab_index) if self.check_allow_closing(editor): self.forget(editor) editor.destroy() def _cmd_close_file(self): self.close_tab(self.index(self.select())) def close_tab(self, index): editor = self.get_child_by_index(index) if editor: self.close_editor(editor) def close_editor(self, editor, force=False): if not force and not self.check_allow_closing(editor): return self.forget(editor) editor.destroy() def _cmd_save_file(self): if self.get_current_editor(): self.get_current_editor().save_file() self.update_editor_title(self.get_current_editor()) def _cmd_save_file_enabled(self): return self.get_current_editor() and self.get_current_editor().save_file_enabled() def _cmd_save_file_as(self): if not self.get_current_editor(): return self.get_current_editor().save_file(ask_filename=True) self.update_editor_title(self.get_current_editor()) get_workbench().update_title() def _cmd_save_copy(self): if not self.get_current_editor(): return self.get_current_editor().save_file(ask_filename=True, save_copy=True) self.update_editor_title(self.get_current_editor()) def _cmd_save_file_as_enabled(self): return self.get_current_editor() is not None def _cmd_rename_file(self): editor = self.get_current_editor() old_filename = editor.get_filename() assert old_filename is not None self._cmd_save_file_as() if editor.get_filename() != old_filename: os.remove(old_filename) def _cmd_rename_file_enabled(self): return self.get_current_editor() and self.get_current_editor().get_filename() is not None def close_single_untitled_unmodified_editor(self): editors = self.winfo_children() if len(editors) == 1 and not editors[0].is_modified() and not editors[0].get_filename(): self._cmd_close_file() def _mac_open_document(self, *args): for arg in args: if isinstance(arg, str) and os.path.exists(arg): self.show_file(arg) get_workbench().become_active_window() def get_current_editor(self): return self.get_current_child() def get_current_editor_content(self): editor = self.get_current_editor() if editor is None: return None else: return editor.get_code_view().get_content() def get_all_editors(self): # When workspace is closing, self.winfo_children() # may return an unexplainable tkinter.Frame return [child for child in self.winfo_children() if isinstance(child, Editor)] def select_next_prev_editor(self, direction): cur_index = self.index(self.select()) next_index = (cur_index + direction) % len(self.tabs()) self.select(self.get_child_by_index(next_index)) def file_is_opened(self, path): for editor in self.get_all_editors(): if editor.get_filename() and is_same_path(path, editor.get_filename()): return True return False def show_file(self, filename, text_range=None, set_focus=True, propose_dialog=True): # self.close_single_untitled_unmodified_editor() try: editor = self.get_editor(filename, True) except PermissionError: logging.getLogger("thonny").exception("Loading " + filename) msg = "Got permission error when trying to load\n" + filename if running_on_mac_os() and propose_dialog: msg += "\n\nTry opening it with File => Open." messagebox.showerror("Permission error", msg) return None assert editor is not None self.select(editor) if set_focus: editor.focus_set() if text_range is not None: editor.select_range(text_range) return editor def show_remote_file(self, target_filename): if not get_runner().ready_for_remote_file_operations(show_message=True): return None else: return self.show_file(make_remote_path(target_filename)) def show_file_at_line(self, filename, lineno, col_offset=None): editor = self.show_file(filename) editor.select_line(lineno, col_offset) def update_appearance(self): for editor in self.winfo_children(): editor.update_appearance() def update_editor_title(self, editor, title=None): if title is None: title = editor.get_title() try: self.tab(editor, text=title) except TclError: pass try: self.indicate_modification() except Exception: logging.exception("Could not update modification indication") def indicate_modification(self): if not running_on_mac_os(): return atts = self.winfo_toplevel().wm_attributes() if "-modified" in atts: i = atts.index("-modified") mod = atts[i : i + 2] rest = atts[:i] + atts[i + 2 :] else: mod = () rest = atts for editor in self.get_all_editors(): if editor.is_modified(): if mod != ("-modified", 1): self.winfo_toplevel().wm_attributes(*(rest + ("-modified", 1))) break else: if mod == ("-modified", 1): self.winfo_toplevel().wm_attributes(*(rest + ("-modified", 0))) def _open_file(self, filename): editor = Editor(self) editor._load_file(filename) self.add(editor, text=editor.get_title()) return editor def get_editor(self, filename, open_when_necessary=False): if not is_remote_path(filename): filename = normpath_with_actual_case(os.path.abspath(filename)) for child in self.winfo_children(): child_filename = child.get_filename(False) if child_filename == filename: return child if open_when_necessary: return self._open_file(filename) else: return None def check_allow_closing(self, editor=None): if not editor: modified_editors = [e for e in self.winfo_children() if e.is_modified()] else: if not editor.is_modified(): return True else: modified_editors = [editor] if len(modified_editors) == 0: return True message = "Do you want to save files before closing?" if editor: message = "Do you want to save file before closing?" confirm = messagebox.askyesnocancel( title="Save On Close", message=message, default=messagebox.YES ) if confirm: for editor_ in modified_editors: if editor_.get_filename(True): editor_.save_file() else: return False return True elif confirm is None: return False else: return True def on_focus_window(self, event=None): for editor in self.get_all_editors(): editor.check_for_external_changes() def get_current_breakpoints(): result = {} for editor in get_workbench().get_editor_notebook().get_all_editors(): filename = editor.get_filename() if filename: linenos = editor.get_code_view().get_breakpoint_line_numbers() if linenos: result[filename] = linenos return result def get_saved_current_script_filename(force=True): editor = get_workbench().get_editor_notebook().get_current_editor() if not editor: return filename = editor.get_filename(force) if not filename: return if editor.is_modified(): filename = editor.save_file() return filename def is_remote_path(s): return REMOTE_PATH_MARKER in s def extract_target_path(s): assert is_remote_path(s) return s[s.find(REMOTE_PATH_MARKER) + len(REMOTE_PATH_MARKER) :] def make_remote_path(target_path): return get_runner().get_node_label() + REMOTE_PATH_MARKER + target_path thonny-3.2.7/thonny/running_config_page.py0000644000175000017500000002165213611773167021770 0ustar annamaaannamaa00000000000000import os.path import subprocess import tkinter as tk from shutil import which from tkinter import messagebox, ttk from thonny import get_workbench, running, ui_utils from thonny.common import normpath_with_actual_case from thonny.misc_utils import running_on_mac_os, running_on_windows from thonny.plugins.backend_config_page import BackendDetailsConfigPage from thonny.running import WINDOWS_EXE, get_interpreter_for_subprocess from thonny.ui_utils import SubprocessDialog, askdirectory, askopenfilename, create_string_var class SameAsFrontEndConfigurationPage(BackendDetailsConfigPage): def __init__(self, master): super().__init__(master) label = ttk.Label(self, text=get_interpreter_for_subprocess()) label.grid() def should_restart(self): return False class PrivateVenvConfigurationPage(BackendDetailsConfigPage): def __init__(self, master): super().__init__(master) text = ( _("This virtual environment is automatically maintained by Thonny.\n") + _("Location: ") + running.get_private_venv_path() ) label = ttk.Label(self, text=text) label.grid() def should_restart(self): return False class CustomCPythonConfigurationPage(BackendDetailsConfigPage): def __init__(self, master): super().__init__(master) self._configuration_variable = create_string_var( get_workbench().get_option("CustomInterpreter.path") ) entry_label = ttk.Label(self, text=_("Known interpreters")) entry_label.grid(row=0, column=0, columnspan=2, sticky=tk.W) self._entry = ttk.Combobox( self, exportselection=False, textvariable=self._configuration_variable, values=self._get_interpreters(), ) self._entry.grid(row=1, column=0, columnspan=2, sticky=tk.NSEW) self._entry.state(["!disabled", "readonly"]) another_label = ttk.Label(self, text=_("Your interpreter isn't in the list?")) another_label.grid(row=2, column=0, columnspan=2, sticky=tk.W, pady=(10, 0)) ttk.Style().configure("Centered.TButton", justify="center") self._select_button = ttk.Button( self, style="Centered.TButton", text=_("Locate another") + " " + ("python.exe ..." if running_on_windows() else _("python executable") + " ...") + "\n" + _("NB! Thonny only supports Python 3.5 and later"), command=self._select_executable, ) self._select_button.grid(row=3, column=0, columnspan=2, sticky=tk.NSEW) self._venv_button = ttk.Button( self, style="Centered.TButton", text=_("Create new virtual environment") + " ...\n" + "(" + _("Select existing or create a new empty directory") + ")", command=self._create_venv, ) self._venv_button.grid(row=4, column=0, columnspan=2, sticky=tk.NSEW, pady=(5, 0)) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) def _select_executable(self): # TODO: get dir of current interpreter options = {"master": self} if running_on_windows(): options["filetypes"] = [ (_("Python interpreters"), "python.exe"), (_("all files"), ".*"), ] filename = askopenfilename(**options) if filename: self._configuration_variable.set(filename) def _create_venv(self): path = None while True: path = askdirectory( master=self, initialdir=path, title=_("Select empty directory for new virtual environment"), ) if not path: return if os.listdir(path): messagebox.showerror( _("Bad directory"), _("Selected directory is not empty.\nSelect another or cancel."), ) else: break assert os.path.isdir(path) path = normpath_with_actual_case(path) proc = subprocess.Popen( [running.get_interpreter_for_subprocess(), "-m", "venv", path], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, ) dlg = SubprocessDialog(self, proc, _("Creating virtual environment")) ui_utils.show_dialog(dlg) if running_on_windows(): exe_path = normpath_with_actual_case(os.path.join(path, "Scripts", "python.exe")) else: exe_path = os.path.join(path, "bin", "python3") if os.path.exists(exe_path): self._configuration_variable.set(exe_path) def _get_interpreters(self): result = set() if running_on_windows(): # registry result.update(self._get_interpreters_from_windows_registry()) for minor in [5, 6, 7, 8]: for dir_ in [ "C:\\Python3%d" % minor, "C:\\Python3%d-32" % minor, "C:\\Python3%d-64" % minor, "C:\\Program Files\\Python 3.%d" % minor, "C:\\Program Files\\Python 3.%d-64" % minor, "C:\\Program Files (x86)\\Python 3.%d" % minor, "C:\\Program Files (x86)\\Python 3.%d-32" % minor, ]: path = os.path.join(dir_, WINDOWS_EXE) if os.path.exists(path): result.add(normpath_with_actual_case(path)) # other locations for dir_ in ["C:\\Anaconda3", os.path.expanduser("~/Anaconda3")]: path = os.path.join(dir_, WINDOWS_EXE) if os.path.exists(path): result.add(normpath_with_actual_case(path)) else: # Common unix locations dirs = ["/bin", "/usr/bin", "/usr/local/bin", os.path.expanduser("~/.local/bin")] for dir_ in dirs: # if the dir_ is just a link to another dir_, skip it # (not to show items twice) # for example on Fedora /bin -> usr/bin if not os.path.exists(dir_): continue apath = normpath_with_actual_case(dir_) if apath != dir_ and apath in dirs: continue for name in ["python3", "python3.5", "python3.6", "python3.7", "python3.8"]: path = os.path.join(dir_, name) if os.path.exists(path): result.add(path) if running_on_mac_os(): for version in ["3.5", "3.6", "3.7", "3.8"]: dir_ = os.path.join("/Library/Frameworks/Python.framework/Versions", version, "bin") path = os.path.join(dir_, "python3") if os.path.exists(path): result.add(path) for command in ["python3", "python3.5", "python3.5", "python3.6", "python3.7", "python3.8"]: path = which(command) if path is not None and os.path.isabs(path): result.add(path) for path in get_workbench().get_option("CustomInterpreter.used_paths"): if os.path.exists(path): result.add(normpath_with_actual_case(path)) return sorted(result) def _get_interpreters_from_windows_registry(self): # https://github.com/python/cpython/blob/master/Tools/msi/README.txt import winreg result = set() for key in [winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER]: for version in [ "3.5", "3.5-32", "3.5-64", "3.6", "3.6-32", "3.6-64", "3.7", "3.7-32", "3.7-64", "3.8", "3.8-32", "3.8-64", ]: try: for subkey in [ "SOFTWARE\\Python\\PythonCore\\" + version + "\\InstallPath", "SOFTWARE\\Python\\PythonCore\\Wow6432Node\\" + version + "\\InstallPath", ]: dir_ = winreg.QueryValue(key, subkey) if dir_: path = os.path.join(dir_, WINDOWS_EXE) if os.path.exists(path): result.add(path) except Exception: pass return result def should_restart(self): return self._configuration_variable.modified # pylint: disable=no-member def apply(self): if not self.should_restart(): return path = self._configuration_variable.get() if os.path.isfile(path): get_workbench().set_option("CustomInterpreter.path", path) thonny-3.2.7/thonny/first_run.py0000644000175000017500000000657613611773167020012 0ustar annamaaannamaa00000000000000import os.path import tkinter as tk from tkinter import ttk from thonny import ui_utils, languages, is_portable STD_MODE_TEXT = "Standard" RPI_MODE_TEXT = "Raspberry Pi" class FirstRunWindow(tk.Tk): def __init__(self, configuration_manager): super().__init__(className="Thonny") ttk.Style().theme_use(ui_utils.get_default_basic_theme()) self.title("Welcome to Thonny!" + " [portable]" if is_portable() else "") self.protocol("WM_DELETE_WINDOW", self.destroy) self.ok = False self.conf = configuration_manager self.main_frame = ttk.Frame(self) self.main_frame.grid(row=1, column=1, sticky="nsew") self.columnconfigure(1, weight=1) self.rowconfigure(1, weight=1) self.main_frame.rowconfigure(1, weight=1) logo_file = os.path.join(os.path.dirname(__file__), "res", "thonny.png") self.logo = tk.PhotoImage(file=logo_file) logo_label = ttk.Label(self.main_frame, image=self.logo) logo_label.grid(row=1, rowspan=3, column=1, sticky="nsew") self.padx = 50 self.pady = 50 self.language_variable = ui_utils.create_string_var( languages.BASE_LANGUAGE_NAME, self.on_change_language ) self.add_combo( 1, "Language:", self.language_variable, list(languages.LANGUAGES_DICT.values()) ) self.mode_variable = tk.StringVar(value=STD_MODE_TEXT) self.add_combo(2, "Initial settings:", self.mode_variable, [STD_MODE_TEXT, RPI_MODE_TEXT]) ok_button = ttk.Button(self.main_frame, text="Let's go!", command=self.on_ok) ok_button.grid( row=3, column=3, padx=(0, self.padx), pady=(self.pady * 0.7, self.pady), sticky="se" ) self.center() def on_change_language(self): print(self.language_variable.get()) def add_combo(self, row, label_text, variable, values): pady = 7 label = ttk.Label(self.main_frame, text=label_text) label.grid(row=row, column=2, sticky="sw", pady=(pady, 0)) combobox = ttk.Combobox( self.main_frame, exportselection=False, textvariable=variable, state="readonly", height=15, width=20, values=values, ) combobox.grid(row=row, column=3, padx=(10, self.padx), sticky="sw", pady=(pady, 0)) def center(self): width = max(self.winfo_reqwidth(), 640) height = max(self.winfo_reqheight(), 300) screen_width = self.winfo_screenwidth() screen_height = self.winfo_screenheight() if screen_width > screen_height * 2: # probably dual monitors screen_width //= 2 left = max(int(screen_width / 2 - width / 2), 0) top = max(int(screen_height / 2 - height / 2), 0) # Positions the window in the center of the page. self.geometry("+{}+{}".format(left, top)) def on_ok(self): if self.mode_variable.get() == RPI_MODE_TEXT: self.conf.set_option("debugger.preferred_debugger", "faster") self.conf.set_option("view.ui_theme", "Raspberry Pi") self.conf.set_option("general.ui_mode", "simple") self.conf.set_option( "general.language", languages.get_language_code_by_name(self.language_variable.get()) ) self.conf.save() self.ok = True self.destroy() thonny-3.2.7/thonny/tktextext.py0000644000175000017500000012407213611773167020033 0ustar annamaaannamaa00000000000000# coding=utf-8 """Extensions for tk.Text""" import platform import time import tkinter as tk import traceback from logging import exception from tkinter import TclError, messagebox from tkinter import font as tkfont from tkinter import ttk class TweakableText(tk.Text): """Allows intercepting Text commands at Tcl-level""" def __init__(self, master=None, cnf={}, read_only=False, **kw): super().__init__(master=master, cnf=cnf, **kw) self._read_only = read_only self._suppress_events = False self._original_widget_name = self._w + "_orig" self.tk.call("rename", self._w, self._original_widget_name) self.tk.createcommand(self._w, self._dispatch_tk_operation) self._tk_proxies = {} self._original_insert = self._register_tk_proxy_function("insert", self.intercept_insert) self._original_delete = self._register_tk_proxy_function("delete", self.intercept_delete) self._original_mark = self._register_tk_proxy_function("mark", self.intercept_mark) def _register_tk_proxy_function(self, operation, function): self._tk_proxies[operation] = function setattr(self, operation, function) def original_function(*args): self.tk.call((self._original_widget_name, operation) + args) return original_function def _dispatch_tk_operation(self, operation, *args): f = self._tk_proxies.get(operation) try: if f: return f(*args) else: return self.tk.call((self._original_widget_name, operation) + args) except TclError as e: # Some Tk internal actions (eg. paste and cut) can cause this error if ( str(e).lower() == '''text doesn't contain any characters tagged with "sel"''' and operation in ["delete", "index", "get"] and args in [("sel.first", "sel.last"), ("sel.first",)] ): pass else: exception( "[_dispatch_tk_operation] operation: " + operation + ", args:" + repr(args) ) # traceback.print_exc() return "" # Taken from idlelib.WidgetRedirector def set_read_only(self, value): self._read_only = value def is_read_only(self): return self._read_only def set_content(self, chars): self.direct_delete("1.0", tk.END) self.direct_insert("1.0", chars) def set_insertwidth(self, new_width): """Change cursor width NB! Need to be careful with setting text["insertwidth"]! My first straightforward solution caused unexplainable infinite loop of insertions and deletions in the text (Repro: insert a line and a word, select that word and then do Ctrl-Z). This solution seems safe but be careful! """ if self._suppress_events: return if self["insertwidth"] != new_width: old_suppress = self._suppress_events try: self._suppress_events = True self.config(insertwidth=new_width) finally: self._suppress_events = old_suppress def intercept_mark(self, *args): self.direct_mark(*args) def intercept_insert(self, index, chars, tags=None, **kw): assert isinstance(chars, str) if chars >= "\uf704" and chars <= "\uf70d": # Function keys F1..F10 in Mac cause these pass elif self.is_read_only(): self.bell() else: self.direct_insert(index, chars, tags, **kw) def intercept_delete(self, index1, index2=None, **kw): if index1 == "sel.first" and index2 == "sel.last" and not self.has_selection(): return if self.is_read_only(): self.bell() elif self._is_erroneous_delete(index1, index2): pass else: self.direct_delete(index1, index2, **kw) def _is_erroneous_delete(self, index1, index2): """Paste can cause deletes where index1 is sel.start but text has no selection. This would cause errors""" return index1.startswith("sel.") and not self.has_selection() def direct_mark(self, *args): self._original_mark(*args) if args[:2] == ("set", "insert") and not self._suppress_events: self.event_generate("<>") def index_sel_first(self): # Tk will give error without this check if self.tag_ranges("sel"): return self.index("sel.first") else: return None def index_sel_last(self): if self.tag_ranges("sel"): return self.index("sel.last") else: return None def has_selection(self): return len(self.tag_ranges("sel")) > 0 def get_selection_indices(self): # If a selection is defined in the text widget, return (start, # end) as Tkinter text indices, otherwise return (None, None) if self.has_selection(): return self.index("sel.first"), self.index("sel.last") else: return None, None def direct_insert(self, index, chars, tags=None, **kw): self._original_insert(index, chars, tags, **kw) if not self._suppress_events: self.event_generate("<>") def direct_delete(self, index1, index2=None, **kw): self._original_delete(index1, index2, **kw) if not self._suppress_events: self.event_generate("<>") class EnhancedText(TweakableText): """Text widget with extra navigation and editing aids. Provides more comfortable deletion, indentation and deindentation, and undo handling. Not specific to Python code. Most of the code is adapted from idlelib.EditorWindow. """ def __init__( self, master=None, style="Text", tag_current_line=False, indent_with_tabs=False, replace_tabs=False, cnf={}, **kw ): # Parent class shouldn't autoseparate # TODO: take client provided autoseparators value into account kw["autoseparators"] = False self._style = style self._original_options = kw.copy() super().__init__(master=master, cnf=cnf, **kw) self.tabwidth = 8 # See comments in idlelib.editor.EditorWindow self.indent_width = 4 self.indent_with_tabs = indent_with_tabs self.replace_tabs = replace_tabs self._last_event_kind = None self._last_key_time = None self._bind_editing_aids() self._bind_movement_aids() self._bind_selection_aids() self._bind_undo_aids() self._bind_mouse_aids() self._ui_theme_change_binding = self.bind( "<>", self._reload_theme_options, True ) self._initial_configuration = self.configure() self._regular_insertwidth = self["insertwidth"] self._reload_theme_options() self._should_tag_current_line = tag_current_line if tag_current_line: self.bind("<>", self._tag_current_line, True) self.bind("<>", self._tag_current_line, True) self._tag_current_line() def _bind_mouse_aids(self): if _running_on_mac(): self.bind("", self.on_secondary_click) self.bind("", self.on_secondary_click) else: self.bind("", self.on_secondary_click) def _bind_editing_aids(self): def if_not_readonly(fun): def dispatch(event): if not self.is_read_only(): return fun(event) else: return "break" return dispatch self.bind("", if_not_readonly(self.delete_word_left), True) self.bind("", if_not_readonly(self.delete_word_right), True) self.bind("", self._redirect_ctrld, True) self.bind("", self._redirect_ctrlt, True) self.bind("", if_not_readonly(self.perform_smart_backspace), True) self.bind("", if_not_readonly(self.perform_return), True) self.bind("", if_not_readonly(self.perform_return), True) self.bind("", if_not_readonly(self.perform_tab), True) try: # Is needed on eg. Ubuntu with Estonian keyboard self.bind("", if_not_readonly(self.perform_tab), True) except Exception: pass if platform.system() == "Windows": self.bind("", self._insert_untypable_characters_on_windows, True) def _bind_movement_aids(self): self.bind("", self.perform_smart_home, True) self.bind("", self.move_to_edge_if_selection(0), True) self.bind("", self.move_to_edge_if_selection(1), True) self.bind("", self.perform_page_down, True) self.bind("", self.perform_page_up, True) def _bind_selection_aids(self): self.bind("" if _running_on_mac() else "", self.select_all, True) def _bind_undo_aids(self): self.bind("<>", self._on_undo, True) self.bind("<>", self._on_redo, True) self.bind("<>", self._on_cut, True) self.bind("<>", self._on_copy, True) self.bind("<>", self._on_paste, True) self.bind("", self._on_get_focus, True) self.bind("", self._on_lose_focus, True) self.bind("", self._on_key_press, True) self.bind("<1>", self._on_mouse_click, True) self.bind("<2>", self._on_mouse_click, True) self.bind("<3>", self._on_mouse_click, True) if _running_on_x11() or _running_on_mac(): def custom_redo(event): self.event_generate("<>") return "break" self.bind("", custom_redo, True) def _redirect_ctrld(self, event): # I want to disable the deletion effect of Ctrl-D in the text but still # keep the event for other purposes self.event_generate("<>") return "break" def _redirect_ctrlt(self, event): # I want to disable the swap effect of Ctrl-T in the text but still # keep the event for other purposes self.event_generate("<>") return "break" def tag_reset(self, tag_name): empty_conf = {key: "" for key in self.tag_configure(tag_name)} self.tag_configure(empty_conf) def select_lines(self, first_line, last_line): self.tag_remove("sel", "1.0", tk.END) self.tag_add("sel", "%s.0" % first_line, "%s.end" % last_line) def delete_word_left(self, event): self.event_generate("") self.edit_separator() return "break" def delete_word_right(self, event): self.event_generate("") self.edit_separator() return "break" def perform_smart_backspace(self, event): self._log_keypress_for_undo(event) text = self first, last = self.get_selection_indices() if first and last: text.delete(first, last) text.mark_set("insert", first) return "break" # Delete whitespace left, until hitting a real char or closest # preceding virtual tab stop. chars = text.get("insert linestart", "insert") if chars == "": if text.compare("insert", ">", "1.0"): # easy: delete preceding newline text.delete("insert-1c") else: text.bell() # at start of buffer return "break" if ( chars.strip() != "" ): # there are non-whitespace chars somewhere to the left of the cursor # easy: delete preceding real char text.delete("insert-1c") self._log_keypress_for_undo(event) return "break" # Ick. It may require *inserting* spaces if we back up over a # tab character! This is written to be clear, not fast. have = len(chars.expandtabs(self.tabwidth)) assert have > 0 want = ((have - 1) // self.indent_width) * self.indent_width # Debug prompt is multilined.... # if self.context_use_ps1: # last_line_of_prompt = sys.ps1.split('\n')[-1] # else: last_line_of_prompt = "" ncharsdeleted = 0 while 1: if chars == last_line_of_prompt: break chars = chars[:-1] ncharsdeleted = ncharsdeleted + 1 have = len(chars.expandtabs(self.tabwidth)) if have <= want or chars[-1] not in " \t": break text.delete("insert-%dc" % ncharsdeleted, "insert") if have < want: text.insert("insert", " " * (want - have)) return "break" def perform_midline_tab(self, event=None): "autocompleter can put its magic here" # by default return self.perform_smart_tab(event) def perform_smart_tab(self, event=None): self._log_keypress_for_undo(event) # if intraline selection: # delete it # elif multiline selection: # do indent-region # else: # indent one level first, last = self.get_selection_indices() if first and last: if index2line(first) != index2line(last): return self.indent_region(event) self.delete(first, last) self.mark_set("insert", first) prefix = self.get("insert linestart", "insert") raw, effective = classifyws(prefix, self.tabwidth) if raw == len(prefix): # only whitespace to the left self._reindent_to(effective + self.indent_width) else: # tab to the next 'stop' within or to right of line's text: if self.indent_with_tabs: pad = "\t" else: effective = len(prefix.expandtabs(self.tabwidth)) n = self.indent_width pad = " " * (n - effective % n) self.insert("insert", pad) self.see("insert") return "break" def get_cursor_position(self): return map(int, self.index("insert").split(".")) def get_line_count(self): return list(map(int, self.index("end-1c").split(".")))[0] def perform_return(self, event): self.insert("insert", "\n") return "break" def perform_page_down(self, event): # if last line is visible then go to last line # (by default it doesn't move then) try: last_visible_idx = self.index("@0,%d" % self.winfo_height()) row, _ = map(int, last_visible_idx.split(".")) line_count = self.get_line_count() if row == line_count or row == line_count - 1: # otherwise tk doesn't show last line self.mark_set("insert", "end") except Exception: traceback.print_exc() def perform_page_up(self, event): # if first line is visible then go there # (by default it doesn't move then) try: first_visible_idx = self.index("@0,0") row, _ = map(int, first_visible_idx.split(".")) if row == 1: self.mark_set("insert", "1.0") except Exception: traceback.print_exc() def compute_smart_home_destination_index(self): """Is overridden in shell""" line = self.get("insert linestart", "insert lineend") for insertpt in range(len(line)): if line[insertpt] not in (" ", "\t"): break else: insertpt = len(line) lineat = int(self.index("insert").split(".")[1]) if insertpt == lineat: insertpt = 0 return "insert linestart+" + str(insertpt) + "c" def perform_smart_home(self, event): if (event.state & 4) != 0 and event.keysym == "Home": # state&4==Control. If , use the Tk binding. return None dest = self.compute_smart_home_destination_index() if (event.state & 1) == 0: # shift was not pressed self.tag_remove("sel", "1.0", "end") else: if not self.index_sel_first(): # there was no previous selection self.mark_set("my_anchor", "insert") else: if self.compare(self.index_sel_first(), "<", self.index("insert")): self.mark_set("my_anchor", "sel.first") # extend back else: self.mark_set("my_anchor", "sel.last") # extend forward first = self.index(dest) last = self.index("my_anchor") if self.compare(first, ">", last): first, last = last, first self.tag_remove("sel", "1.0", "end") self.tag_add("sel", first, last) self.mark_set("insert", dest) self.see("insert") return "break" def move_to_edge_if_selection(self, edge_index): """Cursor move begins at start or end of selection When a left/right cursor key is pressed create and return to Tkinter a function which causes a cursor move from the associated edge of the selection. """ def move_at_edge(event): if ( self.has_selection() and (event.state & 5) == 0 ): # no shift(==1) or control(==4) pressed try: self.mark_set("insert", ("sel.first+1c", "sel.last-1c")[edge_index]) except tk.TclError: pass return move_at_edge def perform_tab(self, event=None): self._log_keypress_for_undo(event) if event.state & 0x0001: # shift is pressed (http://stackoverflow.com/q/32426250/261181) return self.dedent_region(event) else: # check whether there are letters before cursor on this line index = self.index("insert") left_text = self.get(index + " linestart", index) if left_text.strip() == "" or self.has_selection(): return self.perform_smart_tab(event) else: return self.perform_midline_tab(event) def indent_region(self, event=None): return self._change_indentation(True) def dedent_region(self, event=None): return self._change_indentation(False) def _change_indentation(self, increase=True): head, tail, chars, lines = self._get_region() # Text widget plays tricks if selection ends on last line # and content doesn't end with empty line, text_last_line = index2line(self.index("end-1c")) sel_last_line = index2line(tail) if sel_last_line >= text_last_line: while not self.get(head, "end").endswith("\n\n"): self.insert("end", "\n") for pos in range(len(lines)): line = lines[pos] if line: raw, effective = classifyws(line, self.tabwidth) if increase: effective = effective + self.indent_width else: effective = max(effective - self.indent_width, 0) lines[pos] = self._make_blanks(effective) + line[raw:] self._set_region(head, tail, chars, lines) return "break" def select_all(self, event): self.tag_remove("sel", "1.0", tk.END) self.tag_add("sel", "1.0", tk.END) def set_read_only(self, value): if value == self.is_read_only(): return TweakableText.set_read_only(self, value) self._reload_theme_options() if self._should_tag_current_line: self._tag_current_line() def _reindent_to(self, column): # Delete from beginning of line to insert point, then reinsert # column logical (meaning use tabs if appropriate) spaces. if self.compare("insert linestart", "!=", "insert"): self.delete("insert linestart", "insert") if column: self.insert("insert", self._make_blanks(column)) def _get_region(self): first, last = self.get_selection_indices() if first and last: head = self.index(first + " linestart") tail = self.index(last + "-1c lineend +1c") else: head = self.index("insert linestart") tail = self.index("insert lineend +1c") chars = self.get(head, tail) lines = chars.split("\n") return head, tail, chars, lines def _set_region(self, head, tail, chars, lines): newchars = "\n".join(lines) if newchars == chars: self.bell() return self.tag_remove("sel", "1.0", "end") self.mark_set("insert", head) self.delete(head, tail) self.insert(head, newchars) self.tag_add("sel", head, "insert") def _log_keypress_for_undo(self, e): if e is None: return # NB! this may not execute if the event is cancelled in another handler event_kind = self._get_event_kind(e) if ( event_kind != self._last_event_kind or e.char in ("\r", "\n", " ", "\t") or e.keysym in ["Return", "KP_Enter"] or time.time() - self._last_key_time > 2 ): self.edit_separator() self._last_event_kind = event_kind self._last_key_time = time.time() def _get_event_kind(self, event): if event.keysym in ("BackSpace", "Delete"): return "delete" elif event.char: return "insert" else: # eg. e.keysym in ("Left", "Up", "Right", "Down", "Home", "End", "Prior", "Next"): return "other_key" def _make_blanks(self, n): # Make string that displays as n leading blanks. if self.indent_with_tabs: ntabs, nspaces = divmod(n, self.tabwidth) return "\t" * ntabs + " " * nspaces else: return " " * n def _on_undo(self, e): self._last_event_kind = "undo" def _on_redo(self, e): self._last_event_kind = "redo" def _on_cut(self, e): self._last_event_kind = "cut" self.edit_separator() def _on_copy(self, e): self._last_event_kind = "copy" self.edit_separator() def _on_paste(self, e): if self.is_read_only(): return try: if self.has_selection(): self.direct_delete("sel.first", "sel.last") except Exception: pass self._last_event_kind = "paste" self.edit_separator() self.see("insert") self.after_idle(lambda: self.see("insert")) def _on_get_focus(self, e): self._last_event_kind = "get_focus" self.edit_separator() def _on_lose_focus(self, e): self._last_event_kind = "lose_focus" self.edit_separator() def _on_key_press(self, e): return self._log_keypress_for_undo(e) def _on_mouse_click(self, event): self.edit_separator() def _tag_current_line(self, event=None): self.tag_remove("current_line", "1.0", "end") # Let's show current line only with readable text # (this fits well with Thonny debugger, # otherwise debugger focus box and current line interact in an ugly way) if self._should_tag_current_line and not self.is_read_only(): # we may be on the same line as with prev event but tag needs extension lineno = int(self.index("insert").split(".")[0]) self.tag_add("current_line", str(lineno) + ".0", str(lineno + 1) + ".0") def on_secondary_click(self, event=None): "Use this for invoking context menu" self.focus_set() if event: self.mark_set("insert", "@%d,%d" % (event.x, event.y)) def _reload_theme_options(self, event=None): style = ttk.Style() states = [] if self.is_read_only(): states.append("readonly") # Following crashes when a combobox is focused # if self.focus_get() == self: # states.append("focus") if "background" not in self._initial_configuration: background = style.lookup(self._style, "background", states) if background: self.configure(background=background) if "foreground" not in self._initial_configuration: foreground = style.lookup(self._style, "foreground", states) if foreground: self.configure(foreground=foreground) self.configure(insertbackground=foreground) def _insert_untypable_characters_on_windows(self, event): if event.state == 131084: # AltGr or Ctrl+Alt lang_id = get_keyboard_language() char = _windows_altgr_chars_by_lang_id_and_keycode.get(lang_id, {}).get( event.keycode, None ) if char is not None: self.insert("insert", char) def destroy(self): self.unbind("<>", self._ui_theme_change_binding) super().destroy() def direct_insert(self, index, chars, tags=None, **kw): chars = self.check_convert_tabs_to_spaces(chars) super().direct_insert(index, chars, tags, **kw) def check_convert_tabs_to_spaces(self, chars): if not self.replace_tabs: return chars tab_count = chars.count("\t") if tab_count == 0: return chars else: if messagebox.askyesno( "Convert tabs to spaces?", "Thonny (according to Python recommendation) uses spaces for indentation, " + "but the text you are about to insert/open contains %d tab characters. " % tab_count + "To avoid confusion, it's better to convert them into spaces (unless you know they should be kept as tabs).\n\n" + "Do you want me to replace each tab with %d spaces?\n\n" % self.indent_width, ): return chars.expandtabs(self.indent_width) else: return chars class TextFrame(ttk.Frame): "Decorates text with scrollbars, listens for theme changes" def __init__( self, master, text_class=EnhancedText, horizontal_scrollbar=True, vertical_scrollbar=True, vertical_scrollbar_class=ttk.Scrollbar, horizontal_scrollbar_class=ttk.Scrollbar, vertical_scrollbar_style=None, horizontal_scrollbar_style=None, borderwidth=0, relief="sunken", **text_options ): ttk.Frame.__init__(self, master=master, borderwidth=borderwidth, relief=relief) final_text_options = { "borderwidth": 0, "insertwidth": 2, "spacing1": 0, "spacing3": 0, "highlightthickness": 0, "inactiveselectbackground": "gray", "padx": 5, "pady": 5, } final_text_options.update(text_options) self.text = text_class(self, **final_text_options) self.text.grid(row=0, column=2, sticky=tk.NSEW) if vertical_scrollbar: self._vbar = vertical_scrollbar_class( self, orient=tk.VERTICAL, style=vertical_scrollbar_style ) self._vbar.grid(row=0, column=3, sticky=tk.NSEW) self._vbar["command"] = self._vertical_scroll self.text["yscrollcommand"] = self._vertical_scrollbar_update if horizontal_scrollbar: self._hbar = horizontal_scrollbar_class( self, orient=tk.HORIZONTAL, style=horizontal_scrollbar_style ) self._hbar.grid(row=1, column=0, sticky=tk.NSEW, columnspan=3) self._hbar["command"] = self._horizontal_scroll self.text["xscrollcommand"] = self._horizontal_scrollbar_update self.columnconfigure(2, weight=1) self.rowconfigure(0, weight=1) self._ui_theme_change_binding = self.bind( "<>", self._reload_theme_options, True ) # TODO: add context menu? self._reload_theme_options(None) def focus_set(self): self.text.focus_set() def _vertical_scrollbar_update(self, *args): if not hasattr(self, "_vbar"): return self._vbar.set(*args) self.text.event_generate("<>") def _horizontal_scrollbar_update(self, *args): self._hbar.set(*args) def _vertical_scroll(self, *args): self.text.yview(*args) self.text.event_generate("<>") def _horizontal_scroll(self, *args): self.text.xview(*args) def _reload_theme_options(self, event=None): pass def destroy(self): self.unbind("<>", self._ui_theme_change_binding) super().destroy() class EnhancedTextFrame(TextFrame): "Adds line numbers and print margin" def __init__( self, master, line_numbers=False, line_length_margin=0, first_line_number=1, text_class=EnhancedText, horizontal_scrollbar=True, vertical_scrollbar=True, vertical_scrollbar_class=ttk.Scrollbar, horizontal_scrollbar_class=ttk.Scrollbar, vertical_scrollbar_style=None, horizontal_scrollbar_style=None, borderwidth=0, relief="sunken", gutter_background="#e0e0e0", gutter_foreground="#999999", **text_options ): self._gutter = None super().__init__( master, text_class=text_class, horizontal_scrollbar=horizontal_scrollbar, vertical_scrollbar=vertical_scrollbar, vertical_scrollbar_class=vertical_scrollbar_class, horizontal_scrollbar_class=horizontal_scrollbar_class, vertical_scrollbar_style=vertical_scrollbar_style, horizontal_scrollbar_style=horizontal_scrollbar_style, borderwidth=borderwidth, relief=relief, **text_options ) self._recommended_line_length = line_length_margin self._gutter = tk.Text( self, width=5, padx=0, pady=5, highlightthickness=0, bd=0, takefocus=False, font=self.text["font"], background="#e0e0e0", foreground=gutter_foreground, selectbackground=gutter_background, selectforeground=gutter_foreground, cursor="arrow", state="disabled", undo=False, wrap="none", ) if "height" in text_options: self._gutter.configure(height=text_options["height"]) self._gutter_is_gridded = False self._gutter.bind("", self.on_gutter_double_click, True), self._gutter.bind("", self.on_gutter_click, True) self._gutter.bind("", self.on_gutter_click, True) self._gutter.bind("", self.on_gutter_motion, True) self._gutter["yscrollcommand"] = self._gutter_scroll # need tags for justifying and rmargin self._gutter.tag_configure("content", justify="right", rmargin=3) # gutter will be gridded later assert first_line_number is not None self._first_line_number = first_line_number self.set_gutter_visibility(line_numbers) margin_line_color = ttk.Style().lookup("Gutter", "background", default="LightGray") self._margin_line = tk.Canvas( self.text, borderwidth=0, width=1, height=2000, highlightthickness=0, background=margin_line_color, ) self.update_margin_line() self.text.bind("<>", self._text_changed, True) self.text.bind("<>", self._cursor_moved, True) self._reload_gutter_theme_options() def set_gutter_visibility(self, value): if value and not self._gutter_is_gridded: self._gutter.grid(row=0, column=0, sticky=tk.NSEW) self._gutter_is_gridded = True elif not value and self._gutter_is_gridded: self._gutter.grid_forget() self._gutter_is_gridded = False else: return """ # insert first line number (NB! Without trailing linebreak. See update_gutter) self._gutter.config(state="normal") self._gutter.delete("1.0", "end") for content, tags in self.compute_gutter_line(self._first_line_number): self._gutter.insert("end", content, ("content",) + tags) self._gutter.config(state="disabled") """ self.update_gutter(True) def set_line_length_margin(self, value): self._recommended_line_length = value self.update_margin_line() def _gutter_scroll(self, *args): if not hasattr(self, "_vbar"): return try: self._vbar.set(*args) self.text.yview(tk.MOVETO, args[0]) except TclError: pass def _text_changed(self, event): self.update_gutter() def _cursor_moved(self, event): self._update_gutter_active_line() def update_gutter(self, clean=False): if clean: self._gutter.config(state="normal") self._gutter.delete("1.0", "end") # need to add first item separately, because Text can't report 0 rows for content, tags in self.compute_gutter_line(self._first_line_number): self._gutter.insert("end-1c", content, tags + ("content",)) self._gutter.config(state="disabled") text_line_count = int(self.text.index("end").split(".")[0]) gutter_line_count = int(self._gutter.index("end").split(".")[0]) if text_line_count != gutter_line_count: self._gutter.config(state="normal") # NB! Text acts weird with last symbol # (don't really understand whether it automatically keeps a newline there or not) # Following seems to ensure both Text-s have same height if text_line_count > gutter_line_count: delta = text_line_count - gutter_line_count start = gutter_line_count + self._first_line_number - 1 if not clean and text_line_count > 10 and gutter_line_count < 3: # probably initial load, do bulk insert parts = [] for i in range(start, start + delta): parts.append("\n") for content, tags in self.compute_gutter_line(i, plain=True): parts.append(content) self._gutter.insert("end-1c", "".join(parts), ("content",) + tags) else: for i in range(start, start + delta): self._gutter.insert("end-1c", "\n", ("content",)) for content, tags in self.compute_gutter_line(i): self._gutter.insert("end-1c", content, ("content",) + tags) else: self._gutter.delete(line2index(text_line_count) + "-1c", "end-1c") self._gutter.config(state="disabled") # synchronize gutter scroll position with text # https://mail.python.org/pipermail/tkinter-discuss/2010-March/002197.html first, _ = self.text.yview() self._gutter.yview_moveto(first) self._update_gutter_active_line() if text_line_count > 9998: self._gutter.configure(width=7) elif text_line_count > 998: self._gutter.configure(width=6) def _update_gutter_active_line(self): self._gutter.tag_remove("active", "1.0", "end") insert = self.text.index("insert") self._gutter.tag_add("active", insert + " linestart", insert + " lineend") def compute_gutter_line(self, lineno, plain=False): yield str(lineno), () def update_margin_line(self): if self._recommended_line_length == 0: self._margin_line.place_forget() else: try: self.text.update_idletasks() # How far left has text been scrolled first_visible_idx = self.text.index("@0,0") first_visible_col = int(first_visible_idx.split(".")[1]) bbox = self.text.bbox(first_visible_idx) first_visible_col_x = bbox[0] margin_line_visible_col = self._recommended_line_length - first_visible_col delta = first_visible_col_x except Exception: # fall back to ignoring scroll position margin_line_visible_col = self._recommended_line_length delta = 0 if margin_line_visible_col > -1: x = ( get_text_font(self.text).measure((margin_line_visible_col - 1) * "M") + delta + self.text["padx"] ) else: x = -10 # print(first_visible_col, first_visible_col_x) self._margin_line.place(y=-10, x=x) def on_gutter_click(self, event=None): try: linepos = self._gutter.index("@%s,%s" % (event.x, event.y)).split(".")[0] self.text.mark_set("insert", "%s.0" % linepos) self._gutter.mark_set("gutter_selection_start", "%s.0" % linepos) if ( event.type == "4" ): # In Python 3.6 you can use tk.EventType.ButtonPress instead of "4" self.text.tag_remove("sel", "1.0", "end") except tk.TclError: exception("on_gutter_click") def on_gutter_double_click(self, event=None): try: self._gutter.mark_unset("gutter_selection_start") self.text.tag_remove("sel", "1.0", "end") self._gutter.tag_remove("sel", "1.0", "end") except tk.TclError: exception("on_gutter_click") def on_gutter_motion(self, event=None): try: if "gutter_selection_start" not in self._gutter.mark_names(): return linepos = int(self._gutter.index("@%s,%s" % (event.x, event.y)).split(".")[0]) gutter_selection_start = int(self._gutter.index("gutter_selection_start").split(".")[0]) self.text.select_lines( min(gutter_selection_start, linepos), max(gutter_selection_start - 1, linepos - 1) ) self.text.mark_set("insert", "%s.0" % linepos) except tk.TclError: exception("on_gutter_motion") def _vertical_scrollbar_update(self, *args): if not hasattr(self, "_vbar"): return super()._vertical_scrollbar_update(*args) self._gutter.yview(tk.MOVETO, args[0]) def _horizontal_scrollbar_update(self, *args): super()._horizontal_scrollbar_update(*args) self.update_margin_line() def _vertical_scroll(self, *args): super()._vertical_scroll(*args) self._gutter.yview(*args) def _horizontal_scroll(self, *args): super()._horizontal_scroll(*args) self.update_margin_line() def _reload_theme_options(self, event=None): super()._reload_theme_options(event) if self._gutter is not None: self._reload_gutter_theme_options(event) def _reload_gutter_theme_options(self, event=None): style = ttk.Style() background = style.lookup("GUTTER", "background") if background: self._gutter.configure(background=background, selectbackground=background) self._margin_line.configure(background=background) foreground = style.lookup("GUTTER", "foreground") if foreground: self._gutter.configure(foreground=foreground, selectforeground=foreground) def get_text_font(text): font = text["font"] if isinstance(font, str): return tkfont.nametofont(font) else: return font def classifyws(s, tabwidth): raw = effective = 0 for ch in s: if ch == " ": raw = raw + 1 effective = effective + 1 elif ch == "\t": raw = raw + 1 effective = (effective // tabwidth + 1) * tabwidth else: break return raw, effective def index2line(index): return int(float(index)) def line2index(line): return str(float(line)) def fixwordbreaks(root): # Adapted from idlelib.EditorWindow (Python 3.4.2) # Modified to include non-ascii chars # Make sure that Tk's double-click and next/previous word # operations use our definition of a word (i.e. an identifier) root.tk.call("tcl_wordBreakAfter", "a b", 0) # make sure word.tcl is loaded root.tk.call("set", "tcl_wordchars", r"\w") root.tk.call("set", "tcl_nonwordchars", r"\W") def rebind_control_a(root): # Tk 8.6 has <> event but 8.5 doesn't # http://stackoverflow.com/questions/22907200/remap-default-keybinding-in-tkinter def control_a(event): widget = event.widget if isinstance(widget, tk.Text): widget.tag_remove("sel", "1.0", "end") widget.tag_add("sel", "1.0", "end") root.bind_class("Text", "", control_a) def _running_on_mac(): return tk._default_root.call("tk", "windowingsystem") == "aqua" def _running_on_x11(): return tk._default_root.call("tk", "windowingsystem") == "x11" def get_keyboard_language(): # https://stackoverflow.com/a/42047820/261181 if platform.system() != "Windows": raise NotImplementedError("Can provide keyboard language only on Windows") import ctypes user32 = ctypes.WinDLL("user32", use_last_error=True) curr_window = user32.GetForegroundWindow() thread_id = user32.GetWindowThreadProcessId(curr_window, 0) # Made up of 0xAAABBBB, AAA = HKL (handle object) & BBBB = language ID klid = user32.GetKeyboardLayout(thread_id) # Language ID -> low 10 bits, Sub-language ID -> high 6 bits # Extract language ID from KLID lid = klid & (2 ** 16 - 1) return lid _windows_altgr_chars_by_lang_id_and_keycode = { # https://docs.microsoft.com/en-us/windows/desktop/intl/language-identifier-constants-and-strings 0x0425: {191: "^"} # AltGr+Ä } thonny-3.2.7/thonny/VERSION0000644000175000017500000000000513611777123016446 0ustar annamaaannamaa000000000000003.2.7thonny-3.2.7/thonny/config.py0000644000175000017500000001754113611773167017236 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import ast import sys import configparser import datetime import os.path import tkinter as tk from configparser import ConfigParser from logging import exception import shutil from thonny import THONNY_USER_DIR import traceback _manager_cache = {} def try_load_configuration(filename): if filename in _manager_cache: return _manager_cache[filename] try: # use cache so Workbench doesn't create duplicate manager # when FirstRunWindow already created one mgr = ConfigurationManager(filename) _manager_cache[filename] = mgr return mgr except configparser.Error: from tkinter import messagebox if os.path.exists(filename) and messagebox.askyesno( "Problem", "Thonny's configuration file can't be read. It may be corrupt.\n\n" + "Do you want to discard the file and open Thonny with default settings?", ): os.replace(filename, filename + "_corrupt") # For some reasons Thonny styles are not loaded properly once messagebox has been shown before main window (At least Windows Py 3.5) raise SystemExit("Configuration file has been discarded. Please restart Thonny!") else: raise class ConfigurationManager: def __init__(self, filename): self._ini = ConfigParser(interpolation=None) self._filename = filename self._defaults = {} self._defaults_overrides_str = {} self._variables = {} # Tk variables if os.path.exists(self._filename): with open(self._filename, "r", encoding="UTF-8") as fp: self._ini.read_file(fp) else: # For migration to new conf directory # only if not in venv if not ( hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix or hasattr(sys, "real_prefix") and getattr(sys, "real_prefix") != sys.prefix ): old_user_dir = os.path.join(os.path.expanduser("~"), ".thonny") old_config_file = os.path.join(old_user_dir, "configuration.ini") if os.path.exists(old_config_file): with open(old_config_file, "r", encoding="UTF-8") as fp: self._ini.read_file(fp) self.set_option("run.backend_name", "SameAsFrontend") # migrate user_logs # (I know, it's not proper place for this code, but ...) old_user_logs = os.path.join(old_user_dir, "user_logs") new_user_logs = os.path.join(THONNY_USER_DIR, "user_logs") if os.path.exists(old_user_logs) and not os.path.exists(new_user_logs): try: shutil.copytree(old_user_logs, new_user_logs) except Exception: traceback.print_exc() if not self.get_option("general.configuration_creation_timestamp"): self.set_option( "general.configuration_creation_timestamp", datetime.datetime.now().isoformat() ) # print(prefs_filename, self.sections()) self._init_default_overrides() def _init_default_overrides(self): overrides_path = os.path.join(os.path.dirname(__file__), "defaults.ini") if not os.path.isfile(overrides_path): return defparser = configparser.ConfigParser() defparser.read(overrides_path, "utf-8") for section in defparser.sections(): for key in defparser[section]: # leave parsing until base default value is known self._defaults_overrides_str[section + "." + key] = defparser[section][key] def get_option(self, name, secondary_default=None): section, option = self._parse_name(name) name = section + "." + option # variable may have more recent value if name in self._variables: return self._variables[name].get() try: val = self._ini.get(section, option) # if option's data type is str (inferred from the default value) # then don't try to parse anything if isinstance(self._defaults.get(name), str): return val else: return self._parse_value(val) except Exception: if name in self._defaults: return self._defaults[name] else: return secondary_default def has_option(self, name): return name in self._defaults def set_option(self, name, value): section, option = self._parse_name(name) name = section + "." + option if not self._ini.has_section(section): self._ini.add_section(section) if isinstance(value, str): self._ini.set(section, option, value) else: self._ini.set(section, option, repr(value)) # update variable if name in self._variables: self._variables[name].set(value) def set_default(self, name, primary_default_value): # normalize name section, option = self._parse_name(name) name = section + "." + option self._defaults[name] = primary_default_value return if name in self._defaults_overrides_str: if isinstance(primary_default_value, str): value = self._defaults_overrides_str[name] else: value = self._parse_value(self._defaults_overrides_str[name]) else: value = primary_default_value self._defaults[name] = value def get_variable(self, name: str) -> tk.Variable: section, option = self._parse_name(name) name = section + "." + option if name in self._variables: return self._variables[name] else: value = self.get_option(name) if isinstance(value, bool): var = tk.BooleanVar(value=value) # type: tk.Variable elif isinstance(value, int): var = tk.IntVar(value=value) elif isinstance(value, str): var = tk.StringVar(value=value) elif isinstance(value, float): var = tk.StringVar(value=value) else: raise KeyError( "Can't create Tk Variable for " + name + ". Type is " + str(type(value)) ) self._variables[name] = var return var def save(self): # save all tk variables for name in self._variables: self.set_option(name, self._variables[name].get()) # store if not os.path.exists(self._filename): os.makedirs(os.path.dirname(self._filename), mode=0o700, exist_ok=True) # Normal saving occasionally creates corrupted file: # https://bitbucket.org/plas/thonny/issues/167/configuration-file-occasionally-gets # Now I'm saving the configuration to a temp file # and if the save is successful, I replace configuration file with it temp_filename = self._filename + ".temp" with open(temp_filename, "w", encoding="UTF-8") as fp: self._ini.write(fp) try: ConfigurationManager(temp_filename) # temp file was created successfully os.chmod(temp_filename, 0o600) os.replace(temp_filename, self._filename) os.chmod(self._filename, 0o600) except Exception: exception("Could not save configuration file. Reverting to previous file.") def _parse_name(self, name): if "." in name: return name.split(".", 1) else: return "general", name def _parse_value(self, value): try: return ast.literal_eval(value) except Exception: return value thonny-3.2.7/thonny/gridtable.py0000644000175000017500000002231013611773167017714 0ustar annamaaannamaa00000000000000import math import tkinter as tk from tkinter import ttk from thonny import get_workbench class GridTable(tk.Frame): def __init__(self, master, header_rows, data_row_count, footer_row_count, frozen_column_count): super().__init__(master) self.header_widgets = {} self.data_widgets = {} self.bind("", self.on_configure, True) self.screen_row_height = 22 # TODO: self.first_visible_data_row_no = 0 self.visible_data_row_count = 0 self.header_rows = header_rows self.data_rows = {} self.screen_row_count = 0 self.data_row_count = data_row_count self.column_count = len(self.header_rows[-1]) self.header_row_count = len(header_rows) self.footer_row_count = footer_row_count self.frozen_column_count = frozen_column_count self.update_header_rows() def set_data(self, data_rows): # self.data_rows.update(data_rows) # dict version self.data_rows = data_rows self.data_row_count = len(data_rows) self.update_screen_data() def update_header_rows(self): for row_no in range(self.header_row_count): for col_no in range(self.column_count): w = self.get_header_widget(self.screen_row_count, col_no) w.grid(row=row_no, column=col_no, sticky="nsew", pady=(0, 1), padx=(0, 1)) w.configure(text=self.get_header_value(row_no, col_no)) self.screen_row_count = self.header_row_count def get_data_widget(self, screen_row_no, col_no): if (screen_row_no, col_no) not in self.data_widgets: self.data_widgets[(screen_row_no, col_no)] = self.create_data_widget(col_no) return self.data_widgets[(screen_row_no, col_no)] def get_header_widget(self, row_no, col_no): if (row_no, col_no) not in self.header_widgets: self.header_widgets[(row_no, col_no)] = self.create_header_widget(col_no) return self.header_widgets[(row_no, col_no)] def create_data_widget(self, col_no): if col_no < self.frozen_column_count: background = None else: background = "white" return tk.Label(self, background=background, anchor="e", padx=7, text="") def create_header_widget(self, col_no): return tk.Label(self, anchor="e", padx=7, text="") def set_first_visible_data_row_no(self, n): self.first_visible_data_row_no = max(min(n, self.data_row_count), 0) self.update_screen_data() def _clear_screen_row(self, row_no): for widget in self.grid_slaves(row=row_no): widget.grid_remove() def update_screen_widgets(self, available_screen_height): max_screen_rows = available_screen_height // self.screen_row_height target_screen_row_count = max( min( max_screen_rows, self.header_row_count + self.data_row_count + self.footer_row_count - self.first_visible_data_row_no, ), self.header_row_count + 1 + self.footer_row_count, ) # target_screen_row_count = 30 # remove cells not required anymore ... while self.screen_row_count > target_screen_row_count: # print("removing") self._clear_screen_row(self.screen_row_count - 1) self.screen_row_count -= 1 # ... or add cells that can be shown while self.screen_row_count < target_screen_row_count: # print("adding") for col in range(self.column_count): w = self.get_data_widget(self.screen_row_count, col) w.grid( row=self.screen_row_count, column=col, sticky="nsew", pady=(0, 1), padx=(0, 1) ) self.screen_row_count += 1 self.visible_data_row_count = ( self.screen_row_count - self.header_row_count - self.footer_row_count ) def update_screen_data(self): self.update_screen_widgets(self.winfo_height()) for screen_row_no in range(self.header_row_count, self.screen_row_count): data_row_no = self.first_visible_data_row_no + screen_row_no - self.header_row_count if data_row_no == self.data_row_count: break for col_no in range(self.column_count): w = self.get_data_widget(screen_row_no, col_no) value = self.get_data_value(data_row_no, col_no) if value is None: w.configure(text="") else: w.configure(text=str(value)) def get_data_value(self, row_no, col_no): """ lazy dict version: assert 0 <= row_no < self.data_row_count if row_no in self.data_rows: return self.data_rows[row_no][col_no] else: return "" """ return self.data_rows[row_no][col_no] def get_header_value(self, row_no, col_no): return self.header_rows[row_no][col_no] def on_configure(self, event): # query row height _, _, _, height = self.grid_bbox(row=1) if height > 10 and height < 100: "self.screen_row_height = height + 2" # screen_available_height = self.winfo_height() # print("HE", self.winfo_height(), event.height, self.screen_row_height) self.update_screen_widgets(event.height) self.update_screen_data() class ScrollableGridTable(ttk.Frame): def __init__(self, master, header_rows, data_row_count, footer_row_count, frozen_column_count): ttk.Frame.__init__(self, master) # set up scrolling with canvas hscrollbar = ttk.Scrollbar(self, orient=tk.HORIZONTAL) self.canvas = tk.Canvas(self, bd=0, highlightthickness=0, xscrollcommand=hscrollbar.set) get_workbench().bind_all("", self.debug) self.create_infopanel(data_row_count) hscrollbar.config(command=self.canvas.xview) self.canvas.xview_moveto(0) self.canvas.yview_moveto(0) self.canvas.grid(row=0, column=0, columnspan=2, sticky=tk.NSEW) self.infopanel.grid(row=1, column=0, sticky=tk.NSEW) hscrollbar.grid(row=1, column=1, sticky=tk.NSEW) # vertical scrollbar performs virtual scrolling self.vscrollbar = ttk.Scrollbar( self, orient=tk.VERTICAL, command=self._handle_vertical_scroll ) self.vscrollbar.grid(row=0, column=2, sticky=tk.NSEW) self.columnconfigure(1, weight=1) self.rowconfigure(0, weight=1) self.interior = ttk.Frame(self.canvas) self.interior.columnconfigure(0, weight=1) self.interior.rowconfigure(0, weight=1) self.interior_id = self.canvas.create_window(0, 0, window=self.interior, anchor=tk.NW) self.bind("", self._configure_interior, True) self.bind("", self._on_expose, True) self.grid_table = GridTable( self.interior, header_rows, data_row_count, footer_row_count, frozen_column_count ) self.grid_table.grid(row=0, column=0, sticky=tk.NSEW) self._update_vertical_scrollbar() def debug(self, event=None): print("DE", self.vscrollbar.get()) def create_infopanel(self, data_row_count): self.infopanel = ttk.Frame(self) self.size_label = ttk.Label(self.infopanel, text=str(data_row_count) + " rows") self.size_label.grid(row=0, column=0, padx=5) def _update_vertical_scrollbar(self): first = self.grid_table.first_visible_data_row_no / self.grid_table.data_row_count last = first + self.grid_table.visible_data_row_count / self.grid_table.data_row_count # print(first, last, self.grid_table.visible_data_row_count) self.vscrollbar.set(first, last) def _handle_vertical_scroll(self, *args): # print("vscroll", args, self.vscrollbar.get()) if len(args) == 3 and args[0] == "scroll": amount = int(args[1]) unit = args[2] if unit == "pages": amount *= self.grid_table.visible_data_row_count self.grid_table.set_first_visible_data_row_no( self.grid_table.first_visible_data_row_no + amount ) else: assert args[0] == "moveto" pos = max(min(float(args[1]), 1.0), 0.0) top_row = math.floor( (self.grid_table.data_row_count - self.grid_table.visible_data_row_count + 1) * pos ) self.grid_table.set_first_visible_data_row_no(top_row) self._update_vertical_scrollbar() def _on_expose(self, event): self.update_idletasks() self._configure_interior(event) def _configure_interior(self, event): # update the scrollbars to match the size of the inner frame size = (self.interior.winfo_reqwidth(), self.canvas.winfo_height()) self.canvas.config(scrollregion="0 0 %s %s" % size) if ( self.interior.winfo_reqheight() != self.canvas.winfo_height() and self.canvas.winfo_height() > 10 ): # update the interior's height to fit canvas self.canvas.itemconfigure(self.interior_id, height=self.canvas.winfo_height()) self._update_vertical_scrollbar() thonny-3.2.7/thonny/rst_utils.py0000644000175000017500000003563113611773167020021 0ustar annamaaannamaa00000000000000import logging import tkinter as tk import docutils.core import docutils.nodes from thonny import get_workbench, ui_utils from thonny.codeview import get_syntax_options_for_tag from thonny.tktextext import TweakableText import traceback class RstText(TweakableText): def __init__(self, master=None, cnf={}, read_only=False, **kw): super().__init__( master=master, cnf=cnf, read_only=read_only, **{ "font": "TkDefaultFont", # "cursor" : "", **kw, } ) self.configure_tags() self._visitor = None def configure_tags(self): main_font = tk.font.nametofont("TkDefaultFont") bold_font = main_font.copy() bold_font.configure(weight="bold", size=main_font.cget("size")) italic_font = main_font.copy() italic_font.configure(slant="italic", size=main_font.cget("size")) h1_font = main_font.copy() h1_font.configure(size=main_font.cget("size") * 2, weight="bold") h2_font = main_font.copy() h2_font.configure(size=round(main_font.cget("size") * 1.5), weight="bold") h3_font = main_font.copy() h3_font.configure(size=main_font.cget("size"), weight="bold") small_font = main_font.copy() small_font.configure(size=round(main_font.cget("size") * 0.8)) small_italic_font = italic_font.copy() small_italic_font.configure(size=round(main_font.cget("size") * 0.8)) # Underline on font looks better than underline on tag underline_font = main_font.copy() underline_font.configure(underline=True) self.tag_configure("h1", font=h1_font, spacing3=5) self.tag_configure("h2", font=h2_font, spacing3=5) self.tag_configure("h3", font=h3_font, spacing3=5) self.tag_configure("p", spacing1=0, spacing3=10, spacing2=0) self.tag_configure("line_block", spacing1=0, spacing3=10, spacing2=0) self.tag_configure("em", font=italic_font) self.tag_configure("strong", font=bold_font) # TODO: hyperlink syntax options may require different background as well self.tag_configure( "a", **{**get_syntax_options_for_tag("hyperlink"), "underline": False}, font=underline_font ) self.tag_configure("small", font=small_font) self.tag_configure("light", foreground="gray") self.tag_configure("remark", font=small_italic_font) self.tag_bind("a", "", self._hyperlink_enter) self.tag_bind("a", "", self._hyperlink_leave) self.tag_configure("topic_title", lmargin2=16, font=bold_font) self.tag_configure("topic_body", lmargin1=16, lmargin2=16) self.tag_configure( "code", font="TkFixedFont", # wrap="none", # TODO: needs automatic hor-scrollbar and better padding mgmt # background="#eeeeee" ) # if ui_utils.get_tk_version_info() >= (8,6,6): # self.tag_configure("code", lmargincolor=self["background"]) for i in range(1, 6): self.tag_configure("list%d" % i, lmargin1=i * 10, lmargin2=i * 10 + 10) toti_code_font = bold_font.copy() toti_code_font.configure( family=tk.font.nametofont("TkFixedFont").cget("family"), size=bold_font.cget("size") ) self.tag_configure("topic_title_code", font=toti_code_font) self.tag_raise("topic_title_code", "code") self.tag_raise("topic_title_code", "topic_title") self.tag_raise("a", "topic_title") # TODO: topic_title + em self.tag_raise("em", "topic_title") self.tag_raise("a", "em") self.tag_raise("a", "topic_body") self.tag_raise("a", "topic_title") if ui_utils.get_tk_version_info() >= (8, 6, 6): self.tag_configure("sel", lmargincolor=self["background"]) self.tag_raise("sel") def clear(self): self.direct_delete("1.0", "end") def load_rst(self, rst_source, global_tags=()): self.clear() self.append_rst(rst_source, global_tags) def append_rst(self, rst_source, global_tags=()): try: doc = docutils.core.publish_doctree(rst_source) doc.walkabout(self.create_visitor(doc, global_tags)) except Exception: self.direct_insert("end", "RST SOURCE:\n" + rst_source + "\n\n") self.direct_insert("end", traceback.format_exc()) # For debugging: # self.direct_insert("end", doc.pformat()) # self.direct_insert("end", rst_source) def create_visitor(self, doc, global_tags=()): # Pass unique tag count from previous visitor # to keep uniqueness if self._visitor is None: unique_tag_count = 0 else: unique_tag_count = self._visitor.unique_tag_count self._visitor = TkTextRenderingVisitor(doc, self, global_tags, unique_tag_count) return self._visitor def _hyperlink_enter(self, event): self.config(cursor="hand2") def _hyperlink_leave(self, event): self.config(cursor="xterm") class TkTextRenderingVisitor(docutils.nodes.GenericNodeVisitor): def __init__(self, document, text, global_tags=(), unique_tag_count=0): super().__init__(document) self._context_tags = list(global_tags) self.text = text self.section_level = 0 self.in_topic = False self.in_paragraph = False self.in_title = False self.active_lists = [] self.unique_tag_count = unique_tag_count def visit_document(self, node): pass def visit_Text(self, node): self._append_text(self._node_to_text(node)) def visit_section(self, node): self.section_level += 1 def depart_section(self, node): self.section_level -= 1 def _get_title_tag(self): if self.in_topic: return "topic_title" else: return "h%d" % (self.section_level + 1) def visit_title(self, node): self.in_title = True self._add_tag(self._get_title_tag()) def depart_title(self, node): self.in_title = False self._append_text("\n") self._pop_tag(self._get_title_tag()) def visit_paragraph(self, node): self.in_paragraph = True if not self.active_lists: self._add_tag("p") def depart_paragraph(self, node): self.in_paragraph = False self._append_text("\n") if not self.active_lists: self._pop_tag("p") def visit_line_block(self, node): self._add_tag("line_block") def depart_line_block(self, node): self._pop_tag("line_block") def visit_line(self, node): pass def depart_line(self, node): self._append_text("\n") def visit_topic(self, node): self.in_topic = True if "toggle" in node.attributes["classes"]: return self._visit_toggle_topic(node) elif "empty" in node.attributes["classes"]: return self._visit_empty_topic(node) else: return self.default_visit(node) def _visit_toggle_topic(self, node): tag = self._create_unique_tag() title_id_tag = tag + "_title" body_id_tag = tag + "_body" def get_toggler_image_name(kind): if get_workbench().uses_dark_ui_theme(): return kind + "_light" else: return kind if "open" in node.attributes["classes"]: initial_image = get_toggler_image_name("boxminus") initial_elide = False else: initial_image = get_toggler_image_name("boxplus") initial_elide = True label = tk.Label( self.text, image=get_workbench().get_image(initial_image), borderwidth=0, background=self.text["background"], cursor="arrow", ) def toggle_body(event=None): elide = self.text.tag_cget(body_id_tag, "elide") if elide == "1": elide = True elif elide == "0": elide = False else: elide = bool(elide) elide = not elide self.text.tag_configure(body_id_tag, elide=elide) if self.text.has_selection(): self.text.tag_remove("sel", "1.0", "end") if elide: label.configure(image=get_workbench().get_image(get_toggler_image_name("boxplus"))) else: label.configure(image=get_workbench().get_image(get_toggler_image_name("boxminus"))) assert isinstance(node.children[0], docutils.nodes.title) # self.text.tag_bind(title_id_tag, "<1>", toggle_body, True) self._add_tag(title_id_tag) self._append_window(label) label.bind("<1>", toggle_body, True) node.children[0].walkabout(self) self._pop_tag(title_id_tag) self.text.tag_configure(body_id_tag, elide=initial_elide) self._add_tag(body_id_tag) self._add_tag("topic_body") for child in list(node.children)[1:]: child.walkabout(self) self._pop_tag("topic_body") self._pop_tag(body_id_tag) if "tight" not in node.attributes["classes"]: self._append_text("\n") raise docutils.nodes.SkipNode() def _visit_empty_topic(self, node): img = get_workbench().get_image( "boxdot_light" if get_workbench().uses_dark_ui_theme() else "boxdot" ) label = tk.Label( self.text, image=img, borderwidth=0, background=self.text["background"], cursor="arrow" ) self._append_window(label) assert isinstance(node.children[0], docutils.nodes.title) node.children[0].walkabout(self) if "tight" not in node.attributes["classes"]: self._append_text("\n") raise docutils.nodes.SkipNode() def depart_topic(self, node): # only for non-toggle topics self.in_topic = False self._append_text("\n") def visit_image(self, node): self._append_image(node.attributes["uri"]) if not self.in_paragraph and not self.in_title: self._append_text("\n") def visit_reference(self, node): tag = self._create_unique_tag() node.unique_tag = tag self._add_tag("a") self._add_tag(tag) def handle_click(event): get_workbench().open_url(node.attributes["refuri"]) self.text.tag_bind(tag, "", handle_click) def depart_reference(self, node): self._pop_tag("a") self._pop_tag(node.unique_tag) def visit_literal(self, node): self._add_tag("code") def depart_literal(self, node): self._pop_tag("code") def visit_inline(self, node): for cls in node.attributes["classes"]: self._add_tag(cls) def depart_inline(self, node): for cls in node.attributes["classes"]: self._pop_tag(cls) def visit_literal_block(self, node): self._add_tag("code") def depart_literal_block(self, node): self._pop_tag("code") self._append_text("\n\n") def visit_bullet_list(self, node): self.active_lists.append(node.attributes["bullet"]) def depart_bullet_list(self, node): self._append_text("\n") self.active_lists.pop() def visit_enumerated_list(self, node): self.active_lists.append(node.attributes["enumtype"]) def depart_enumerated_list(self, node): self._append_text("\n") self.active_lists.pop() def visit_list_item(self, node): if self.active_lists[-1] == "*": self._append_text("• ") elif self.active_lists[-1] == "arabic": for i, sib in enumerate(node.parent.children): if sib is node: self._append_text("%d. " % (i + 1)) break def visit_note(self, node): self._add_tag("em") def depart_note(self, node): self._pop_tag("em") def visit_target(self, node): pass def visit_substitution_definition(self, node): raise docutils.nodes.SkipNode() def visit_system_message(self, node): logging.getLogger("thonny").warning( "docutils message: '%s'. Context: %s" % (node.astext(), node.parent) ) raise docutils.nodes.SkipNode def visit_emphasis(self, node): self._add_tag("em") def depart_emphasis(self, node): self._pop_tag("em") def visit_strong(self, node): self._add_tag("strong") def depart_strong(self, node): self._pop_tag("strong") def visit_block_quote(self, node): self._add_tag("code") def depart_block_quote(self, node): self._pop_tag("code") def default_visit(self, node): self._append_text(self._node_to_text(node)) print("skipping children", type(node), node) raise docutils.nodes.SkipChildren() def default_departure(self, node): # Pass all other nodes through. pass def _create_unique_tag(self): self.unique_tag_count += 1 return "_UT_%s" % self.unique_tag_count def _node_to_text(self, node): if node.parent.attributes.get("xml:space") == "preserve": return node.astext() else: return node.astext().replace("\r", "").replace("\n", " ") def _add_tag(self, tag): self._context_tags.append(tag) def _pop_tag(self, tag): self._context_tags.remove(tag) def _append_text(self, chars, extra_tags=()): # print("APPP", chars, tags) self.text.direct_insert("end", chars, self._get_effective_tags(extra_tags)) def _append_image(self, name, extra_tags=()): index = self.text.index("end-1c") self.text.image_create(index, image=get_workbench().get_image(name)) for tag in self._get_effective_tags(extra_tags): self.text.tag_add(tag, index) def _append_window(self, window, extra_tags=()): index = self.text.index("end-1c") self.text.window_create(index, window=window) for tag in self._get_effective_tags(extra_tags): self.text.tag_add(tag, index) def _get_effective_tags(self, extra_tags): tags = set(extra_tags) | set(self._context_tags) if self.active_lists: tags.add("list%d" % min(len(self.active_lists), 5)) # combine tags if "code" in tags and "topic_title" in tags: tags.remove("code") tags.remove("topic_title") tags.add("topic_title_code") return tuple(sorted(tags)) def escape(s): return ( s.replace("\\", "\\\\") .replace("*", "\\*") .replace("`", "\\`") .replace("_", "\\_") .replace("..", "\\..") ) def create_title(text, line_symbol="="): text = text.replace("\r\n", "\n").replace("\n", " ").strip() return text + "\n" + line_symbol * len(text) + "\n" thonny-3.2.7/thonny/memory.py0000644000175000017500000000767513611773167017310 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import tkinter as tk import tkinter.font as tk_font from thonny import get_workbench, ui_utils from thonny.common import ValueInfo from thonny.ui_utils import TreeFrame MAX_REPR_LENGTH_IN_GRID = 100 def format_object_id(object_id): # this format aligns with how Python shows memory addresses if object_id is None: return None else: return "0x" + hex(object_id)[2:].upper() # .rjust(8,'0') def parse_object_id(object_id_repr): return int(object_id_repr, base=16) class MemoryFrame(TreeFrame): def __init__(self, master, columns): TreeFrame.__init__(self, master, columns) font = tk_font.nametofont("TkDefaultFont").copy() font.configure(underline=True) self.tree.tag_configure("hovered", font=font) def stop_debugging(self): self._clear_tree() def show_selected_object_info(self): iid = self.tree.focus() if iid != "": # NB! Assuming id is second column! id_str = self.tree.item(iid)["values"][1] if id_str in ["", None, "None"]: return object_id = parse_object_id(id_str) get_workbench().event_generate("ObjectSelect", object_id=object_id) class VariablesFrame(MemoryFrame): def __init__(self, master): MemoryFrame.__init__(self, master, ("name", "id", "value")) self.tree.column("name", width=120, anchor=tk.W, stretch=False) self.tree.column("id", width=450, anchor=tk.W, stretch=True) self.tree.column("value", width=450, anchor=tk.W, stretch=True) self.tree.heading("name", text="Name", anchor=tk.W) self.tree.heading("id", text="Value ID", anchor=tk.W) self.tree.heading("value", text="Value", anchor=tk.W) get_workbench().bind("ShowView", self._update_memory_model, True) get_workbench().bind("HideView", self._update_memory_model, True) self._update_memory_model() self.tree.tag_configure( "group_title", font="BoldTkDefaultFont", background=ui_utils.lookup_style_option(".", "background"), ) def destroy(self): MemoryFrame.destroy(self) get_workbench().unbind("ShowView", self._update_memory_model) get_workbench().unbind("HideView", self._update_memory_model) def _update_memory_model(self, event=None): if get_workbench().in_heap_mode(): self.tree.configure(displaycolumns=("name", "id")) # self.tree.columnconfigure(1, weight=1, width=400) # self.tree.columnconfigure(2, weight=0) else: self.tree.configure(displaycolumns=("name", "value")) # self.tree.columnconfigure(1, weight=0) # self.tree.columnconfigure(2, weight=1, width=400) def update_variables(self, all_variables): self._clear_tree() if not all_variables: return if isinstance(all_variables, list): groups = all_variables else: groups = [("", all_variables)] for group_title, variables in groups: if group_title: node_id = self.tree.insert("", "end", tags=("group_title",)) self.tree.set(node_id, "name", group_title) for name in sorted(variables.keys()): if not name.startswith("__"): node_id = self.tree.insert("", "end", tags="item") self.tree.set(node_id, "name", name) if isinstance(variables[name], ValueInfo): description = variables[name].repr id_str = variables[name].id else: description = variables[name] id_str = None self.tree.set(node_id, "id", format_object_id(id_str)) self.tree.set(node_id, "value", description) def on_select(self, event): self.show_selected_object_info() thonny-3.2.7/thonny/ast_utils.py0000644000175000017500000001366513611773167020003 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import ast from asttokens.asttokens import ASTTokens def extract_text_range(source, text_range): if isinstance(source, bytes): # TODO: may be wrong encoding source = source.decode("utf-8") lines = source.splitlines(True) # get relevant lines lines = lines[text_range.lineno - 1 : text_range.end_lineno] # trim last and first lines lines[-1] = lines[-1][: text_range.end_col_offset] lines[0] = lines[0][text_range.col_offset :] return "".join(lines) def find_expression(node, text_range): for node in ast.walk(node): if ( isinstance(node, ast.expr) and node.lineno == text_range.lineno and node.col_offset == text_range.col_offset and node.end_lineno == text_range.end_lineno and node.end_col_offset == text_range.end_col_offset ): return node def parse_source(source: bytes, filename="", mode="exec", fallback_to_one_char=False): root = ast.parse(source, filename, mode) mark_text_ranges(root, source, fallback_to_one_char) return root def get_last_child(node, skip_incorrect=True): """Returns last focusable child expression or child statement""" def ok_node(node): if node is None: return None assert isinstance(node, (ast.expr, ast.stmt)) if skip_incorrect and getattr(node, "incorrect_range", False): return None return node def last_ok(nodes): for i in range(len(nodes) - 1, -1, -1): if ok_node(nodes[i]): node = nodes[i] if isinstance(node, ast.Starred): if ok_node(node.value): return node.value else: return None else: return nodes[i] return None if isinstance(node, ast.Call): # TODO: take care of Python 3.5 updates (Starred etc.) if hasattr(node, "kwargs") and ok_node(node.kwargs): return node.kwargs elif hasattr(node, "starargs") and ok_node(node.starargs): return node.starargs else: kw_values = list(map(lambda x: x.value, node.keywords)) last_ok_kw = last_ok(kw_values) if last_ok_kw: return last_ok_kw elif last_ok(node.args): return last_ok(node.args) else: return ok_node(node.func) elif isinstance(node, ast.BoolOp): return last_ok(node.values) elif isinstance(node, ast.BinOp): if ok_node(node.right): return node.right else: return ok_node(node.left) elif isinstance(node, ast.Compare): return last_ok(node.comparators) elif isinstance(node, ast.UnaryOp): return ok_node(node.operand) elif isinstance(node, (ast.Tuple, ast.List, ast.Set)): return last_ok(node.elts) elif isinstance(node, ast.Dict): # TODO: actually should pairwise check last value, then last key, etc. return last_ok(node.values) elif isinstance( node, (ast.Index, ast.Return, ast.Assign, ast.AugAssign, ast.Yield, ast.YieldFrom) ): return ok_node(node.value) elif isinstance(node, ast.Delete): return last_ok(node.targets) elif isinstance(node, ast.Expr): return ok_node(node.value) elif isinstance(node, ast.Assert): if ok_node(node.msg): return node.msg else: return ok_node(node.test) elif isinstance(node, ast.Slice): # [:] if ok_node(node.step): return node.step elif ok_node(node.upper): return node.upper else: return ok_node(node.lower) elif isinstance(node, ast.ExtSlice): # [:,:] for dim in reversed(node.dims): result = get_last_child(dim, skip_incorrect) assert result is None or isinstance(result, ast.expr) if result is not None: return result return None elif isinstance(node, ast.Subscript): result = get_last_child(node.slice, skip_incorrect) if result is not None: return result else: return node.value elif isinstance(node, ast.Raise): if ok_node(node.cause): return node.cause elif ok_node(node.exc): return node.exc elif isinstance(node, (ast.For, ast.While, ast.If, ast.With)): return True # There is last child, but I don't know which it will be # TODO: pick more cases from here: """ (isinstance(node, (ast.IfExp, ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp)) # or isinstance(node, ast.FunctionDef, ast.Lambda) and len(node.args.defaults) > 0 and (node.dest is not None or len(node.values) > 0)) #"TODO: Import ja ImportFrom" # TODO: what about ClassDef ??? """ return None def mark_text_ranges(node, source: bytes, fallback_to_one_char=False): """ Node is an AST, source is corresponding source as string. Function adds recursively attributes end_lineno and end_col_offset to each node which has attributes lineno and col_offset. """ ASTTokens(source.decode("utf8"), tree=node) for child in ast.walk(node): if hasattr(child, "last_token"): child.end_lineno, child.end_col_offset = child.last_token.end if hasattr(child, "lineno"): # Fixes problems with some nodes like binop child.lineno, child.col_offset = child.first_token.start # some nodes stay without end info if ( hasattr(child, "lineno") and (not hasattr(child, "end_lineno") or not hasattr(child, "end_col_offset")) and fallback_to_one_char ): child.end_lineno = child.lineno child.end_col_offset = child.col_offset + 2 thonny-3.2.7/thonny/jedi_utils.py0000644000175000017500000000647713611776473020135 0ustar annamaaannamaa00000000000000"""Utils to handle different jedi versions Because of Debian Stretch, Thonny needs to support jedi 0.10, which doesn't use separate parso """ def import_python_tree(): # pylint: disable=import-error,no-name-in-module if get_version_tuple() < (0, 11, 0): # make sure not to import parso in this case, even if it exits from jedi.parser import tree # @UnresolvedImport @UnusedImport else: # assume older versions, which use parso from parso.python import tree # @UnresolvedImport @UnusedImport @Reimport return tree def get_params(func_node): if hasattr(func_node, "get_params"): # parso return func_node.get_params() else: # older jedi return func_node.params def get_parent_scope(node): try: # jedi 0.11 from jedi import parser_utils return parser_utils.get_parent_scope(node) except ImportError: # Older versions return node.get_parent_scope() def get_statement_of_position(node, pos): try: # jedi 0.11 # pylint: disable=redefined-outer-name import jedi.parser_utils func = getattr( jedi.parser_utils, "get_statement_of_position", _copy_of_get_statement_of_position ) return func(node, pos) except ImportError: # Older versions return node.get_statement_for_position(pos) def _copy_of_get_statement_of_position(node, pos): # https://github.com/davidhalter/jedi/commit/9f3a2f93c48eda24e2dcc25e54eb7cc10aa73848 from parso.python import tree for c in node.children: if c.start_pos <= pos <= c.end_pos: if c.type not in ( "decorated", "simple_stmt", "suite", "async_stmt", "async_funcdef", ) and not isinstance(c, (tree.Flow, tree.ClassOrFunc)): return c else: try: return _copy_of_get_statement_of_position(c, pos) except AttributeError: pass # Must be a non-scope return None def get_module_node(script): if hasattr(script, "_module_node"): # Jedi 0.12 return script._module_node elif hasattr(script, "_get_module_node"): # Jedi 0.10 - 0.11 return script._get_module_node() elif hasattr(script, "_get_module"): return script._get_module() else: return script._parser.module() def is_scope(node): try: # jedi 0.11 and older from jedi import parser_utils return parser_utils.is_scope(node) except ImportError: # Older versions return node.is_scope() def get_name_of_position(obj, position): if hasattr(obj, "get_name_of_position"): # parso return obj.get_name_of_position(position) else: # older jedi return obj.name_for_position(position) def parse_source(source): try: import parso return parso.parse(source) except ImportError: import jedi script = jedi.Script(source) return get_module_node(script) def get_version_tuple(): import jedi nums = [] for item in jedi.__version__.split("."): try: nums.append(int(item)) except Exception: nums.append(0) return tuple(nums) thonny-3.2.7/thonny/workbench.py0000644000175000017500000025464413611773167017762 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- import ast import collections import importlib import logging import os.path import pkgutil import platform import queue import re import socket import sys import tkinter as tk import tkinter.font as tk_font import traceback import webbrowser import gettext from threading import Thread from tkinter import ttk, messagebox from typing import ( Any, Callable, Dict, List, Optional, # pylint: disable=unused-import Sequence, Set, # pylint: disable=unused-import Tuple, # pylint: disable=unused-import Type, Union, cast, ) # pylint: disable=unused-import from warnings import warn import thonny from thonny import ( THONNY_USER_DIR, get_runner, running, ui_utils, assistance, languages, get_shell, is_portable, ) from thonny.code import EditorNotebook from thonny.common import Record, UserError, normpath_with_actual_case from thonny.config import try_load_configuration from thonny.config_ui import ConfigurationDialog from thonny.misc_utils import ( running_on_linux, running_on_mac_os, running_on_windows, running_on_rpi, copy_to_clipboard, ) from thonny.running import BackendProxy, Runner from thonny.shell import ShellView from thonny.ui_utils import ( AutomaticNotebook, AutomaticPanedWindow, create_tooltip, get_style_configuration, lookup_style_option, register_latin_shortcut, select_sequence, sequence_to_accelerator, ) SERVER_SUCCESS = "OK" SIMPLE_MODE_VIEWS = ["ShellView"] MenuItem = collections.namedtuple("MenuItem", ["group", "position_in_group", "tester"]) BackendSpec = collections.namedtuple( "BackendSpec", ["name", "proxy_class", "description", "config_page_constructor", "sort_key"] ) BasicUiThemeSettings = Dict[str, Dict[str, Union[Dict, Sequence]]] CompoundUiThemeSettings = List[BasicUiThemeSettings] UiThemeSettings = Union[BasicUiThemeSettings, CompoundUiThemeSettings] FlexibleUiThemeSettings = Union[UiThemeSettings, Callable[[], UiThemeSettings]] SyntaxThemeSettings = Dict[str, Dict[str, Union[str, int, bool]]] FlexibleSyntaxThemeSettings = Union[SyntaxThemeSettings, Callable[[], SyntaxThemeSettings]] OBSOLETE_PLUGINS = [ "thonnycontrib.pi", "thonnycontrib.micropython", "thonnycontrib.circuitpython", "thonnycontrib.microbit", "thonnycontrib.esp", ] class Workbench(tk.Tk): """ Thonny's main window and communication hub. Is responsible for: * creating the main window * maintaining layout (_init_containers) * loading plugins (_init_plugins, add_view, add_command) * providing references to main components (editor_notebook and runner) * communication between other components (see event_generate and bind) * configuration services (get_option, set_option, add_defaults) * loading translations * maintaining fonts (named fonts, increasing and decreasing font size) After workbench and plugins get loaded, 3 kinds of events start happening: * User events (keypresses, mouse clicks, menu selections, ...) * Virtual events (mostly via get_workbench().event_generate). These include: events reported via and dispatched by Tk event system; WorkbenchEvent-s, reported via and dispatched by enhanced get_workbench().event_generate. * Events from the background process (program output notifications, input requests, notifications about debugger's progress) """ def __init__(self) -> None: thonny._workbench = self self._closing = False self._destroyed = False self._lost_focus = False self._is_portable = is_portable() self.initializing = True self._init_configuration() self._check_init_server_loop() tk.Tk.__init__(self, className="Thonny") tk.Tk.report_callback_exception = self._on_tk_exception # type: ignore self._event_handlers = {} # type: Dict[str, Set[Callable]] self._images = ( set() ) # type: Set[tk.PhotoImage] # keep images here to avoid Python garbage collecting them, self._default_image_mapping = ( {} ) # type: Dict[str, str] # to allow specify default alternative images self._image_mapping_by_theme = ( {} ) # type: Dict[str, Dict[str, str]] # theme-based alternative images self._current_theme_name = "clam" # will be overwritten later self._backends = {} # type: Dict[str, BackendSpec] self._commands = [] # type: List[Dict[str, Any]] self._toolbar_buttons = {} self._view_records = {} # type: Dict[str, Dict[str, Any]] self.content_inspector_classes = [] # type: List[Type] self._latin_shortcuts = {} # type: Dict[Tuple[int,int], List[Tuple[Callable, Callable]]] self._init_diagnostic_logging() self._init_language() self._active_ui_mode = os.environ.get("THONNY_MODE", self.get_option("general.ui_mode")) self._init_scaling() self._add_main_backends() self._init_theming() self._init_window() self.add_view(ShellView, _("Shell"), "s", visible_by_default=True, default_position_key="A") assistance.init() self._runner = Runner() self._load_plugins() self._editor_notebook = None # type: Optional[EditorNotebook] self._init_fonts() self.reload_themes() self._init_menu() self._init_containers() assert self._editor_notebook is not None self._init_program_arguments_frame() self._init_regular_mode_link() self._show_views() # Make sure ShellView is loaded get_shell() self._init_commands() self._init_icon() try: self._editor_notebook.load_startup_files() except Exception: self.report_exception() self._editor_notebook.focus_set() self._try_action(self._open_views) self.bind_class("CodeViewText", "<>", self.update_title, True) self.bind_class("CodeViewText", "<>", self.update_title, True) self.bind_class("CodeViewText", "<>", self.update_title, True) self.get_editor_notebook().bind("<>", self.update_title, True) self.bind_all("", self._on_all_key_presses, True) self.bind("", self._on_focus_out, True) self.bind("", self._on_focus_in, True) self._publish_commands() self.initializing = False self.event_generate("<>") self._make_sanity_checks() if self._is_server(): self._poll_ipc_requests() self.after(1, self._start_runner) # Show UI already before waiting for the backend to start def _make_sanity_checks(self): home_dir = os.path.expanduser("~") bad_home_msg = None if home_dir == "~": bad_home_msg = "Can not find your home directory." elif not os.path.exists(home_dir): bad_home_msg = "Reported home directory (%s) does not exist." % home_dir if bad_home_msg: messagebox.showwarning( "Problems with home directory", bad_home_msg + "\nThis may cause problems for Thonny.", ) def _try_action(self, action: Callable) -> None: try: action() except Exception: self.report_exception() def _init_configuration(self) -> None: self._configuration_manager = try_load_configuration(thonny.CONFIGURATION_FILE) self._configuration_pages = [] # type: List[Tuple[str, str, Type[tk.Widget]] self.set_default("general.single_instance", thonny.SINGLE_INSTANCE_DEFAULT) self.set_default("general.ui_mode", "simple" if running_on_rpi() else "regular") self.set_default("general.debug_mode", False) self.set_default("general.disable_notification_sound", False) self.set_default("general.scaling", "default") self.set_default("general.language", languages.BASE_LANGUAGE_CODE) self.set_default("general.font_scaling_mode", "default") self.set_default("run.working_directory", os.path.expanduser("~")) def _init_language(self) -> None: """Initialize language.""" language_code = self.get_option("general.language") if language_code in languages.LANGUAGES_DICT: path = os.path.join(os.path.dirname(__file__), "locale") try: language = gettext.translation("thonny", path, [language_code]) language.install() except Exception: traceback.print_exc() self.report_exception("Can't load language " + language_code) def _get_logging_level(self) -> int: if self.in_debug_mode(): return logging.DEBUG else: return logging.INFO def _init_diagnostic_logging(self) -> None: logFormatter = logging.Formatter("%(levelname)s: %(message)s") root_logger = logging.getLogger() log_file = os.path.join(THONNY_USER_DIR, "frontend.log") file_handler = logging.FileHandler(log_file, encoding="UTF-8", mode="w") file_handler.setFormatter(logFormatter) file_handler.setLevel(self._get_logging_level()) root_logger.addHandler(file_handler) console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(logFormatter) console_handler.setLevel(self._get_logging_level()) root_logger.addHandler(console_handler) root_logger.setLevel(self._get_logging_level()) import faulthandler fault_out = open(os.path.join(THONNY_USER_DIR, "frontend_faults.log"), mode="w") faulthandler.enable(fault_out) def _init_window(self) -> None: self.title("Thonny") self.set_default("layout.zoomed", False) self.set_default("layout.top", 15) self.set_default("layout.left", 150) if self.in_simple_mode(): self.set_default("layout.width", 1050) self.set_default("layout.height", 700) else: self.set_default("layout.width", 800) self.set_default("layout.height", 650) self.set_default("layout.w_width", 200) self.set_default("layout.e_width", 200) self.set_default("layout.s_height", 200) # I don't actually need saved options for Full screen/maximize view, # but it's easier to create menu items, if I use configuration manager's variables self.set_default("view.full_screen", False) self.set_default("view.maximize_view", False) # In order to avoid confusion set these settings to False # even if they were True when Thonny was last run self.set_option("view.full_screen", False) self.set_option("view.maximize_view", False) self.geometry( "{0}x{1}+{2}+{3}".format( min(max(self.get_option("layout.width"), 320), self.winfo_screenwidth()), min(max(self.get_option("layout.height"), 240), self.winfo_screenheight()), min(max(self.get_option("layout.left"), 0), self.winfo_screenwidth() - 200), min(max(self.get_option("layout.top"), 0), self.winfo_screenheight() - 200), ) ) if self.get_option("layout.zoomed"): ui_utils.set_zoomed(self, True) self.protocol("WM_DELETE_WINDOW", self._on_close) self.bind("", self._on_configure, True) def _init_icon(self) -> None: # Window icons if running_on_linux() and ui_utils.get_tk_version_info() >= (8, 6): self.iconphoto(True, self.get_image("thonny.png")) else: icon_file = os.path.join(self.get_package_dir(), "res", "thonny.ico") try: self.iconbitmap(icon_file, default=icon_file) except Exception: try: # seems to work in mac self.iconbitmap(icon_file) except Exception: pass def _init_menu(self) -> None: self.option_add("*tearOff", tk.FALSE) if lookup_style_option("Menubar", "custom", False): self._menubar = ui_utils.CustomMenubar( self ) # type: Union[tk.Menu, ui_utils.CustomMenubar] if self.get_ui_mode() != "simple": self._menubar.grid(row=0, sticky="nsew") else: opts = get_style_configuration("Menubar") if "custom" in opts: del opts["custom"] self._menubar = tk.Menu(self, **opts) if self.get_ui_mode() != "simple": self["menu"] = self._menubar self._menus = {} # type: Dict[str, tk.Menu] self._menu_item_specs = ( {} ) # type: Dict[Tuple[str, str], MenuItem] # key is pair (menu_name, command_label) # create standard menus in correct order self.get_menu("file", _("File")) self.get_menu("edit", _("Edit")) self.get_menu("view", _("View")) self.get_menu("run", _("Run")) self.get_menu("tempdevice", "Device") self.get_menu("tools", _("Tools")) self.get_menu("help", _("Help")) def _load_plugins(self) -> None: # built-in plugins import thonny.plugins # pylint: disable=redefined-outer-name self._load_plugins_from_path( thonny.plugins.__path__, "thonny.plugins." # type: ignore ) # 3rd party plugins from namespace package try: import thonnycontrib # @UnresolvedImport except ImportError: # No 3rd party plugins installed pass else: self._load_plugins_from_path(thonnycontrib.__path__, "thonnycontrib.") def _load_plugins_from_path(self, path: List[str], prefix: str) -> None: load_function_name = "load_plugin" modules = [] for _, module_name, _ in sorted(pkgutil.iter_modules(path, prefix), key=lambda x: x[2]): if module_name in OBSOLETE_PLUGINS: logging.debug("Skipping plug-in %s", module_name) else: try: m = importlib.import_module(module_name) if hasattr(m, load_function_name): modules.append(m) except Exception: logging.exception("Failed loading plugin '" + module_name + "'") def module_sort_key(m): return getattr(m, "load_order_key", m.__name__) for m in sorted(modules, key=module_sort_key): getattr(m, load_function_name)() def _init_fonts(self) -> None: # set up editor and shell fonts self.set_default("view.io_font_family", "Courier" if running_on_mac_os() else "Courier New") default_editor_family = "Courier New" families = tk_font.families() for family in ["Consolas", "Ubuntu Mono", "Menlo", "DejaVu Sans Mono"]: if family in families: default_editor_family = family break self.set_default("view.editor_font_family", default_editor_family) if running_on_mac_os(): self.set_default("view.editor_font_size", 14) self.set_default("view.io_font_size", 12) elif self.in_simple_mode(): self.set_default("view.editor_font_size", 12) self.set_default("view.io_font_size", 12) else: self.set_default("view.editor_font_size", 13) self.set_default("view.io_font_size", 11) default_font = tk_font.nametofont("TkDefaultFont") if running_on_linux(): heading_font = tk_font.nametofont("TkHeadingFont") heading_font.configure(weight="normal") caption_font = tk_font.nametofont("TkCaptionFont") caption_font.configure(weight="normal", size=default_font.cget("size")) small_link_ratio = 0.8 if running_on_windows() else 0.7 self._fonts = [ tk_font.Font( name="SmallLinkFont", family=default_font.cget("family"), size=int(default_font.cget("size") * small_link_ratio), underline=True, ), tk_font.Font(name="IOFont", family=self.get_option("view.io_font_family")), tk_font.Font( name="BoldIOFont", family=self.get_option("view.io_font_family"), weight="bold" ), tk_font.Font( name="UnderlineIOFont", family=self.get_option("view.io_font_family"), underline=True, ), tk_font.Font( name="ItalicIOFont", family=self.get_option("view.io_font_family"), slant="italic" ), tk_font.Font( name="BoldItalicIOFont", family=self.get_option("view.io_font_family"), weight="bold", slant="italic", ), tk_font.Font(name="EditorFont", family=self.get_option("view.editor_font_family")), tk_font.Font(name="SmallEditorFont", family=self.get_option("view.editor_font_family")), tk_font.Font( name="BoldEditorFont", family=self.get_option("view.editor_font_family"), weight="bold", ), tk_font.Font( name="ItalicEditorFont", family=self.get_option("view.editor_font_family"), slant="italic", ), tk_font.Font( name="BoldItalicEditorFont", family=self.get_option("view.editor_font_family"), weight="bold", slant="italic", ), tk_font.Font( name="TreeviewFont", family=default_font.cget("family"), size=default_font.cget("size"), ), tk_font.Font( name="BoldTkDefaultFont", family=default_font.cget("family"), size=default_font.cget("size"), weight="bold", ), tk_font.Font( name="ItalicTkDefaultFont", family=default_font.cget("family"), size=default_font.cget("size"), slant="italic", ), tk_font.Font( name="UnderlineTkDefaultFont", family=default_font.cget("family"), size=default_font.cget("size"), underline=1, ), ] self.update_fonts() def _add_main_backends(self) -> None: self.set_default("run.backend_name", "SameAsFrontend") self.set_default("CustomInterpreter.used_paths", []) self.set_default("CustomInterpreter.path", "") from thonny import running_config_page self.add_backend( "SameAsFrontend", running.SameAsFrontendCPythonProxy, _("The same interpreter which runs Thonny (default)"), running_config_page.SameAsFrontEndConfigurationPage, "1", ) self.add_backend( "CustomCPython", running.CustomCPythonProxy, _("Alternative Python 3 interpreter or virtual environment"), running_config_page.CustomCPythonConfigurationPage, "2", ) self.add_backend( "PrivateVenv", running.PrivateVenvCPythonProxy, _("A special virtual environment (deprecated)"), running_config_page.PrivateVenvConfigurationPage, "z", ) def _start_runner(self) -> None: try: self.update_idletasks() # allow UI to complete thonny._runner = self._runner self._runner.start() self._update_toolbar() except Exception: self.report_exception("Error when initializing backend") def _check_init_server_loop(self) -> None: """Socket will listen requests from newer Thonny instances, which try to delegate opening files to older instance""" if not self.get_option("general.single_instance") or os.path.exists(thonny.IPC_FILE): self._ipc_requests = None return self._ipc_requests = queue.Queue() # type: queue.Queue[bytes] server_socket, actual_secret = self._create_server_socket() server_socket.listen(10) def server_loop(): while True: logging.debug("Waiting for next client") (client_socket, _) = server_socket.accept() try: data = bytes() while True: new_data = client_socket.recv(1024) if len(new_data) > 0: data += new_data else: break proposed_secret, args = ast.literal_eval(data.decode("UTF-8")) if proposed_secret == actual_secret: self._ipc_requests.put(args) # respond OK client_socket.sendall(SERVER_SUCCESS.encode(encoding="utf-8")) client_socket.shutdown(socket.SHUT_WR) logging.debug("AFTER NEW REQUEST %s", client_socket) else: client_socket.shutdown(socket.SHUT_WR) raise PermissionError("Wrong secret") except Exception: traceback.print_exc() Thread(target=server_loop, daemon=True).start() def _create_server_socket(self): if running_on_windows(): server_socket = socket.socket(socket.AF_INET) # @UndefinedVariable server_socket.bind(("127.0.0.1", 0)) # advertise the port and secret port = server_socket.getsockname()[1] import uuid secret = str(uuid.uuid4()) with open(thonny.IPC_FILE, "w") as fp: fp.write(str(port) + "\n") fp.write(secret + "\n") else: server_socket = socket.socket(socket.AF_UNIX) # @UndefinedVariable server_socket.bind(thonny.IPC_FILE) secret = "" os.chmod(thonny.IPC_FILE, 0o600) return server_socket, secret def _init_commands(self) -> None: self.add_command( "exit", "file", _("Exit"), self._on_close, default_sequence=select_sequence("", "", ""), extra_sequences=[""] if running_on_linux() else [""] if running_on_windows() else [], ) self.add_command("show_options", "tools", _("Options..."), self.show_options, group=180) self.createcommand("::tk::mac::ShowPreferences", self.show_options) self.createcommand("::tk::mac::Quit", self._mac_quit) self.add_command( "increase_font_size", "view", _("Increase font size"), lambda: self._change_font_size(1), default_sequence=select_sequence("", ""), extra_sequences=[""], group=60, ) self.add_command( "decrease_font_size", "view", _("Decrease font size"), lambda: self._change_font_size(-1), default_sequence=select_sequence("", ""), extra_sequences=[""], group=60, ) self.bind("", self._cmd_zoom_with_mouse, True) self.add_command( "focus_editor", "view", _("Focus editor"), self._cmd_focus_editor, default_sequence=select_sequence("", ""), group=70, ) self.add_command( "focus_shell", "view", _("Focus shell"), self._cmd_focus_shell, default_sequence=select_sequence("", ""), group=70, ) if self.get_ui_mode() == "expert": self.add_command( "toggle_maximize_view", "view", _("Maximize view"), self._cmd_toggle_maximize_view, flag_name="view.maximize_view", default_sequence=None, group=80, ) self.bind_class("TNotebook", "", self._maximize_view, True) self.bind("", self._unmaximize_view, True) self.add_command( "toggle_maximize_view", "view", _("Full screen"), self._cmd_toggle_full_screen, flag_name="view.full_screen", default_sequence=select_sequence("", ""), group=80, ) if self.in_simple_mode(): self.add_command( "font", "tools", _("Change font size"), caption=_("Zoom"), handler=self._toggle_font_size, image="zoom", include_in_toolbar=True, ) self.add_command( "quit", "help", _("Exit Thonny"), self._on_close, image="quit", caption=_("Quit"), include_in_toolbar=True, group=101, ) if self.in_debug_mode(): self.bind_all("", self._print_state_for_debugging, True) def _print_state_for_debugging(self, event) -> None: print(get_runner()._postponed_commands) def _init_containers(self) -> None: # Main frame functions as # - a backgroud behind padding of main_pw, without this OS X leaves white border # - a container to be hidden, when a view is maximized and restored when view is back home main_frame = ttk.Frame(self) # self._main_frame = main_frame main_frame.grid(row=1, column=0, sticky=tk.NSEW) self.columnconfigure(0, weight=1) self.rowconfigure(1, weight=1) self._maximized_view = None # type: Optional[tk.Widget] self._toolbar = ttk.Frame(main_frame, padding=0) self._toolbar.grid(column=0, row=0, sticky=tk.NSEW, padx=10, pady=(5, 0)) self.set_default("layout.west_pw_width", self.scale(150)) self.set_default("layout.east_pw_width", self.scale(150)) self.set_default("layout.s_nb_height", self.scale(150)) self.set_default("layout.nw_nb_height", self.scale(150)) self.set_default("layout.sw_nb_height", self.scale(150)) self.set_default("layout.ne_nb_height", self.scale(150)) self.set_default("layout.se_nb_height", self.scale(150)) self._main_pw = AutomaticPanedWindow(main_frame, orient=tk.HORIZONTAL) self._main_pw.grid(column=0, row=1, sticky=tk.NSEW, padx=10, pady=10) main_frame.columnconfigure(0, weight=1) main_frame.rowconfigure(1, weight=1) self._west_pw = AutomaticPanedWindow( self._main_pw, 1, orient=tk.VERTICAL, preferred_size_in_pw=self.get_option("layout.west_pw_width"), ) self._center_pw = AutomaticPanedWindow(self._main_pw, 2, orient=tk.VERTICAL) self._east_pw = AutomaticPanedWindow( self._main_pw, 3, orient=tk.VERTICAL, preferred_size_in_pw=self.get_option("layout.east_pw_width"), ) self._view_notebooks = { "nw": AutomaticNotebook( self._west_pw, 1, preferred_size_in_pw=self.get_option("layout.nw_nb_height") ), "w": AutomaticNotebook(self._west_pw, 2), "sw": AutomaticNotebook( self._west_pw, 3, preferred_size_in_pw=self.get_option("layout.sw_nb_height") ), "s": AutomaticNotebook( self._center_pw, 3, preferred_size_in_pw=self.get_option("layout.s_nb_height") ), "ne": AutomaticNotebook( self._east_pw, 1, preferred_size_in_pw=self.get_option("layout.ne_nb_height") ), "e": AutomaticNotebook(self._east_pw, 2), "se": AutomaticNotebook( self._east_pw, 3, preferred_size_in_pw=self.get_option("layout.se_nb_height") ), } for nb_name in self._view_notebooks: self.set_default("layout.notebook_" + nb_name + "_visible_view", None) self._editor_notebook = EditorNotebook(self._center_pw) self._editor_notebook.position_key = 1 # type: ignore self._center_pw.insert("auto", self._editor_notebook) def _init_theming(self) -> None: self._style = ttk.Style() self._ui_themes = ( {} ) # type: Dict[str, Tuple[Optional[str], FlexibleUiThemeSettings, Dict[str, str]]] # value is (parent, settings, images) self._syntax_themes = ( {} ) # type: Dict[str, Tuple[Optional[str], FlexibleSyntaxThemeSettings]] # value is (parent, settings) self.set_default("view.ui_theme", ui_utils.get_default_theme()) def add_command( self, command_id: str, menu_name: str, command_label: str, handler: Optional[Callable[[], None]] = None, tester: Optional[Callable[[], bool]] = None, default_sequence: Optional[str] = None, extra_sequences: Sequence[str] = [], flag_name: Optional[str] = None, skip_sequence_binding: bool = False, accelerator: Optional[str] = None, group: int = 99, position_in_group="end", image: Optional[str] = None, caption: Optional[str] = None, alternative_caption: Optional[str] = None, include_in_menu: bool = True, include_in_toolbar: bool = False, submenu: Optional[tk.Menu] = None, bell_when_denied: bool = True, show_extra_sequences=False, ) -> None: """Registers an item to be shown in specified menu. Args: menu_name: Name of the menu the command should appear in. Standard menu names are "file", "edit", "run", "view", "help". If a menu with given name doesn't exist, then new menu is created (with label=name). command_label: Label for this command handler: Function to be called when the command is invoked. Should be callable with one argument (the event or None). tester: Function to be called for determining if command is available or not. Should be callable with one argument (the event or None). Should return True or False. If None then command is assumed to be always available. default_sequence: Default shortcut (Tk style) flag_name: Used for toggle commands. Indicates the name of the boolean option. group: Used for grouping related commands together. Value should be int. Groups with smaller numbers appear before. Returns: None """ # Temporary solution for plug-ins made for versions before 3.2 if menu_name == "device": menu_name = "tools" group = 150 # store command to be published later self._commands.append( dict( command_id=command_id, menu_name=menu_name, command_label=command_label, handler=handler, tester=tester, default_sequence=default_sequence, extra_sequences=extra_sequences, flag_name=flag_name, skip_sequence_binding=skip_sequence_binding, accelerator=accelerator, group=group, position_in_group=position_in_group, image=image, caption=caption, alternative_caption=alternative_caption, include_in_menu=include_in_menu, include_in_toolbar=include_in_toolbar, submenu=submenu, bell_when_denied=bell_when_denied, show_extra_sequences=show_extra_sequences, ) ) def _publish_commands(self) -> None: for cmd in self._commands: self._publish_command(**cmd) def _publish_command( self, command_id: str, menu_name: str, command_label: str, handler: Optional[Callable[[], None]], tester: Optional[Callable[[], bool]] = None, default_sequence: Optional[str] = None, extra_sequences: Sequence[str] = [], flag_name: Optional[str] = None, skip_sequence_binding: bool = False, accelerator: Optional[str] = None, group: int = 99, position_in_group="end", image: Optional[str] = None, caption: Optional[str] = None, alternative_caption: Optional[str] = None, include_in_menu: bool = True, include_in_toolbar: bool = False, submenu: Optional[tk.Menu] = None, bell_when_denied: bool = True, show_extra_sequences: bool = False, ) -> None: def dispatch(event=None): if not tester or tester(): denied = False handler() else: denied = True logging.debug("Command '" + command_id + "' execution denied") if bell_when_denied: self.bell() self.event_generate("UICommandDispatched", command_id=command_id, denied=denied) sequence_option_name = "shortcuts." + command_id self.set_default(sequence_option_name, default_sequence) sequence = self.get_option(sequence_option_name) if sequence: if not skip_sequence_binding: self.bind_all(sequence, dispatch, True) # register shortcut even without binding register_latin_shortcut(self._latin_shortcuts, sequence, handler, tester) for extra_sequence in extra_sequences: self.bind_all(extra_sequence, dispatch, True) if "greek_" not in extra_sequence.lower() or running_on_linux(): # Use greek alternatives only on Linux # (they are not required on Mac # and cause double events on Windows) register_latin_shortcut(self._latin_shortcuts, sequence, handler, tester) menu = self.get_menu(menu_name) if image: _image = self.get_image(image) # type: Optional[tk.PhotoImage] _disabled_image = self.get_image(image, disabled=True) else: _image = None _disabled_image = None if not accelerator and sequence: accelerator = sequence_to_accelerator(sequence) """ # Does not work on Mac if show_extra_sequences: for extra_seq in extra_sequences: accelerator += " or " + sequence_to_accelerator(extra_seq) """ if include_in_menu: def dispatch_from_menu(): # I don't like that Tk menu toggles checbutton variable # automatically before calling the handler. # So I revert the toggle before calling the actual handler. # This way the handler doesn't have to worry whether it # needs to toggle the variable or not, and it can choose to # decline the toggle. if flag_name is not None: var = self.get_variable(flag_name) var.set(not var.get()) dispatch(None) if _image and lookup_style_option("OPTIONS", "icons_in_menus", True): menu_image = _image # type: Optional[tk.PhotoImage] elif flag_name: # no image or black next to a checkbox menu_image = None else: menu_image = self.get_image("16x16-blank") # remember the details that can't be stored in Tkinter objects self._menu_item_specs[(menu_name, command_label)] = MenuItem( group, position_in_group, tester ) menu.insert( self._find_location_for_menu_item(menu_name, command_label), "checkbutton" if flag_name else "cascade" if submenu else "command", label=command_label, accelerator=accelerator, image=menu_image, compound=tk.LEFT, variable=self.get_variable(flag_name) if flag_name else None, command=dispatch_from_menu if handler else None, menu=submenu, ) if include_in_toolbar: toolbar_group = self._get_menu_index(menu) * 100 + group assert caption is not None self._add_toolbar_button( command_id, _image, _disabled_image, command_label, caption, caption if alternative_caption is None else alternative_caption, accelerator, handler, tester, toolbar_group, ) def add_view( self, cls: Type[tk.Widget], label: str, default_location: str, visible_by_default: bool = False, default_position_key: Optional[str] = None, ) -> None: """Adds item to "View" menu for showing/hiding given view. Args: view_class: Class or constructor for view. Should be callable with single argument (the master of the view) label: Label of the view tab location: Location descriptor. Can be "nw", "sw", "s", "se", "ne" Returns: None """ view_id = cls.__name__ if default_position_key == None: default_position_key = label self.set_default("view." + view_id + ".visible", visible_by_default) self.set_default("view." + view_id + ".location", default_location) self.set_default("view." + view_id + ".position_key", default_position_key) if self.in_simple_mode(): visibility_flag = tk.BooleanVar(value=view_id in SIMPLE_MODE_VIEWS) else: visibility_flag = cast(tk.BooleanVar, self.get_variable("view." + view_id + ".visible")) self._view_records[view_id] = { "class": cls, "label": label, "location": self.get_option("view." + view_id + ".location"), "position_key": self.get_option("view." + view_id + ".position_key"), "visibility_flag": visibility_flag, } # handler def toggle_view_visibility(): if visibility_flag.get(): self.hide_view(view_id) else: self.show_view(view_id, True) self.add_command( "toggle_" + view_id, menu_name="view", command_label=label, handler=toggle_view_visibility, flag_name="view." + view_id + ".visible", group=10, position_in_group="alphabetic", ) def add_configuration_page( self, key: str, title: str, page_class: Type[tk.Widget], order: int ) -> None: self._configuration_pages.append((key, title, page_class, order)) def add_content_inspector(self, inspector_class: Type) -> None: self.content_inspector_classes.append(inspector_class) def add_backend( self, name: str, proxy_class: Type[BackendProxy], description: str, config_page_constructor, sort_key=None, ) -> None: self._backends[name] = BackendSpec( name, proxy_class, description, config_page_constructor, sort_key if sort_key is not None else description, ) # assing names to related classes proxy_class.backend_name = name # type: ignore if not getattr(config_page_constructor, "backend_name", None): config_page_constructor.backend_name = name def add_ui_theme( self, name: str, parent: Union[str, None], settings: FlexibleUiThemeSettings, images: Dict[str, str] = {}, ) -> None: if name in self._ui_themes: warn(_("Overwriting theme '%s'") % name) self._ui_themes[name] = (parent, settings, images) def add_syntax_theme( self, name: str, parent: Optional[str], settings: FlexibleSyntaxThemeSettings ) -> None: if name in self._syntax_themes: warn(_("Overwriting theme '%s'") % name) self._syntax_themes[name] = (parent, settings) def get_usable_ui_theme_names(self) -> Sequence[str]: return sorted([name for name in self._ui_themes if self._ui_themes[name][0] is not None]) def get_syntax_theme_names(self) -> Sequence[str]: return sorted(self._syntax_themes.keys()) def get_ui_mode(self) -> str: return self._active_ui_mode def in_simple_mode(self) -> bool: return self.get_ui_mode() == "simple" def scale(self, value: Union[int, float]) -> int: if isinstance(value, (int, float)): # using int instead of round so that thin lines will stay # one pixel even with scaling_factor 1.67 result = int(self._scaling_factor * value) if result == 0 and value > 0: # don't lose thin lines because of scaling return 1 else: return result else: raise NotImplementedError("Only numeric dimensions supported at the moment") def _register_ui_theme_as_tk_theme(self, name: str) -> None: # collect settings from all ancestors total_settings = [] # type: List[FlexibleUiThemeSettings] total_images = {} # type: Dict[str, str] temp_name = name while True: parent, settings, images = self._ui_themes[temp_name] total_settings.insert(0, settings) for img_name in images: total_images.setdefault(img_name, images[img_name]) if parent is not None: temp_name = parent else: # reached start of the chain break assert temp_name in self._style.theme_names() # only root of the ancestors is relevant for theme_create, # because the method actually doesn't take parent settings into account # (https://mail.python.org/pipermail/tkinter-discuss/2015-August/003752.html) self._style.theme_create(name, temp_name) self._image_mapping_by_theme[name] = total_images # load images self.get_image("tab-close", "img_close") self.get_image("tab-close-active", "img_close_active") # apply settings starting from root ancestor for settings in total_settings: if callable(settings): settings = settings() if isinstance(settings, dict): self._style.theme_settings(name, settings) else: for subsettings in settings: self._style.theme_settings(name, subsettings) def _apply_ui_theme(self, name: str) -> None: self._current_theme_name = name if name not in self._style.theme_names(): self._register_ui_theme_as_tk_theme(name) self._style.theme_use(name) # https://wiki.tcl.tk/37973#pagetocfe8b22ab for setting in ["background", "foreground", "selectBackground", "selectForeground"]: value = self._style.lookup("Listbox", setting) if value: self.option_add("*TCombobox*Listbox." + setting, value) self.option_add("*Listbox." + setting, value) text_opts = self._style.configure("Text") if text_opts: for key in text_opts: self.option_add("*Text." + key, text_opts[key]) if hasattr(self, "_menus"): # if menus have been initialized, ie. when theme is being changed for menu in self._menus.values(): menu.configure(get_style_configuration("Menu")) self.update_fonts() def _apply_syntax_theme(self, name: str) -> None: def get_settings(name): try: parent, settings = self._syntax_themes[name] except KeyError: self.report_exception("Can't find theme '%s'" % name) return {} if callable(settings): settings = settings() if parent is None: return settings else: result = get_settings(parent) for key in settings: if key in result: result[key].update(settings[key]) else: result[key] = settings[key] return result from thonny import codeview codeview.set_syntax_options(get_settings(name)) def reload_themes(self) -> None: preferred_theme = self.get_option("view.ui_theme") available_themes = self.get_usable_ui_theme_names() if preferred_theme in available_themes: self._apply_ui_theme(preferred_theme) elif "Enhanced Clam" in available_themes: self._apply_ui_theme("Enhanced Clam") elif "Windows" in available_themes: self._apply_ui_theme("Windows") self._apply_syntax_theme(self.get_option("view.syntax_theme")) def uses_dark_ui_theme(self) -> bool: name = self._style.theme_use() while True: if "dark" in name.lower(): return True name, _, _ = self._ui_themes[name] if name is None: # reached start of the chain break return False def _init_program_arguments_frame(self) -> None: self.set_default("view.show_program_arguments", False) self.set_default("run.program_arguments", "") self.set_default("run.past_program_arguments", []) visibility_var = self.get_variable("view.show_program_arguments") content_var = self.get_variable("run.program_arguments") frame = ttk.Frame(self._toolbar) col = 1000 self._toolbar.columnconfigure(col, weight=1) label = ttk.Label(frame, text=_("Program arguments:")) label.grid(row=0, column=0, sticky="nse", padx=5) self.program_arguments_box = ttk.Combobox( frame, width=80, height=15, textvariable=content_var, values=[""] + self.get_option("run.past_program_arguments"), ) self.program_arguments_box.grid(row=0, column=1, sticky="nsew", padx=5) frame.columnconfigure(1, weight=1) def update_visibility(): if visibility_var.get(): if not frame.winfo_ismapped(): frame.grid(row=0, column=col, sticky="nse") else: if frame.winfo_ismapped(): frame.grid_remove() def toggle(): visibility_var.set(not visibility_var.get()) update_visibility() self.add_command( "viewargs", "view", _("Program arguments"), toggle, flag_name="view.show_program_arguments", group=11, ) update_visibility() def _init_regular_mode_link(self): if self.get_ui_mode() != "simple": return label = ttk.Label( self._toolbar, text=_("Switch to\nregular\nmode"), justify="right", font="SmallLinkFont", style="Url.TLabel", cursor="hand2", ) label.grid(row=0, column=1001, sticky="ne") def on_click(event): self.set_option("general.ui_mode", "regular") tk.messagebox.showinfo( _("Regular mode"), _( "Configuration has been updated. " + "Restart Thonny to start working in regular mode.\n\n" + "(See 'Tools → Options → General' if you change your mind later.)" ), ) label.bind("<1>", on_click, True) def log_program_arguments_string(self, arg_str: str) -> None: arg_str = arg_str.strip() self.set_option("run.program_arguments", arg_str) if arg_str == "": # empty will be handled differently return past_args = self.get_option("run.past_program_arguments") if arg_str in past_args: past_args.remove(arg_str) past_args.insert(0, arg_str) past_args = past_args[:10] self.set_option("run.past_program_arguments", past_args) self.program_arguments_box.configure(values=[""] + past_args) def _show_views(self) -> None: for view_id in self._view_records: if self._view_records[view_id]["visibility_flag"].get(): try: self.show_view(view_id, False) except Exception: self.report_exception("Problem showing " + view_id) def update_image_mapping(self, mapping: Dict[str, str]) -> None: """Was used by thonny-pi. Not recommended anymore""" self._default_image_mapping.update(mapping) def get_backends(self) -> Dict[str, BackendSpec]: return self._backends def get_option(self, name: str, default=None) -> Any: # Need to return Any, otherwise each typed call site needs to cast return self._configuration_manager.get_option(name, default) def set_option(self, name: str, value: Any) -> None: self._configuration_manager.set_option(name, value) def get_local_cwd(self) -> str: cwd = self.get_option("run.working_directory") if os.path.exists(cwd): return normpath_with_actual_case(cwd) else: return normpath_with_actual_case(os.path.expanduser("~")) def set_local_cwd(self, value: str) -> None: if self.get_option("run.working_directory") != value: self.set_option("run.working_directory", value) if value: self.event_generate("LocalWorkingDirectoryChanged", cwd=value) def set_default(self, name: str, default_value: Any) -> None: """Registers a new option. If the name contains a period, then the part left to the (first) period will become the section of the option and rest will become name under that section. If the name doesn't contain a period, then it will be added under section "general". """ self._configuration_manager.set_default(name, default_value) def get_variable(self, name: str) -> tk.Variable: return self._configuration_manager.get_variable(name) def get_menu(self, name: str, label: Optional[str] = None) -> tk.Menu: """Gives the menu with given name. Creates if not created yet. Args: name: meant to be used as not translatable menu name label: translated label, used only when menu with given name doesn't exist yet """ if name not in self._menus: if running_on_mac_os(): conf = {} else: conf = get_style_configuration("Menu") menu = tk.Menu(self._menubar, **conf) menu["postcommand"] = lambda: self._update_menu(menu, name) self._menubar.add_cascade(label=label if label else name, menu=menu) self._menus[name] = menu if label: self._menus[label] = menu return self._menus[name] def get_view(self, view_id: str, create: bool = True) -> tk.Widget: if "instance" not in self._view_records[view_id]: if not create: raise RuntimeError("View %s not created" % view_id) class_ = self._view_records[view_id]["class"] location = self._view_records[view_id]["location"] master = self._view_notebooks[location] # create the view view = class_(self) # View's master is workbench to allow making it maximized view.position_key = self._view_records[view_id]["position_key"] self._view_records[view_id]["instance"] = view # create the view home_widget to be added into notebook view.home_widget = ttk.Frame(master) view.home_widget.columnconfigure(0, weight=1) view.home_widget.rowconfigure(0, weight=1) view.home_widget.maximizable_widget = view # type: ignore view.home_widget.close = lambda: self.hide_view(view_id) # type: ignore if hasattr(view, "position_key"): view.home_widget.position_key = view.position_key # type: ignore # initially the view will be in it's home_widget view.grid(row=0, column=0, sticky=tk.NSEW, in_=view.home_widget) view.hidden = True return self._view_records[view_id]["instance"] def get_editor_notebook(self) -> EditorNotebook: assert self._editor_notebook is not None return self._editor_notebook def get_package_dir(self): """Returns thonny package directory""" return os.path.dirname(sys.modules["thonny"].__file__) def get_image( self, filename: str, tk_name: Optional[str] = None, disabled=False ) -> tk.PhotoImage: if filename in self._image_mapping_by_theme[self._current_theme_name]: filename = self._image_mapping_by_theme[self._current_theme_name][filename] if filename in self._default_image_mapping: filename = self._default_image_mapping[filename] # if path is relative then interpret it as living in res folder if not os.path.isabs(filename): filename = os.path.join(self.get_package_dir(), "res", filename) if not os.path.exists(filename): if os.path.exists(filename + ".png"): filename = filename + ".png" elif os.path.exists(filename + ".gif"): filename = filename + ".gif" if disabled: filename = os.path.join( os.path.dirname(filename), "_disabled_" + os.path.basename(filename) ) if not os.path.exists(filename): return None # are there platform-specific variants? plat_filename = filename[:-4] + "_" + platform.system() + ".png" if os.path.exists(plat_filename): filename = plat_filename if self._scaling_factor >= 2.0: scaled_filename = filename[:-4] + "_2x.png" if os.path.exists(scaled_filename): filename = scaled_filename else: img = tk.PhotoImage(file=filename) # can't use zoom method, because this doesn't allow name img2 = tk.PhotoImage(tk_name) self.tk.call( img2, "copy", img.name, "-zoom", int(self._scaling_factor), int(self._scaling_factor), ) self._images.add(img2) return img2 img = tk.PhotoImage(tk_name, file=filename) self._images.add(img) return img def show_view(self, view_id: str, set_focus: bool = True) -> Union[bool, tk.Widget]: """View must be already registered. Args: view_id: View class name without package name (eg. 'ShellView') """ if view_id == "MainFileBrowser": # Was renamed in 3.1.1 view_id = "FilesView" # NB! Don't forget that view.home_widget is added to notebook, not view directly # get or create view = self.get_view(view_id) notebook = view.home_widget.master # type: ignore if hasattr(view, "before_show") and view.before_show() == False: # type: ignore return False if view.hidden: # type: ignore notebook.insert( "auto", view.home_widget, # type: ignore text=self._view_records[view_id]["label"], ) view.hidden = False # type: ignore if hasattr(view, "on_show"): # type: ignore view.on_show() # switch to the tab notebook.select(view.home_widget) # type: ignore # add focus if set_focus: view.focus_set() self.set_option("view." + view_id + ".visible", True) self.event_generate("ShowView", view=view, view_id=view_id) return view def hide_view(self, view_id: str) -> Union[bool, None]: # NB! Don't forget that view.home_widget is added to notebook, not view directly if "instance" in self._view_records[view_id]: # TODO: handle the case, when view is maximized view = self._view_records[view_id]["instance"] if view.hidden: return if hasattr(view, "before_hide") and view.before_hide() == False: return False view.home_widget.master.forget(view.home_widget) self.set_option("view." + view_id + ".visible", False) self.event_generate("HideView", view=view, view_id=view_id) view.hidden = True return None def event_generate(self, sequence: str, event: Optional[Record] = None, **kwargs) -> None: """Uses custom event handling when sequence doesn't start with <. In this case arbitrary attributes can be added to the event. Otherwise forwards the call to Tk's event_generate""" # pylint: disable=arguments-differ if sequence.startswith("<"): assert event is None tk.Tk.event_generate(self, sequence, **kwargs) else: if sequence in self._event_handlers: if event is None: event = WorkbenchEvent(sequence, **kwargs) else: event.update(kwargs) # make a copy of handlers, so that event handler can remove itself # from the registry during iteration # (or new handlers can be added) for handler in sorted(self._event_handlers[sequence].copy(), key=str): try: handler(event) except Exception: self.report_exception("Problem when handling '" + sequence + "'") if not self._closing: self._update_toolbar() def bind(self, sequence: str, func: Callable, add: bool = None) -> None: # type: ignore """Uses custom event handling when sequence doesn't start with <. Otherwise forwards the call to Tk's bind""" # pylint: disable=signature-differs if not add: logging.warning( "Workbench.bind({}, ..., add={}) -- did you really want to replace existing bindings?".format( sequence, add ) ) if sequence.startswith("<"): tk.Tk.bind(self, sequence, func, add) else: if sequence not in self._event_handlers or not add: self._event_handlers[sequence] = set() self._event_handlers[sequence].add(func) def unbind(self, sequence: str, func=None) -> None: if sequence.startswith("<"): tk.Tk.unbind(self, sequence, funcid=func) else: try: self._event_handlers[sequence].remove(func) except Exception: logging.getLogger("thonny").exception( "Can't remove binding for '%s' and '%s'", sequence, func ) def in_heap_mode(self) -> bool: # TODO: add a separate command for enabling the heap mode # untie the mode from HeapView return self._configuration_manager.has_option("view.HeapView.visible") and self.get_option( "view.HeapView.visible" ) def in_debug_mode(self) -> bool: return os.environ.get("THONNY_DEBUG", False) in [ "1", 1, "True", True, "true", ] or self.get_option("general.debug_mode", False) def _init_scaling(self) -> None: self._default_scaling_factor = self.tk.call("tk", "scaling") if self._default_scaling_factor > 10: # it may be infinity in eg. Fedora self._default_scaling_factor = 1.33 scaling = self.get_option("general.scaling") if scaling in ["default", "auto"]: # auto was used in 2.2b3 self._scaling_factor = self._default_scaling_factor else: self._scaling_factor = float(scaling) MAC_SCALING_MODIFIER = 1.7 if running_on_mac_os(): self._scaling_factor *= MAC_SCALING_MODIFIER self.tk.call("tk", "scaling", self._scaling_factor) font_scaling_mode = self.get_option("general.font_scaling_mode") if ( running_on_linux() and font_scaling_mode in ["default", "extra"] and scaling not in ["default", "auto"] ): # update system fonts which are given in pixel sizes for name in tk_font.names(): f = tk_font.nametofont(name) orig_size = f.cget("size") # According to do documentation, absolute values of negative font sizes # should be interpreted as pixel sizes (not affected by "tk scaling") # and positive values are point sizes, which are supposed to scale automatically # http://www.tcl.tk/man/tcl8.6/TkCmd/font.htm#M26 # Unfortunately it seems that this cannot be relied on # https://groups.google.com/forum/#!msg/comp.lang.tcl/ZpL6tq77M4M/GXImiV2INRQJ # My experiments show that manually changing negative font sizes # doesn't have any effect -- fonts keep their default size # (Tested in Raspbian Stretch, Ubuntu 18.04 and Fedora 29) # On the other hand positive sizes scale well (and they don't scale automatically) # convert pixel sizes to point_size if orig_size < 0: orig_size = -orig_size / self._default_scaling_factor # scale scaled_size = round( orig_size * (self._scaling_factor / self._default_scaling_factor) ) f.configure(size=scaled_size) elif running_on_mac_os() and scaling not in ["default", "auto"]: # see http://wiki.tcl.tk/44444 # update system fonts for name in tk_font.names(): f = tk_font.nametofont(name) orig_size = f.cget("size") assert orig_size > 0 f.configure(size=int(orig_size * self._scaling_factor / MAC_SCALING_MODIFIER)) def update_fonts(self) -> None: editor_font_size = self._guard_font_size(self.get_option("view.editor_font_size")) editor_font_family = self.get_option("view.editor_font_family") io_font_size = self._guard_font_size(self.get_option("view.io_font_size")) io_font_family = self.get_option("view.io_font_family") for io_name in [ "IOFont", "BoldIOFont", "UnderlineIOFont", "ItalicIOFont", "BoldItalicIOFont", ]: tk_font.nametofont(io_name).configure(family=io_font_family, size=io_font_size) try: shell = self.get_view("ShellView", create=False) except Exception: # shell may be not created yet pass else: shell.update_tabs() tk_font.nametofont("EditorFont").configure(family=editor_font_family, size=editor_font_size) tk_font.nametofont("SmallEditorFont").configure( family=editor_font_family, size=editor_font_size - 2 ) tk_font.nametofont("BoldEditorFont").configure( family=editor_font_family, size=editor_font_size ) tk_font.nametofont("ItalicEditorFont").configure( family=editor_font_family, size=editor_font_size ) tk_font.nametofont("BoldItalicEditorFont").configure( family=editor_font_family, size=editor_font_size ) if self.get_ui_mode() == "simple": default_size_factor = max(0.7, 1 - (editor_font_size - 10) / 25) small_size_factor = max(0.6, 0.8 - (editor_font_size - 10) / 25) tk_font.nametofont("TkDefaultFont").configure( size=round(editor_font_size * default_size_factor) ) tk_font.nametofont("TkHeadingFont").configure( size=round(editor_font_size * default_size_factor) ) tk_font.nametofont("SmallLinkFont").configure( size=round(editor_font_size * small_size_factor) ) # Update Treeview font and row height if running_on_mac_os(): treeview_font_size = int(editor_font_size * 0.7 + 4) else: treeview_font_size = int(editor_font_size * 0.7 + 2) treeview_font = tk_font.nametofont("TreeviewFont") treeview_font.configure(size=treeview_font_size) rowheight = round(treeview_font.metrics("linespace") * 1.2) style = ttk.Style() style.configure("Treeview", rowheight=rowheight) if self._editor_notebook is not None: self._editor_notebook.update_appearance() def _get_menu_index(self, menu: tk.Menu) -> int: for i in range(len(self._menubar.winfo_children())): if menu == self._menubar.winfo_children()[i]: return i raise RuntimeError("Couldn't find menu") def _add_toolbar_button( self, command_id: str, image: Optional[tk.PhotoImage], disabled_image: Optional[tk.PhotoImage], command_label: str, caption: str, alternative_caption: str, accelerator: Optional[str], handler: Callable[[], None], tester: Optional[Callable[[], bool]], toolbar_group: int, ) -> None: assert caption is not None and len(caption) > 0, ( "Missing caption for '%s'. Toolbar commands must have caption." % command_label ) slaves = self._toolbar.grid_slaves(0, toolbar_group) if len(slaves) == 0: group_frame = ttk.Frame(self._toolbar) if self.in_simple_mode(): padx = 0 # type: Union[int, Tuple[int, int]] else: padx = (0, 10) group_frame.grid(row=0, column=toolbar_group, padx=padx) else: group_frame = slaves[0] if self.in_simple_mode(): screen_width = self.winfo_screenwidth() if screen_width >= 1280: button_width = max(7, len(caption), len(alternative_caption)) elif screen_width >= 1024: button_width = max(6, len(caption), len(alternative_caption)) else: button_width = max(5, len(caption), len(alternative_caption)) else: button_width = None if disabled_image is not None: image_spec = [image, "disabled", disabled_image] else: image_spec = image button = ttk.Button( group_frame, command=handler, image=image_spec, style="Toolbutton", state=tk.NORMAL, text=caption, compound="top" if self.in_simple_mode() else None, pad=(10, 0) if self.in_simple_mode() else None, width=button_width, ) button.pack(side=tk.LEFT) button.tester = tester # type: ignore tooltip_text = command_label if self.get_ui_mode() != "simple": if accelerator and lookup_style_option( "OPTIONS", "shortcuts_in_tooltips", default=True ): tooltip_text += " (" + accelerator + ")" create_tooltip(button, tooltip_text) self._toolbar_buttons[command_id] = button def get_toolbar_button(self, command_id): return self._toolbar_buttons[command_id] def _update_toolbar(self) -> None: if self._destroyed or not hasattr(self, "_toolbar"): return if self._toolbar.winfo_ismapped(): for group_frame in self._toolbar.grid_slaves(0): for button in group_frame.pack_slaves(): if thonny._runner is None or button.tester and not button.tester(): button["state"] = tk.DISABLED else: button["state"] = tk.NORMAL def _cmd_zoom_with_mouse(self, event) -> None: if event.delta > 0: self._change_font_size(1) else: self._change_font_size(-1) def _toggle_font_size(self) -> None: current_size = self.get_option("view.editor_font_size") if self.winfo_screenwidth() < 1024: # assuming 32x32 icons small_size = 10 medium_size = 12 large_size = 14 elif self.winfo_screenwidth() < 1280: # assuming 32x32 icons small_size = 12 medium_size = 14 large_size = 18 else: small_size = 12 medium_size = 16 large_size = 20 widths = {10: 800, 12: 1050, 14: 1200, 16: 1300, 18: 1400, 20: 1650} if current_size < small_size or current_size >= large_size: new_size = small_size elif current_size < medium_size: new_size = medium_size else: new_size = large_size self._change_font_size(new_size - current_size) new_width = min(widths[new_size], self.winfo_screenwidth()) geo = re.findall(r"\d+", self.wm_geometry()) self.geometry("{0}x{1}+{2}+{3}".format(new_width, geo[1], geo[2], geo[3])) def _change_font_size(self, delta: int) -> None: if delta != 0: editor_font_size = self.get_option("view.editor_font_size") editor_font_size += delta self.set_option("view.editor_font_size", self._guard_font_size(editor_font_size)) io_font_size = self.get_option("view.io_font_size") io_font_size += delta self.set_option("view.io_font_size", self._guard_font_size(io_font_size)) self.update_fonts() def _guard_font_size(self, size: int) -> int: # https://bitbucket.org/plas/thonny/issues/164/negative-font-size-crashes-thonny MIN_SIZE = 4 MAX_SIZE = 200 if size < MIN_SIZE: return MIN_SIZE elif size > MAX_SIZE: return MAX_SIZE else: return size def _check_update_window_width(self, delta: int) -> None: if not ui_utils.get_zoomed(self): self.update_idletasks() # TODO: shift to left if right edge goes away from screen # TODO: check with screen width new_geometry = "{0}x{1}+{2}+{3}".format( self.winfo_width() + delta, self.winfo_height(), self.winfo_x(), self.winfo_y() ) self.geometry(new_geometry) def _maximize_view(self, event=None) -> None: if self._maximized_view is not None: return # find the widget that can be relocated widget = self.focus_get() if isinstance(widget, (EditorNotebook, AutomaticNotebook)): current_tab = widget.get_current_child() if current_tab is None: return if not hasattr(current_tab, "maximizable_widget"): return widget = current_tab.maximizable_widget while widget is not None: if hasattr(widget, "home_widget"): # if widget is view, then widget.master is workbench widget.grid( row=1, column=0, sticky=tk.NSEW, in_=widget.master # type: ignore ) # hide main_frame self._main_frame.grid_forget() self._maximized_view = widget self.get_variable("view.maximize_view").set(True) break else: widget = widget.master # type: ignore def _unmaximize_view(self, event=None) -> None: if self._maximized_view is None: return # restore main_frame self._main_frame.grid(row=1, column=0, sticky=tk.NSEW, in_=self) # put the maximized view back to its home_widget self._maximized_view.grid( row=0, column=0, sticky=tk.NSEW, in_=self._maximized_view.home_widget # type: ignore ) self._maximized_view = None self.get_variable("view.maximize_view").set(False) def show_options(self, page_key=None): dlg = ConfigurationDialog(self, self._configuration_pages) if page_key: dlg.select_page(page_key) ui_utils.show_dialog(dlg) def _cmd_focus_editor(self) -> None: self.get_editor_notebook().focus_set() def _cmd_focus_shell(self) -> None: self.show_view("ShellView", True) shell = get_shell() # go to the end of any current input shell.text.mark_set("insert", "end") shell.text.see("insert") def _cmd_toggle_full_screen(self) -> None: """ TODO: For mac http://wiki.tcl.tk/44444 Switching a window to fullscreen mode (Normal Difference) To switch a window to fullscreen mode, the window must first be withdrawn. # For Linux/Mac OS X: set cfs [wm attributes $w -fullscreen] if { $::tcl_platform(os) eq "Darwin" } { if { $cfs == 0 } { # optional: save the window geometry set savevar [wm geometry $w] } wm withdraw $w } wm attributes $w -fullscreen [expr {1-$cfs}] if { $::tcl_platform(os) eq "Darwin" } { wm deiconify $w if { $cfs == 1 } { after idle [list wm geometry $w $savevar] } } """ var = self.get_variable("view.full_screen") var.set(not var.get()) self.attributes("-fullscreen", var.get()) def _cmd_toggle_maximize_view(self) -> None: if self._maximized_view is not None: self._unmaximize_view() else: self._maximize_view() def _update_menu(self, menu: tk.Menu, menu_name: str) -> None: if menu.index("end") is None: return for i in range(menu.index("end") + 1): item_data = menu.entryconfigure(i) if "label" in item_data: command_label = menu.entrycget(i, "label") if (menu_name, command_label) not in self._menu_item_specs: continue tester = self._menu_item_specs[(menu_name, command_label)].tester enabled = not tester if tester: try: enabled = tester() except Exception: traceback.print_exc() enabled = False if enabled: menu.entryconfigure(i, state=tk.NORMAL) else: menu.entryconfigure(i, state=tk.DISABLED) def _find_location_for_menu_item(self, menu_name: str, command_label: str) -> Union[str, int]: menu = self.get_menu(menu_name) if menu.index("end") == None: # menu is empty return "end" specs = self._menu_item_specs[(menu_name, command_label)] this_group_exists = False for i in range(0, menu.index("end") + 1): data = menu.entryconfigure(i) if "label" in data: # it's a command, not separator sibling_label = menu.entrycget(i, "label") sibling_group = self._menu_item_specs[(menu_name, sibling_label)].group if sibling_group == specs.group: this_group_exists = True if specs.position_in_group == "alphabetic" and sibling_label > command_label: return i if sibling_group > specs.group: assert ( not this_group_exists ) # otherwise we would have found the ending separator menu.insert_separator(i) return i else: # We found a separator if this_group_exists: # it must be the ending separator for this group return i # no group was bigger, ie. this should go to the end if not this_group_exists: menu.add_separator() return "end" def _poll_ipc_requests(self) -> None: try: if self._ipc_requests.empty(): return while not self._ipc_requests.empty(): args = self._ipc_requests.get() try: for filename in args: if os.path.isfile(filename): self.get_editor_notebook().show_file(filename) except Exception: traceback.print_exc() self.become_active_window() finally: self.after(50, self._poll_ipc_requests) def _on_close(self) -> None: if not self.get_editor_notebook().check_allow_closing(): return self._closing = True try: self._save_layout() self._editor_notebook.remember_open_files() self.event_generate("WorkbenchClose") self._configuration_manager.save() except Exception: self.report_exception() self.destroy() self._destroyed = True def _on_all_key_presses(self, event): if running_on_windows(): ui_utils.handle_mistreated_latin_shortcuts(self._latin_shortcuts, event) def _on_focus_in(self, event): if self._lost_focus: self._lost_focus = False self.event_generate("WindowFocusIn") def _on_focus_out(self, event): if self.focus_get() is None: if not self._lost_focus: self._lost_focus = True self.event_generate("WindowFocusOut") def focus_get(self) -> Optional[tk.Widget]: try: return tk.Tk.focus_get(self) except Exception: # This may give error in Ubuntu return None def destroy(self) -> None: try: if self._is_server() and os.path.exists(thonny.IPC_FILE): os.remove(thonny.IPC_FILE) self._closing = True # Tk clipboard gets cleared on exit and won't end up in system clipboard # https://bugs.python.org/issue1207592 # https://stackoverflow.com/questions/26321333/tkinter-in-python-3-4-on-windows-dont-post-internal-clipboard-data-to-the-windo try: clipboard_data = self.clipboard_get() if len(clipboard_data) < 1000 and all( map(os.path.exists, clipboard_data.splitlines()) ): # Looks like the clipboard contains file name(s) # Most likely this means actual file cut/copy operation # was made outside of Thonny. # Don't want to replace this with simple string data of file names. pass else: copy_to_clipboard(clipboard_data) except Exception: pass except Exception: logging.exception("Error while destroying workbench") finally: try: super().destroy() finally: runner = get_runner() if runner != None: runner.destroy_backend() def _on_configure(self, event) -> None: # called when window is moved or resized if ( hasattr(self, "_maximized_view") # configure may happen before the attribute is defined and self._maximized_view # type: ignore ): # grid again, otherwise it acts weird self._maximized_view.grid( row=1, column=0, sticky=tk.NSEW, in_=self._maximized_view.master # type: ignore ) def _on_tk_exception(self, exc, val, tb) -> None: # copied from tkinter.Tk.report_callback_exception with modifications # see http://bugs.python.org/issue22384 sys.last_type = exc sys.last_value = val sys.last_traceback = tb self.report_exception() def report_exception(self, title: str = "Internal error") -> None: logging.exception(title) if tk._default_root and not self._closing: # type: ignore (typ, value, _) = sys.exc_info() assert typ is not None if issubclass(typ, UserError): msg = str(value) else: msg = traceback.format_exc() dlg = ui_utils.LongTextDialog(title, msg, parent=self) ui_utils.show_dialog(dlg, self) def _open_views(self) -> None: for nb_name in self._view_notebooks: view_name = self.get_option("layout.notebook_" + nb_name + "_visible_view") if view_name != None: if view_name == "GlobalsView": # was renamed in 2.2b5 view_name = "VariablesView" if self.get_ui_mode() != "simple" or view_name in SIMPLE_MODE_VIEWS: self.show_view(view_name) # make sure VariablesView is at least loaded # otherwise it may miss globals events # and will show empty table on open self.get_view("VariablesView") if ( self.get_option("assistance.open_assistant_on_errors") or self.get_option("assistance.open_assistant_on_warnings") ) and (self.get_ui_mode() != "simple" or "AssistantView" in SIMPLE_MODE_VIEWS): self.get_view("AssistantView") def _save_layout(self) -> None: self.update_idletasks() self.set_option("layout.zoomed", ui_utils.get_zoomed(self)) for nb_name in self._view_notebooks: widget = self._view_notebooks[nb_name].get_visible_child() if hasattr(widget, "maximizable_widget"): view = widget.maximizable_widget view_name = type(view).__name__ self.set_option("layout.notebook_" + nb_name + "_visible_view", view_name) else: self.set_option("layout.notebook_" + nb_name + "_visible_view", None) if not ui_utils.get_zoomed(self) or running_on_mac_os(): # can't restore zoom on mac without setting actual dimensions gparts = re.findall(r"\d+", self.wm_geometry()) self.set_option("layout.width", int(gparts[0])) self.set_option("layout.height", int(gparts[1])) self.set_option("layout.left", int(gparts[2])) self.set_option("layout.top", int(gparts[3])) self.set_option("layout.west_pw_width", self._west_pw.preferred_size_in_pw) self.set_option("layout.east_pw_width", self._east_pw.preferred_size_in_pw) for key in ["nw", "sw", "s", "se", "ne"]: self.set_option( "layout.%s_nb_height" % key, self._view_notebooks[key].preferred_size_in_pw ) def update_title(self, event=None) -> None: editor = self.get_editor_notebook().get_current_editor() if self._is_portable: title_text = "Portable Thonny" else: title_text = "Thonny" if editor != None: title_text += " - " + editor.get_long_description() self.title(title_text) def become_active_window(self, force=True) -> None: # Looks like at least on Windows all following is required # for ensuring the window gets focus # (deiconify, ..., iconify, deiconify) self.deiconify() if force: self.attributes("-topmost", True) self.after_idle(self.attributes, "-topmost", False) self.lift() if not running_on_linux(): # http://stackoverflow.com/a/13867710/261181 self.iconify() self.deiconify() editor = self.get_editor_notebook().get_current_editor() if editor is not None: # This method is meant to be called when new file is opened, so it's safe to # send the focus to the editor editor.focus_set() else: self.focus_set() def open_url(self, url): m = re.match(r"^thonny-editor://(.*?)(#(\d+)(:(\d+))?)?$", url) if m is not None: filename = m.group(1).replace("%20", " ") lineno = None if m.group(3) is None else int(m.group(3)) col_offset = None if m.group(5) is None else int(m.group(5)) if lineno is None: self.get_editor_notebook().show_file(filename) else: self.get_editor_notebook().show_file_at_line(filename, lineno, col_offset) return m = re.match(r"^thonny-help://(.*?)(#(.+))?$", url) if m is not None: topic = m.group(1) fragment = m.group(3) self.show_view("HelpView").load_topic(topic, fragment) return if url.endswith(".rst") and not url.startswith("http"): parts = url.split("#", maxsplit=1) topic = parts[0][:-4] if len(parts) == 2: fragment = parts[1] else: fragment = None self.show_view("HelpView").load_topic(topic, fragment) return # Fallback webbrowser.open(url, False, True) def open_help_topic(self, topic, fragment=None): self.show_view("HelpView").load_topic(topic, fragment) def bell(self, displayof=0): if not self.get_option("general.disable_notification_sound"): super().bell(displayof=displayof) def _mac_quit(self, *args): self._on_close() def _is_server(self): return self._ipc_requests is not None def get_toolbar(self): return self._toolbar class WorkbenchEvent(Record): def __init__(self, sequence: str, **kwargs) -> None: Record.__init__(self, **kwargs) self.sequence = sequence thonny-3.2.7/thonny/running.py0000644000175000017500000015142413611773167017450 0ustar annamaaannamaa00000000000000# -*- coding: utf-8 -*- """Code for maintaining the background process and for running user programs Commands get executed via shell, this way the command line in the shell becomes kind of title for the execution. """ import collections import logging import os.path import shlex import shutil import signal import subprocess import sys import time from logging import debug from threading import Thread from time import sleep from tkinter import ttk from thonny import THONNY_USER_DIR, common, get_runner, get_shell, get_workbench, ui_utils from thonny.code import get_current_breakpoints, get_saved_current_script_filename, is_remote_path from thonny.common import ( BackendEvent, CommandToBackend, DebuggerCommand, DebuggerResponse, InlineCommand, InputSubmission, ToplevelCommand, ToplevelResponse, UserError, normpath_with_actual_case, is_same_path, parse_message, path_startswith, serialize_message, update_system_path, EOFCommand, ) from thonny.misc_utils import construct_cmd_line, running_on_mac_os, running_on_windows from typing import Any, List, Optional, Sequence, Set # @UnusedImport; @UnusedImport from thonny.terminal import run_in_terminal from thonny.ui_utils import select_sequence, show_dialog, CommonDialogEx from tkinter import messagebox import warnings import re import traceback WINDOWS_EXE = "python.exe" OUTPUT_MERGE_THRESHOLD = 1000 RUN_COMMAND_LABEL = "" # init later when gettext is ready RUN_COMMAND_CAPTION = "" EDITOR_CONTENT_TOKEN = "$EDITOR_CONTENT" EXPECTED_TERMINATION_CODE = 123 ANSI_CODE_TERMINATOR = re.compile("[@-~]") # other components may turn it on in order to avoid grouping output lines into one event io_animation_required = False _console_allocated = False class Runner: def __init__(self) -> None: get_workbench().set_default("run.auto_cd", True) self._init_commands() self._state = "starting" self._proxy = None # type: Any self._publishing_events = False self._polling_after_id = None self._postponed_commands = [] # type: List[CommandToBackend] def _remove_obsolete_jedi_copies(self) -> None: # Thonny 2.1 used to copy jedi in order to make it available # for the backend. Get rid of it now for item in os.listdir(THONNY_USER_DIR): if item.startswith("jedi_0."): shutil.rmtree(os.path.join(THONNY_USER_DIR, item), True) def start(self) -> None: global _console_allocated try: self._check_alloc_console() _console_allocated = True except Exception: logging.getLogger("thonny").exception("Problem allocating console") _console_allocated = False self.restart_backend(False, True) # temporary self._remove_obsolete_jedi_copies() def _init_commands(self) -> None: global RUN_COMMAND_CAPTION, RUN_COMMAND_LABEL RUN_COMMAND_LABEL = _("Run current script") RUN_COMMAND_CAPTION = _("Run") get_workbench().set_default("run.run_in_terminal_python_repl", False) get_workbench().set_default("run.run_in_terminal_keep_open", True) try: import thonny.plugins.debugger # @UnusedImport debugger_available = True except ImportError: debugger_available = False get_workbench().add_command( "run_current_script", "run", RUN_COMMAND_LABEL, caption=RUN_COMMAND_CAPTION, handler=self.cmd_run_current_script, default_sequence="", extra_sequences=[select_sequence("", "")], tester=self.cmd_run_current_script_enabled, group=10, image="run-current-script", include_in_toolbar=not (get_workbench().in_simple_mode() and debugger_available), show_extra_sequences=True, ) get_workbench().add_command( "run_current_script_in_terminal", "run", _("Run current script in terminal"), caption="RunT", handler=self._cmd_run_current_script_in_terminal, default_sequence="", extra_sequences=["<>"], tester=self._cmd_run_current_script_in_terminal_enabled, group=35, image="terminal", ) get_workbench().add_command( "restart", "run", _("Stop/Restart backend"), caption=_("Stop"), handler=self.cmd_stop_restart, default_sequence="", group=100, image="stop", include_in_toolbar=True, ) get_workbench().add_command( "interrupt", "run", _("Interrupt execution"), handler=self._cmd_interrupt, tester=self._cmd_interrupt_enabled, default_sequence="", group=100, bell_when_denied=False, ) get_workbench().add_command( "ctrld", "run", _("Send EOF / Soft reboot"), self.ctrld, self.ctrld_enabled, group=100, default_sequence="", extra_sequences=["<>"], ) get_workbench().add_command( "disconnect", "run", _("Disconnect"), self.disconnect, self.disconnect_enabled, group=100, ) def get_state(self) -> str: """State is one of "running", "waiting_debugger_command", "waiting_toplevel_command" """ return self._state def _set_state(self, state: str) -> None: if self._state != state: logging.debug("Runner state changed: %s ==> %s" % (self._state, state)) self._state = state def is_running(self): return self._state == "running" def is_waiting(self): return self._state.startswith("waiting") def is_waiting_toplevel_command(self): return self._state == "waiting_toplevel_command" def is_waiting_debugger_command(self): return self._state == "waiting_debugger_command" def get_sys_path(self) -> List[str]: return self._proxy.get_sys_path() def send_command(self, cmd: CommandToBackend) -> None: if self._proxy is None: return if self._publishing_events: # allow all event handlers to complete before sending the commands # issued by first event handlers self._postpone_command(cmd) return # First sanity check if ( isinstance(cmd, ToplevelCommand) and not self.is_waiting_toplevel_command() and cmd.name not in ["Reset", "Run", "Debug"] or isinstance(cmd, DebuggerCommand) and not self.is_waiting_debugger_command() ): get_workbench().bell() logging.warning( "RUNNER: Command %s was attempted at state %s" % (cmd, self.get_state()) ) return # Attach extra info if "debug" in cmd.name.lower(): cmd["breakpoints"] = get_current_breakpoints() if "id" not in cmd: cmd["id"] = generate_command_id() cmd["local_cwd"] = get_workbench().get_local_cwd() # Offer the command logging.debug("RUNNER Sending: %s, %s", cmd.name, cmd) response = self._proxy.send_command(cmd) if response == "discard": return elif response == "postpone": self._postpone_command(cmd) return else: assert response is None get_workbench().event_generate("CommandAccepted", command=cmd) if isinstance(cmd, (ToplevelCommand, DebuggerCommand)): self._set_state("running") if cmd.name[0].isupper(): get_workbench().event_generate("BackendRestart", full=False) if cmd.get("blocking"): dlg = BlockingDialog(get_workbench(), cmd) show_dialog(dlg) return dlg.response def _postpone_command(self, cmd: CommandToBackend) -> None: # in case of InlineCommands, discard older same type command if isinstance(cmd, InlineCommand): for older_cmd in self._postponed_commands: if older_cmd.name == cmd.name: self._postponed_commands.remove(older_cmd) if len(self._postponed_commands) > 10: logging.warning("Can't pile up too many commands. This command will be just ignored") else: self._postponed_commands.append(cmd) def _send_postponed_commands(self) -> None: todo = self._postponed_commands self._postponed_commands = [] for cmd in todo: logging.debug("Sending postponed command: %s", cmd) self.send_command(cmd) def send_program_input(self, data: str) -> None: assert self.is_running() self._proxy.send_program_input(data) def execute_script( self, script_path: str, args: List[str], working_directory: Optional[str] = None, command_name: str = "Run", ) -> None: if working_directory is not None and get_workbench().get_local_cwd() != working_directory: # create compound command # start with %cd cd_cmd_line = construct_cd_command(working_directory) + "\n" next_cwd = working_directory else: # create simple command cd_cmd_line = "" next_cwd = get_workbench().get_local_cwd() if not is_remote_path(script_path) and self._proxy.uses_local_filesystem(): rel_filename = os.path.relpath(script_path, next_cwd) cmd_parts = ["%" + command_name, rel_filename] + args else: cmd_parts = ["%" + command_name, "-c", EDITOR_CONTENT_TOKEN] + args exe_cmd_line = construct_cmd_line(cmd_parts, [EDITOR_CONTENT_TOKEN]) + "\n" # submit to shell (shell will execute it) get_shell().submit_magic_command(cd_cmd_line + exe_cmd_line) def execute_current(self, command_name: str) -> None: """ This method's job is to create a command for running/debugging current file/script and submit it to shell """ if not self.is_waiting_toplevel_command(): self.restart_backend(True, False, 2) filename = get_saved_current_script_filename() if not filename: # user has cancelled file saving return if is_remote_path(filename) or not self._proxy.uses_local_filesystem(): working_directory = None else: # changing dir may be required script_dir = os.path.dirname(filename) if get_workbench().get_option("run.auto_cd") and command_name[0].isupper(): working_directory = script_dir # type: Optional[str] else: working_directory = None args = self._get_active_arguments() self.execute_script(filename, args, working_directory, command_name) def _get_active_arguments(self): if get_workbench().get_option("view.show_program_arguments"): args_str = get_workbench().get_option("run.program_arguments") get_workbench().log_program_arguments_string(args_str) return shlex.split(args_str) else: return [] def cmd_run_current_script_enabled(self) -> bool: return ( get_workbench().get_editor_notebook().get_current_editor() is not None and "run" in get_runner().get_supported_features() ) def _cmd_run_current_script_in_terminal_enabled(self) -> bool: return ( self._proxy and "run_in_terminal" in self._proxy.get_supported_features() and self.cmd_run_current_script_enabled() ) def cmd_run_current_script(self) -> None: if get_workbench().in_simple_mode(): get_workbench().hide_view("VariablesView") self.execute_current("Run") def _cmd_run_current_script_in_terminal(self) -> None: filename = get_saved_current_script_filename() self._proxy.run_script_in_terminal( filename, self._get_active_arguments(), get_workbench().get_option("run.run_in_terminal_python_repl"), get_workbench().get_option("run.run_in_terminal_keep_open"), ) def _cmd_interrupt(self) -> None: if self._proxy is not None: if _console_allocated: self._proxy.interrupt() else: messagebox.showerror( "No console", "Can't interrupt as console was not allocated.\n\nUse Stop/Restart instead.", ) else: logging.warning("Interrupting without proxy") def _cmd_interrupt_enabled(self) -> bool: if not self._proxy or not self._proxy.is_connected(): return False # TODO: distinguish command and Ctrl+C shortcut widget = get_workbench().focus_get() if not running_on_mac_os(): # on Mac Ctrl+C is not used for Copy if widget is not None and hasattr(widget, "selection_get"): try: selection = widget.selection_get() if isinstance(selection, str) and len(selection) > 0: # assuming user meant to copy, not interrupt # (IDLE seems to follow same logic) return False except Exception: # selection_get() gives error when calling without selection on Ubuntu pass return self.is_running() or self.is_waiting_toplevel_command() def cmd_stop_restart(self) -> None: if get_workbench().in_simple_mode(): get_workbench().hide_view("VariablesView") self.restart_backend(True) def disconnect(self): proxy = self.get_backend_proxy() assert hasattr(proxy, "disconnect") proxy.disconnect() def disconnect_enabled(self): return hasattr(self.get_backend_proxy(), "disconnect") def ctrld(self): proxy = self.get_backend_proxy() if not proxy: return if get_shell().has_pending_input(): messagebox.showerror( "Can't perform this action", "Ctrl+D only has effect on an empty line / prompt.\n" + "Submit current input (press ENTER) and try again", ) return proxy.send_command(EOFCommand()) self._set_state("running") def ctrld_enabled(self): proxy = self.get_backend_proxy() return proxy and proxy.is_connected() def _poll_vm_messages(self) -> None: """I chose polling instead of event_generate in listener thread, because event_generate across threads is not reliable http://www.thecodingforums.com/threads/more-on-tk-event_generate-and-threads.359615/ """ self._polling_after_id = None if self._pull_vm_messages() is False: return self._polling_after_id = get_workbench().after(20, self._poll_vm_messages) def _pull_vm_messages(self): while self._proxy is not None: try: msg = self._proxy.fetch_next_message() if not msg: break logging.debug( "RUNNER GOT: %s, %s in state: %s", msg.event_type, msg, self.get_state() ) except BackendTerminatedError as exc: self._report_backend_crash(exc) self.destroy_backend() return False if msg.get("SystemExit", False): self.restart_backend(True) return False # change state if isinstance(msg, ToplevelResponse): self._set_state("waiting_toplevel_command") elif isinstance(msg, DebuggerResponse): self._set_state("waiting_debugger_command") else: "other messages don't affect the state" if "cwd" in msg: if not self.supports_remote_files(): get_workbench().set_local_cwd(msg["cwd"]) # Publish the event # NB! This may cause another command to be sent before we get to postponed commands. try: self._publishing_events = True class_event_type = type(msg).__name__ get_workbench().event_generate(class_event_type, event=msg) # more general event if msg.event_type != class_event_type: # more specific event get_workbench().event_generate(msg.event_type, event=msg) finally: self._publishing_events = False # TODO: is it necessary??? # https://stackoverflow.com/a/13520271/261181 # get_workbench().update() self._send_postponed_commands() def _report_backend_crash(self, exc: Exception) -> None: returncode = getattr(exc, "returncode", "?") err = "Backend terminated or disconnected." try: faults_file = os.path.join(THONNY_USER_DIR, "backend_faults.log") if os.path.exists(faults_file): with open(faults_file, encoding="ASCII") as fp: err += fp.read() except Exception: logging.exception("Failed retrieving backend faults") err = err.strip() + " Use 'Stop/Restart' to restart.\n" if returncode != EXPECTED_TERMINATION_CODE: get_workbench().event_generate("ProgramOutput", stream_name="stderr", data="\n" + err) get_workbench().become_active_window(False) def restart_backend(self, clean: bool, first: bool = False, wait: float = 0) -> None: """Recreate (or replace) backend proxy / backend process.""" if not first: get_shell().restart() get_shell().update_idletasks() self.destroy_backend() backend_name = get_workbench().get_option("run.backend_name") if backend_name not in get_workbench().get_backends(): raise UserError( "Can't find backend '{}'. Please select another backend from options".format( backend_name ) ) backend_class = get_workbench().get_backends()[backend_name].proxy_class self._set_state("running") self._proxy = None self._proxy = backend_class(clean) self._poll_vm_messages() if wait: start_time = time.time() while not self.is_waiting_toplevel_command() and time.time() - start_time <= wait: # self._pull_vm_messages() get_workbench().update() sleep(0.01) get_workbench().event_generate("BackendRestart", full=True) def destroy_backend(self) -> None: if self._polling_after_id is not None: get_workbench().after_cancel(self._polling_after_id) self._polling_after_id = None self._postponed_commands = [] if self._proxy: self._proxy.destroy() self._proxy = None get_workbench().event_generate("BackendTerminated") def get_local_executable(self) -> Optional[str]: if self._proxy is None: return None else: return self._proxy.get_local_executable() def get_backend_proxy(self) -> "BackendProxy": return self._proxy def _check_alloc_console(self) -> None: if sys.executable.endswith("pythonw.exe"): # These don't have console allocated. # Console is required for sending interrupts. # AllocConsole would be easier but flashes console window import ctypes kernel32 = ctypes.WinDLL("kernel32", use_last_error=True) exe = sys.executable.replace("pythonw.exe", "python.exe") cmd = [exe, "-c", "print('Hi!'); input()"] child = subprocess.Popen( cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, ) child.stdout.readline() result = kernel32.AttachConsole(child.pid) if not result: err = ctypes.get_last_error() logging.info("Could not allocate console. Error code: " + str(err)) child.stdin.write(b"\n") try: child.stdin.flush() except Exception: # May happen eg. when installation path has "&" in it # See https://bitbucket.org/plas/thonny/issues/508/cant-allocate-windows-console-when # Without flush the console window becomes visible, but Thonny can be still used logging.getLogger("thonny").exception("Problem with finalizing console allocation") def ready_for_remote_file_operations(self, show_message=False): if not self._proxy or not self.supports_remote_files(): return False ready = self._proxy.ready_for_remote_file_operations() if not ready and show_message: if self._proxy.is_connected(): msg = "Device is not connected" else: msg = ( "Device is busy -- can't perform this action now." + "\nPlease wait or cancel current work and try again!", ) messagebox.showerror("Can't complete", msg) return ready def get_supported_features(self) -> Set[str]: if self._proxy is None: return set() else: return self._proxy.get_supported_features() def supports_remote_files(self): if self._proxy is None: return False else: return self._proxy.supports_remote_files() def supports_remote_directories(self): if self._proxy is None: return False else: return self._proxy.supports_remote_directories() def get_node_label(self): if self._proxy is None: return "Back-end" else: return self._proxy.get_node_label() def using_venv(self) -> bool: return isinstance(self._proxy, CPythonProxy) and self._proxy._in_venv class BackendProxy: """Communicates with backend process. All communication methods must be non-blocking, ie. suitable for calling from GUI thread.""" # backend_name will be overwritten on Workbench.add_backend # Subclasses don't need to worry about it. backend_name = None def __init__(self, clean: bool) -> None: """Initializes (or starts the initialization of) the backend process. Backend is considered ready when the runner gets a ToplevelResponse with attribute "welcome_text" from fetch_next_message. """ def send_command(self, cmd: CommandToBackend) -> Optional[str]: """Send the command to backend. Return None, 'discard' or 'postpone'""" raise NotImplementedError() def send_program_input(self, data: str) -> None: """Send input data to backend""" raise NotImplementedError() def fetch_next_message(self): """Read next message from the queue or None if queue is empty""" raise NotImplementedError() def run_script_in_terminal(self, script_path, interactive, keep_open): raise NotImplementedError() def get_sys_path(self): "backend's sys.path" return [] def get_backend_name(self): return type(self).backend_name def interrupt(self): """Tries to interrupt current command without reseting the backend""" pass def destroy(self): """Called when Thonny no longer needs this instance (Thonny gets closed or new backend gets selected) """ pass def is_connected(self): return True def get_local_executable(self): """Return system command for invoking current interpreter""" return None def get_supported_features(self): return {"run"} def get_node_label(self): """Used as files caption if back-end has separate files""" return "Back-end" def supports_remote_files(self): """Whether remote file browser should be presented with this back-end""" return False def uses_local_filesystem(self): """Whether it runs code from local files""" return True def supports_remote_directories(self): return False def supports_trash(self): return True def ready_for_remote_file_operations(self): return False def get_cwd(self): return None class SubprocessProxy(BackendProxy): def __init__(self, clean: bool, executable: str) -> None: super().__init__(clean) self._executable = executable self._response_queue = None self._welcome_text = "" self._proc = None self._response_queue = None self._sys_path = [] self._usersitepackages = None self._gui_update_loop_id = None self._in_venv = None self._cwd = self._get_initial_cwd() self._start_background_process(clean=clean) def _get_initial_cwd(self): return None def _start_background_process(self, clean=None): # deque, because in one occasion I need to put messages back self._response_queue = collections.deque() # prepare environment env = get_environment_for_python_subprocess(self._executable) # variables controlling communication with the back-end process env["PYTHONIOENCODING"] = "utf-8" # because cmd line option -u won't reach child processes # see https://github.com/thonny/thonny/issues/808 env["PYTHONUNBUFFERED"] = "1" # Let back-end know about plug-ins env["THONNY_USER_DIR"] = THONNY_USER_DIR env["THONNY_FRONTEND_SYS_PATH"] = repr(sys.path) env["THONNY_LANGUAGE"] = get_workbench().get_option("general.language") env["FRIENDLY_TRACEBACK_LEVEL"] = str( get_workbench().get_option("assistance.friendly_traceback_level") ) if get_workbench().in_debug_mode(): env["THONNY_DEBUG"] = "1" elif "THONNY_DEBUG" in env: del env["THONNY_DEBUG"] if not os.path.exists(self._executable): raise UserError( "Interpreter (%s) not found. Please recheck corresponding option!" % self._executable ) cmd_line = [ self._executable, "-u", # unbuffered IO "-B", # don't write pyo/pyc files # (to avoid problems when using different Python versions without write permissions) ] + self._get_launcher_with_args() creationflags = 0 if running_on_windows(): creationflags = subprocess.CREATE_NEW_PROCESS_GROUP debug("Starting the backend: %s %s", cmd_line, get_workbench().get_local_cwd()) extra_params = {} if sys.version_info >= (3, 6): extra_params["encoding"] = "utf-8" self._proc = subprocess.Popen( cmd_line, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.get_cwd() if self.uses_local_filesystem() else None, env=env, universal_newlines=True, creationflags=creationflags, **extra_params ) # setup asynchronous output listeners Thread(target=self._listen_stdout, args=(self._proc.stdout,), daemon=True).start() Thread(target=self._listen_stderr, args=(self._proc.stderr,), daemon=True).start() def _get_launcher_with_args(self): raise NotImplementedError() def send_command(self, cmd: CommandToBackend) -> Optional[str]: """Send the command to backend. Return None, 'discard' or 'postpone'""" method_name = "_cmd_" + cmd.name if hasattr(self, method_name): return getattr(self, method_name)(cmd) if isinstance(cmd, ToplevelCommand) and cmd.name[0].isupper(): self._clear_environment() self._send_msg(cmd) def _send_msg(self, msg): self._proc.stdin.write(serialize_message(msg) + "\n") self._proc.stdin.flush() def _clear_environment(self): pass def send_program_input(self, data): self._send_msg(InputSubmission(data)) def process_is_alive(self): return self._proc is not None and self._proc.poll() is None def is_connected(self): return self.process_is_alive() def get_sys_path(self): return self._sys_path def interrupt(self): if self._proc is not None and self._proc.poll() is None: if running_on_windows(): try: os.kill(self._proc.pid, signal.CTRL_BREAK_EVENT) # @UndefinedVariable except Exception: logging.exception("Could not interrupt backend process") else: self._proc.send_signal(signal.SIGINT) def destroy(self): self._close_backend() def _close_backend(self): if self._proc is not None and self._proc.poll() is None: self._proc.kill() self._proc = None self._response_queue = None def _listen_stdout(self, stdout): # debug("... started listening to stdout") # will be called from separate thread message_queue = self._response_queue def publish_as_msg(data): msg = parse_message(data) if "cwd" in msg: self.cwd = msg["cwd"] message_queue.append(msg) if len(message_queue) > 50: # Probably backend runs an infinite/long print loop. # Throttle message thougput in order to keep GUI thread responsive. while len(message_queue) > 0: sleep(0.1) while self.process_is_alive(): data = stdout.readline() # debug("... read some stdout data", repr(data)) if data == "": break else: try: publish_as_msg(data) except Exception: # Can mean the line was from subprocess, # which can't be captured by stream faking. # NB! If subprocess printed it without linebreak, # then the suffix can be thonny message parts = data.rsplit(common.MESSAGE_MARKER, maxsplit=1) # print first part as it is message_queue.append( BackendEvent("ProgramOutput", data=parts[0], stream_name="stdout") ) if len(parts) == 2: second_part = common.MESSAGE_MARKER + parts[1] try: publish_as_msg(second_part) except Exception: # just print ... message_queue.append( BackendEvent( "ProgramOutput", data=second_part, stream_name="stdout" ) ) def _listen_stderr(self, stderr): # stderr is used only for debugger debugging while self.process_is_alive(): data = stderr.readline() if data == "": break else: self._response_queue.append( BackendEvent("ProgramOutput", stream_name="stderr", data=data) ) def _store_state_info(self, msg): if "cwd" in msg: self._cwd = msg["cwd"] if "welcome_text" in msg: self._welcome_text = msg["welcome_text"] if "in_venv" in msg: self._in_venv = msg["in_venv"] if "path" in msg: self._sys_path = msg["path"] if "usersitepackages" in msg: self._usersitepackages = msg["usersitepackages"] if "prefix" in msg: self._sys_prefix = msg["prefix"] if "exe_dirs" in msg: self._exe_dirs = msg["exe_dirs"] def get_supported_features(self): return {"run"} def get_site_packages(self): # NB! site.sitepackages may not be present in virtualenv for d in self._sys_path: if ("site-packages" in d or "dist-packages" in d) and path_startswith( d, self._sys_prefix ): return d return None def get_user_site_packages(self): return self._usersitepackages def get_cwd(self): return self._cwd def get_exe_dirs(self): return self._exe_dirs def fetch_next_message(self): if not self._response_queue or len(self._response_queue) == 0: if not self.process_is_alive(): raise BackendTerminatedError(self._proc.returncode if self._proc else None) else: return None msg = self._response_queue.popleft() self._store_state_info(msg) if msg.event_type == "ProgramOutput": # combine available small output messages to one single message, # in order to put less pressure on UI code wait_time = 0.01 total_wait_time = 0 while True: if len(self._response_queue) == 0: if _ends_with_incomplete_ansi_code(msg["data"]) and total_wait_time < 0.1: # Allow reader to send the remaining part sleep(wait_time) total_wait_time += wait_time continue else: return msg else: next_msg = self._response_queue.popleft() if ( next_msg.event_type == "ProgramOutput" and next_msg["stream_name"] == msg["stream_name"] and ( len(msg["data"]) + len(next_msg["data"]) <= OUTPUT_MERGE_THRESHOLD and ("\n" not in msg["data"] or not io_animation_required) or _ends_with_incomplete_ansi_code(msg["data"]) ) ): msg["data"] += next_msg["data"] else: # not to be sent in the same block, put it back self._response_queue.appendleft(next_msg) return msg else: return msg def _ends_with_incomplete_ansi_code(data): pos = data.rfind("\033") if pos == -1: return False # note ANSI_CODE_TERMINATOR also includes [ params_and_terminator = data[pos + 2 :] return not ANSI_CODE_TERMINATOR.search(params_and_terminator) class CPythonProxy(SubprocessProxy): "abstract class" def __init__(self, clean: bool, executable: str) -> None: super().__init__(clean, executable) self._send_msg(ToplevelCommand("get_environment_info")) def _get_initial_cwd(self): return get_workbench().get_local_cwd() def _get_launcher_with_args(self): import thonny.backend_launcher return [thonny.backend_launcher.__file__] def _store_state_info(self, msg): super()._store_state_info(msg) if "gui_is_active" in msg: self._update_gui_updating(msg) def _clear_environment(self): self._close_backend() self._start_background_process() def _close_backend(self): self._cancel_gui_update_loop() super()._close_backend() def get_local_executable(self): return self._executable def _update_gui_updating(self, msg): """Enables running Tkinter or Qt programs which doesn't call mainloop. When mainloop is omitted, then program can be interacted with from the shell after it runs to the end. Each ToplevelResponse is supposed to tell, whether gui is active and needs updating. """ if not "gui_is_active" in msg: return if msg["gui_is_active"] and self._gui_update_loop_id is None: # Start updating self._loop_gui_update(True) elif not msg["gui_is_active"] and self._gui_update_loop_id is not None: self._cancel_gui_update_loop() def _loop_gui_update(self, force=False): if force or get_runner().is_waiting_toplevel_command(): try: self.send_command(InlineCommand("process_gui_events")) except OSError: # the backend process may have been closed already # https://github.com/thonny/thonny/issues/966 logging.getLogger("thonny").exception("Could not send process_gui_events") self._gui_update_loop_id = get_workbench().after(50, self._loop_gui_update) def _cancel_gui_update_loop(self): if self._gui_update_loop_id is not None: try: get_workbench().after_cancel(self._gui_update_loop_id) finally: self._gui_update_loop_id = None def run_script_in_terminal(self, script_path, args, interactive, keep_open): cmd = [self._executable] if interactive: cmd.append("-i") cmd.append(os.path.basename(script_path)) cmd.extend(args) run_in_terminal(cmd, os.path.dirname(script_path), keep_open=keep_open) def get_supported_features(self): return {"run", "debug", "run_in_terminal", "pip_gui", "system_shell"} class PrivateVenvCPythonProxy(CPythonProxy): def __init__(self, clean): self._prepare_private_venv() super().__init__(clean, get_private_venv_executable()) def _prepare_private_venv(self): path = get_private_venv_path() if os.path.isdir(path) and os.path.isfile(os.path.join(path, "pyvenv.cfg")): self._check_upgrade_private_venv(path) else: self._create_private_venv( path, "Please wait!\nThonny prepares its virtual environment." ) def _check_upgrade_private_venv(self, path): # If home is wrong then regenerate # If only micro version is different, then upgrade info = _get_venv_info(path) if not is_same_path(info["home"], os.path.dirname(sys.executable)): self._create_private_venv( path, "Thonny's virtual environment was created for another interpreter.\n" + "Regenerating the virtual environment for current interpreter.\n" + "(You may need to reinstall your 3rd party packages)\n" + "Please wait!.", clear=True, ) else: venv_version = tuple(map(int, info["version"].split("."))) sys_version = sys.version_info[:3] assert venv_version[0] == sys_version[0] assert venv_version[1] == sys_version[1] if venv_version[2] != sys_version[2]: self._create_private_venv( path, "Please wait!\nUpgrading Thonny's virtual environment.", upgrade=True ) def _create_private_venv(self, path, description, clear=False, upgrade=False): # Don't include system site packages # This way all students will have similar configuration # independently of system Python (if Thonny is used with system Python) # NB! Cant run venv.create directly, because in Windows bundle # it tries to link venv to thonny.exe. # Need to run it via proper python args = ["-m", "venv"] if clear: args.append("--clear") if upgrade: args.append("--upgrade") try: # pylint: disable=unused-variable import ensurepip # @UnusedImport except ImportError: args.append("--without-pip") args.append(path) proc = create_frontend_python_process(args) from thonny.ui_utils import SubprocessDialog dlg = SubprocessDialog( get_workbench(), proc, "Preparing the backend", long_description=description ) try: ui_utils.show_dialog(dlg) except Exception: # if using --without-pip the dialog may close very quickly # and for some reason wait_window would give error then logging.exception("Problem with waiting for venv creation dialog") get_workbench().become_active_window() # Otherwise focus may get stuck somewhere bindir = os.path.dirname(get_private_venv_executable()) # create private env marker marker_path = os.path.join(bindir, "is_private") with open(marker_path, mode="w") as fp: fp.write("# This file marks Thonny-private venv") # Create recommended pip conf to get rid of list deprecation warning # https://github.com/pypa/pip/issues/4058 pip_conf = "pip.ini" if running_on_windows() else "pip.conf" with open(os.path.join(path, pip_conf), mode="w") as fp: fp.write("[list]\nformat = columns") assert os.path.isdir(path) class SameAsFrontendCPythonProxy(CPythonProxy): def __init__(self, clean): super().__init__(clean, get_interpreter_for_subprocess()) def fetch_next_message(self): msg = super().fetch_next_message() if msg and "welcome_text" in msg: if is_bundled_python(self._executable): msg["welcome_text"] += " (bundled)" else: msg["welcome_text"] += " (" + self._executable + ")" return msg class CustomCPythonProxy(CPythonProxy): def __init__(self, clean): executable = get_workbench().get_option("CustomInterpreter.path") # Rembember the usage of this non-default interpreter used_interpreters = get_workbench().get_option("CustomInterpreter.used_paths") if executable not in used_interpreters: used_interpreters.append(executable) get_workbench().set_option("CustomInterpreter.used_paths", used_interpreters) super().__init__(clean, get_interpreter_for_subprocess(executable)) def fetch_next_message(self): msg = super().fetch_next_message() if msg and "welcome_text" in msg: msg["welcome_text"] += " (" + self._executable + ")" return msg def get_private_venv_path(): if is_bundled_python(sys.executable.lower()): prefix = "BundledPython" else: prefix = "Python" return os.path.join( THONNY_USER_DIR, prefix + "%d%d" % (sys.version_info[0], sys.version_info[1]) ) def get_private_venv_executable(): venv_path = get_private_venv_path() if running_on_windows(): exe = os.path.join(venv_path, "Scripts", WINDOWS_EXE) else: exe = os.path.join(venv_path, "bin", "python3") return exe def _get_venv_info(venv_path): cfg_path = os.path.join(venv_path, "pyvenv.cfg") result = {} with open(cfg_path, encoding="UTF-8") as fp: for line in fp: if "=" in line: key, val = line.split("=", maxsplit=1) result[key.strip()] = val.strip() return result def is_bundled_python(executable): return os.path.exists(os.path.join(os.path.dirname(executable), "thonny_python.ini")) def create_backend_python_process( args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ): """Used for running helper commands (eg. pip) on CPython backend. Assumes current backend is CPython.""" # TODO: if backend == frontend, then delegate to create_frontend_python_process python_exe = get_runner().get_local_executable() env = get_environment_for_python_subprocess(python_exe) env["PYTHONIOENCODING"] = "utf-8" env["PYTHONUNBUFFERED"] = "1" # TODO: remove frontend python from path and add backend python to it return _create_python_process(python_exe, args, stdin, stdout, stderr, env=env) def create_frontend_python_process( args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ): """Used for running helper commands (eg. for installing plug-ins on by the plug-ins)""" if _console_allocated: python_exe = get_interpreter_for_subprocess().replace("pythonw.exe", "python.exe") else: python_exe = get_interpreter_for_subprocess().replace("python.exe", "pythonw.exe") env = get_environment_for_python_subprocess(python_exe) env["PYTHONIOENCODING"] = "utf-8" env["PYTHONUNBUFFERED"] = "1" return _create_python_process(python_exe, args, stdin, stdout, stderr) def _create_python_process( python_exe, args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False, env=None, universal_newlines=True, ): cmd = [python_exe] + args if running_on_windows(): creationflags = subprocess.CREATE_NEW_PROCESS_GROUP startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW else: startupinfo = None creationflags = 0 proc = subprocess.Popen( cmd, stdin=stdin, stdout=stdout, stderr=stderr, shell=shell, env=env, universal_newlines=universal_newlines, startupinfo=startupinfo, creationflags=creationflags, ) proc.cmd = cmd return proc class BackendTerminatedError(Exception): def __init__(self, returncode=None): Exception.__init__(self) self.returncode = returncode def is_venv_interpreter_of_current_interpreter(executable): for location in [".", ".."]: cfg_path = os.path.join(location, "pyvenv.cfg") if os.path.isfile(cfg_path): with open(cfg_path) as fp: content = fp.read() for line in content.splitlines(): if line.replace(" ", "").startswith("home="): _, home = line.split("=", maxsplit=1) home = home.strip() if os.path.isdir(home) and os.path.samefile(home, sys.prefix): return True return False def get_environment_for_python_subprocess(target_executable): overrides = get_environment_overrides_for_python_subprocess(target_executable) return get_environment_with_overrides(overrides) def get_environment_with_overrides(overrides): env = os.environ.copy() for key in overrides: if overrides[key] is None and key in env: del env[key] else: assert isinstance(overrides[key], str) if key.upper() == "PATH": update_system_path(env, overrides[key]) else: env[key] = overrides[key] return env def get_environment_overrides_for_python_subprocess(target_executable): """Take care of not not confusing different interpreter with variables meant for bundled interpreter""" # At the moment I'm tweaking the environment only if current # exe is bundled for Thonny. # In remaining cases it is user's responsibility to avoid # calling Thonny with environment which may be confusing for # different Pythons called in a subprocess. this_executable = sys.executable.replace("pythonw.exe", "python.exe") target_executable = target_executable.replace("pythonw.exe", "python.exe") interpreter_specific_keys = [ "TCL_LIBRARY", "TK_LIBRARY", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH", "SSL_CERT_DIR", "SSL_CERT_FILE", "PYTHONHOME", "PYTHONPATH", "PYTHONNOUSERSITE", "PYTHONUSERBASE", ] result = {} if os.path.samefile( target_executable, this_executable ) or is_venv_interpreter_of_current_interpreter(target_executable): # bring out some important variables so that they can # be explicitly set in macOS Terminal # (If they are set then it's most likely because current exe is in Thonny bundle) for key in interpreter_specific_keys: if key in os.environ: result[key] = os.environ[key] # never pass some variables to different interpreter # (even if it's venv or symlink to current one) if not is_same_path(target_executable, this_executable): for key in ["PYTHONPATH", "PYTHONHOME", "PYTHONNOUSERSITE", "PYTHONUSERBASE"]: if key in os.environ: result[key] = None else: # interpreters are not related # interpreter specific keys most likely would confuse other interpreter for key in interpreter_specific_keys: if key in os.environ: result[key] = None # some keys should be never passed for key in [ "PYTHONSTARTUP", "PYTHONBREAKPOINT", "PYTHONDEBUG", "PYTHONNOUSERSITE", "PYTHONASYNCIODEBUG", ]: if key in os.environ: result[key] = None # venv may not find (correct) Tk without assistance (eg. in Ubuntu) if is_venv_interpreter_of_current_interpreter(target_executable): try: if "TCL_LIBRARY" not in os.environ or "TK_LIBRARY" not in os.environ: result["TCL_LIBRARY"] = get_workbench().tk.exprstring("$tcl_library") result["TK_LIBRARY"] = get_workbench().tk.exprstring("$tk_library") except Exception: logging.exception("Can't compute Tcl/Tk library location") return result def construct_cd_command(path): return construct_cmd_line(["%cd", normpath_with_actual_case(path)]) _command_id_counter = 0 def generate_command_id(): global _command_id_counter _command_id_counter += 1 return "cmd_" + str(_command_id_counter) class BlockingDialog(CommonDialogEx): def __init__(self, master, cmd, mode="indeterminate"): super().__init__(master) self.title(_("Working...")) self.response = None self._sent_interrupt = False self._mode = mode self._cmd_id = cmd["id"] description = cmd.get("description", str(cmd)) self._description_label = ttk.Label(self.main_frame, text=description) self._description_label.grid(row=0, column=0, padx=10, pady=10, sticky="new") self._progress_bar = ttk.Progressbar(self.main_frame, mode=self._mode, length=200) self._progress_bar.grid(row=1, column=0, padx=10, sticky="new") self._progress_bar.start() self._cancel_button = ttk.Button(self.main_frame, text=_("Cancel"), command=self._on_cancel) self._cancel_button.grid(row=2, column=0, padx=10, pady=10) self._start_time = time.time() if isinstance(cmd, InlineCommand): get_workbench().bind("InlineResponse", self._on_response, True) get_workbench().bind("InlineProgress", self._on_progress, True) else: raise NotImplementedError() def _on_response(self, event): self.response = event if event.get("command_id") == self._cmd_id: self.destroy() if event.get("error") and not event.get("interrupted"): messagebox.showerror("Error", event.get("error")) def _on_progress(self, event): if event.get("command_id") != self._cmd_id: return if self._mode == "indeterminate": self._progress_bar.stop() self._mode = "determinate" self._progress_bar.configure(mode=self._mode) self._progress_bar.configure(maximum=event["maximum"], value=event["value"]) def _send_interrupt(self): self._sent_interrupt = True self._description_label.configure(text="Cancelling...") self._cancel_button.configure(text=_("Close")) get_runner()._cmd_interrupt() def on_close(self, event=None): self._on_cancel() def _on_cancel(self): if self._sent_interrupt: if messagebox.askyesno( "Interrupt again?", "Do you want to close this dialog without waiting cancelling to complete?", ): self.destroy() else: self._send_interrupt() else: if messagebox.askyesno( "Cancel current operation?", "Do you really want to cancel this operation?" ): self._send_interrupt() def get_frontend_python(): # TODO: deprecated (name can be misleading) warnings.warn("get_frontend_python is deprecated") return get_interpreter_for_subprocess(sys.executable) def get_interpreter_for_subprocess(candidate=None): if candidate is None: candidate = sys.executable pythonw = candidate.replace("python.exe", "pythonw.exe") if not _console_allocated and os.path.exists(pythonw): return pythonw else: return candidate.replace("pythonw.exe", "python.exe") thonny-3.2.7/thonny/config_ui.py0000644000175000017500000001160213611773167017723 0ustar annamaaannamaa00000000000000import tkinter as tk from tkinter import ttk from thonny import get_workbench, ui_utils import traceback from thonny.ui_utils import ems_to_pixels, CommonDialog class ConfigurationDialog(CommonDialog): last_shown_tab_index = 0 def __init__(self, master, page_records): super().__init__(master) width = ems_to_pixels(53) height = ems_to_pixels(43) self.geometry("%dx%d" % (width, height)) self.title(_("Thonny options")) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) main_frame = ttk.Frame(self) # otherwise there is wrong color background with clam main_frame.grid(row=0, column=0, sticky=tk.NSEW) main_frame.columnconfigure(0, weight=1) main_frame.rowconfigure(0, weight=1) self._notebook = ttk.Notebook(main_frame) self._notebook.grid(row=0, column=0, columnspan=3, sticky=tk.NSEW, padx=10, pady=10) self._ok_button = ttk.Button(main_frame, text=_("OK"), command=self._ok, default="active") self._cancel_button = ttk.Button(main_frame, text=_("Cancel"), command=self._cancel) self._ok_button.grid(row=1, column=1, padx=(0, 11), pady=(0, 10)) self._cancel_button.grid(row=1, column=2, padx=(0, 11), pady=(0, 10)) self._page_records = [] for key, title, page_class, order in sorted(page_records, key=lambda r: (r[3], r[0])): try: spacer = ttk.Frame(self) spacer.rowconfigure(0, weight=1) spacer.columnconfigure(0, weight=1) page = page_class(spacer) page.key = key self._page_records.append((key, title, page)) page.grid(sticky=tk.NSEW, pady=(15, 10), padx=15) self._notebook.add(spacer, text=title) except Exception: traceback.print_exc() self.bind("", self._ok, True) self.bind("", self._cancel, True) self._notebook.select(self._notebook.tabs()[ConfigurationDialog.last_shown_tab_index]) def select_page(self, key): for i, tab in enumerate(self._notebook.tabs()): if self._page_records[i][0] == key: self._notebook.select(tab) def _ok(self, event=None): for key, title, page in self._page_records: try: if page.apply() == False: return except Exception: get_workbench().report_exception("Error when applying options in " + title) self.destroy() def _cancel(self, event=None): for key, title, page in self._page_records: try: page.cancel() except Exception: get_workbench().report_exception("Error when cancelling options in " + title) self.destroy() def destroy(self): ConfigurationDialog.last_shown_tab_index = self._notebook.index(self._notebook.select()) super().destroy() class ConfigurationPage(ttk.Frame): """This is an example dummy implementation of a configuration page. It's not required that configuration pages inherit from this class (can be any widget), but the class must have constructor with single parameter for getting the master.""" def __init__(self, master): ttk.Frame.__init__(self, master) def add_checkbox( self, flag_name, description, row=None, column=0, padx=0, pady=0, columnspan=1, tooltip=None ): variable = get_workbench().get_variable(flag_name) checkbox = ttk.Checkbutton(self, text=description, variable=variable) checkbox.grid( row=row, column=column, sticky=tk.W, padx=padx, pady=pady, columnspan=columnspan ) if tooltip is not None: ui_utils.create_tooltip(checkbox, tooltip) def add_combobox( self, option_name, values, row=None, column=0, padx=0, pady=0, columnspan=1, width=None ): variable = get_workbench().get_variable(option_name) combobox = ttk.Combobox( self, exportselection=False, textvariable=variable, state="readonly", height=15, width=width, values=values, ) combobox.grid( row=row, column=column, sticky=tk.W, pady=pady, padx=padx, columnspan=columnspan ) def add_entry(self, option_name, row=None, column=0, pady=0, padx=0, columnspan=1, **kw): variable = get_workbench().get_variable(option_name) entry = ttk.Entry(self, textvariable=variable, **kw) entry.grid(row=row, column=column, sticky=tk.W, pady=pady, columnspan=columnspan, padx=padx) def apply(self): """Apply method should return False, when page contains invalid input and configuration dialog should not be closed.""" pass def cancel(self): """Called when dialog gets cancelled""" pass thonny-3.2.7/licenses/0000755000175000017500000000000013611777205015672 5ustar annamaaannamaa00000000000000thonny-3.2.7/licenses/ECLIPSE-ICONS-LICENSE.txt0000644000175000017500000002612313611773167021457 0ustar annamaaannamaa00000000000000# Several Thonny icons are taken from http://eclipse-icons.i24.cc ------------------------------ Eclipse Public License - v 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. thonny-3.2.7/thonny.egg-info/0000755000175000017500000000000013611777205017076 5ustar annamaaannamaa00000000000000thonny-3.2.7/thonny.egg-info/entry_points.txt0000644000175000017500000000004613611777205022374 0ustar annamaaannamaa00000000000000[gui_scripts] thonny = thonny:launch thonny-3.2.7/thonny.egg-info/requires.txt0000644000175000017500000000021413611777205021473 0ustar annamaaannamaa00000000000000Send2Trash>=1.4.2 astroid>=1.4.9 asttokens>=1.1.10 docutils>=0.13.1 jedi>=0.10 mypy>=0.470 pylint>=1.6.5 pyserial>=3.1.1 setuptools>=33.1.1 thonny-3.2.7/thonny.egg-info/dependency_links.txt0000644000175000017500000000000113611777205023144 0ustar annamaaannamaa00000000000000 thonny-3.2.7/thonny.egg-info/top_level.txt0000644000175000017500000000000713611777205021625 0ustar annamaaannamaa00000000000000thonny thonny-3.2.7/thonny.egg-info/SOURCES.txt0000644000175000017500000005514713611777205020776 0ustar annamaaannamaa00000000000000CHANGELOG.rst CREDITS.rst LICENSE.txt MANIFEST.in README.rst requirements.txt setup.py licenses/ECLIPSE-ICONS-LICENSE.txt packaging/icons/thonny-128x128.png packaging/icons/thonny-16x16.png packaging/icons/thonny-192x192.png packaging/icons/thonny-2.png packaging/icons/thonny-22x22.png packaging/icons/thonny-256x256.png packaging/icons/thonny-32x32.png packaging/icons/thonny-48x48.png packaging/icons/thonny-64x64.png packaging/linux/org.thonny.Thonny.appdata.xml packaging/linux/org.thonny.Thonny.desktop packaging/linux/thonny.1 thonny/VERSION thonny/__init__.py thonny/__main__.py thonny/assistance.py thonny/ast_utils.py thonny/backend.py thonny/backend_launcher.py thonny/base_file_browser.py thonny/code.py thonny/codeview.py thonny/common.py thonny/config.py thonny/config_ui.py thonny/export.py thonny/first_run.py thonny/gridtable.py thonny/jedi_utils.py thonny/languages.py thonny/memory.py thonny/misc_utils.py thonny/roughparse.py thonny/rst_utils.py thonny/running.py thonny/running_config_page.py thonny/shell.py thonny/terminal.py thonny/tktextext.py thonny/token_utils.py thonny/ui_utils.py thonny/workbench.py thonny.egg-info/PKG-INFO thonny.egg-info/SOURCES.txt thonny.egg-info/dependency_links.txt thonny.egg-info/entry_points.txt thonny.egg-info/requires.txt thonny.egg-info/top_level.txt thonny/locale/compile_mo.bat thonny/locale/thonny.pot thonny/locale/update_pot.bat thonny/locale/de_DE/LC_MESSAGES/thonny.mo thonny/locale/de_DE/LC_MESSAGES/thonny.po thonny/locale/el_GR/LC_MESSAGES/thonny.mo thonny/locale/el_GR/LC_MESSAGES/thonny.po thonny/locale/en_US/LC_MESSAGES/thonny.mo thonny/locale/en_US/LC_MESSAGES/thonny.po thonny/locale/es_ES/LC_MESSAGES/thonny.mo thonny/locale/es_ES/LC_MESSAGES/thonny.po thonny/locale/et_EE/LC_MESSAGES/thonny.mo thonny/locale/et_EE/LC_MESSAGES/thonny.po thonny/locale/fr_FR/HELP_CONTENT/birdseye.rst thonny/locale/fr_FR/HELP_CONTENT/debuggers.rst thonny/locale/fr_FR/HELP_CONTENT/debugging.rst thonny/locale/fr_FR/HELP_CONTENT/dock.rst thonny/locale/fr_FR/HELP_CONTENT/errors.rst thonny/locale/fr_FR/HELP_CONTENT/flask.rst thonny/locale/fr_FR/HELP_CONTENT/index.rst thonny/locale/fr_FR/HELP_CONTENT/modes.rst thonny/locale/fr_FR/HELP_CONTENT/packages.rst thonny/locale/fr_FR/HELP_CONTENT/plotter.rst thonny/locale/fr_FR/HELP_CONTENT/program_arguments.rst thonny/locale/fr_FR/HELP_CONTENT/shell.rst thonny/locale/fr_FR/HELP_CONTENT/turtle.rst thonny/locale/fr_FR/LC_MESSAGES/thonny.mo thonny/locale/fr_FR/LC_MESSAGES/thonny.po thonny/locale/it_IT/LC_MESSAGES/thonny.mo thonny/locale/it_IT/LC_MESSAGES/thonny.po thonny/locale/ja_JP/LC_MESSAGES/thonny.mo thonny/locale/ja_JP/LC_MESSAGES/thonny.po thonny/locale/lt_LT/LC_MESSAGES/thonny.mo thonny/locale/lt_LT/LC_MESSAGES/thonny.po thonny/locale/nl_NL/LC_MESSAGES/thonny.mo thonny/locale/nl_NL/LC_MESSAGES/thonny.po thonny/locale/pl_PL/LC_MESSAGES/thonny.mo thonny/locale/pl_PL/LC_MESSAGES/thonny.po thonny/locale/pt_BR/LC_MESSAGES/thonny.mo thonny/locale/pt_BR/LC_MESSAGES/thonny.po thonny/locale/pt_PT/LC_MESSAGES/thonny.mo thonny/locale/pt_PT/LC_MESSAGES/thonny.po thonny/locale/ru_RU/LC_MESSAGES/thonny.mo thonny/locale/ru_RU/LC_MESSAGES/thonny.po thonny/locale/tr_TR/LC_MESSAGES/thonny.mo thonny/locale/tr_TR/LC_MESSAGES/thonny.po thonny/locale/uk_UA/LC_MESSAGES/thonny.mo thonny/locale/uk_UA/LC_MESSAGES/thonny.po thonny/locale/zh_CN/LC_MESSAGES/thonny.mo thonny/locale/zh_CN/LC_MESSAGES/thonny.po thonny/locale/zh_TW/LC_MESSAGES/thonny.mo thonny/locale/zh_TW/LC_MESSAGES/thonny.po thonny/plugins/__init__.py thonny/plugins/about.py thonny/plugins/assistant_config_page.py thonny/plugins/ast_view.py thonny/plugins/autocomplete.py thonny/plugins/backend_config_page.py thonny/plugins/base_syntax_themes.py thonny/plugins/base_ui_themes.py thonny/plugins/birdseye_frontend.py thonny/plugins/cells.py thonny/plugins/clean_ui_themes.py thonny/plugins/coloring.py thonny/plugins/commenting_indenting.py thonny/plugins/common_editing_commands.py thonny/plugins/debugger.py thonny/plugins/dock_user_windows_frontend.py thonny/plugins/editor_config_page.py thonny/plugins/event_logging.py thonny/plugins/event_view.py thonny/plugins/files.py thonny/plugins/find_replace.py thonny/plugins/general_config_page.py thonny/plugins/goto_definition.py thonny/plugins/heap.py thonny/plugins/highlight_names.py thonny/plugins/locals_marker.py thonny/plugins/misc_analyzers.py thonny/plugins/notes.py thonny/plugins/object_inspector.py thonny/plugins/outline.py thonny/plugins/paren_matcher.py thonny/plugins/pgzero_frontend.py thonny/plugins/pip_gui.py thonny/plugins/pylint.py thonny/plugins/remove_old_data_dir.py thonny/plugins/replayer.py thonny/plugins/run_debug_config_page.py thonny/plugins/shell_config_page.py thonny/plugins/shell_macro.py thonny/plugins/statement_boxes.py thonny/plugins/stdlib_error_helpers.py thonny/plugins/terminal_config_page.py thonny/plugins/theme_and_font_config_page.py thonny/plugins/thonny_folders.py thonny/plugins/tomorrow_syntax_theme.py thonny/plugins/variables.py thonny/plugins/backend/__init__.py thonny/plugins/backend/birdseye_backend.py thonny/plugins/backend/dock_user_windows_backend.py thonny/plugins/backend/flask_backend.py thonny/plugins/backend/matplotlib_backend.py thonny/plugins/backend/pgzero_backend.py thonny/plugins/circuitpython/__init__.py thonny/plugins/circuitpython/api_stubs/analogio.py thonny/plugins/circuitpython/api_stubs/array.py thonny/plugins/circuitpython/api_stubs/audiobusio.py thonny/plugins/circuitpython/api_stubs/audioio.py thonny/plugins/circuitpython/api_stubs/bitbangio.py thonny/plugins/circuitpython/api_stubs/board.py thonny/plugins/circuitpython/api_stubs/builtins.py thonny/plugins/circuitpython/api_stubs/busio.py thonny/plugins/circuitpython/api_stubs/collections.py thonny/plugins/circuitpython/api_stubs/digitalio.py thonny/plugins/circuitpython/api_stubs/errno.py thonny/plugins/circuitpython/api_stubs/framebuf.py thonny/plugins/circuitpython/api_stubs/gamepad.py thonny/plugins/circuitpython/api_stubs/gc.py thonny/plugins/circuitpython/api_stubs/math.py thonny/plugins/circuitpython/api_stubs/microcontroller.py thonny/plugins/circuitpython/api_stubs/micropython.py thonny/plugins/circuitpython/api_stubs/neopixel.py thonny/plugins/circuitpython/api_stubs/neopixel_write.py thonny/plugins/circuitpython/api_stubs/nvm.py thonny/plugins/circuitpython/api_stubs/os.py thonny/plugins/circuitpython/api_stubs/pulseio.py thonny/plugins/circuitpython/api_stubs/random.py thonny/plugins/circuitpython/api_stubs/re.py thonny/plugins/circuitpython/api_stubs/rotaryio.py thonny/plugins/circuitpython/api_stubs/rtc.py thonny/plugins/circuitpython/api_stubs/samd.py thonny/plugins/circuitpython/api_stubs/storage.py thonny/plugins/circuitpython/api_stubs/struct.py thonny/plugins/circuitpython/api_stubs/supervisor.py thonny/plugins/circuitpython/api_stubs/sys.py thonny/plugins/circuitpython/api_stubs/time.py thonny/plugins/circuitpython/api_stubs/touchio.py thonny/plugins/circuitpython/api_stubs/ucollections.py thonny/plugins/circuitpython/api_stubs/ure.py thonny/plugins/circuitpython/api_stubs/usb_hid.py thonny/plugins/circuitpython/api_stubs/usb_midi.py thonny/plugins/circuitpython/api_stubs/ustruct.py thonny/plugins/esp/__init__.py thonny/plugins/esp/esp32_api_stubs/_boot.py thonny/plugins/esp/esp32_api_stubs/_onewire.py thonny/plugins/esp/esp32_api_stubs/_thread.py thonny/plugins/esp/esp32_api_stubs/_webrepl.py thonny/plugins/esp/esp32_api_stubs/apa106.py thonny/plugins/esp/esp32_api_stubs/array.py thonny/plugins/esp/esp32_api_stubs/binascii.py thonny/plugins/esp/esp32_api_stubs/btree.py thonny/plugins/esp/esp32_api_stubs/builtins.py thonny/plugins/esp/esp32_api_stubs/cmath.py thonny/plugins/esp/esp32_api_stubs/collections.py thonny/plugins/esp/esp32_api_stubs/dht.py thonny/plugins/esp/esp32_api_stubs/ds18x20.py thonny/plugins/esp/esp32_api_stubs/errno.py thonny/plugins/esp/esp32_api_stubs/esp.py thonny/plugins/esp/esp32_api_stubs/esp32.py thonny/plugins/esp/esp32_api_stubs/flashbdev.py thonny/plugins/esp/esp32_api_stubs/framebuf.py thonny/plugins/esp/esp32_api_stubs/gc.py thonny/plugins/esp/esp32_api_stubs/hashlib.py thonny/plugins/esp/esp32_api_stubs/heapq.py thonny/plugins/esp/esp32_api_stubs/inisetup.py thonny/plugins/esp/esp32_api_stubs/io.py thonny/plugins/esp/esp32_api_stubs/json.py thonny/plugins/esp/esp32_api_stubs/machine.py thonny/plugins/esp/esp32_api_stubs/math.py thonny/plugins/esp/esp32_api_stubs/micropython.py thonny/plugins/esp/esp32_api_stubs/neopixel.py thonny/plugins/esp/esp32_api_stubs/network.py thonny/plugins/esp/esp32_api_stubs/ntptime.py thonny/plugins/esp/esp32_api_stubs/onewire.py thonny/plugins/esp/esp32_api_stubs/os.py thonny/plugins/esp/esp32_api_stubs/random.py thonny/plugins/esp/esp32_api_stubs/re.py thonny/plugins/esp/esp32_api_stubs/select.py thonny/plugins/esp/esp32_api_stubs/socket.py thonny/plugins/esp/esp32_api_stubs/ssl.py thonny/plugins/esp/esp32_api_stubs/struct.py thonny/plugins/esp/esp32_api_stubs/sys.py thonny/plugins/esp/esp32_api_stubs/time.py thonny/plugins/esp/esp32_api_stubs/ubinascii.py thonny/plugins/esp/esp32_api_stubs/ucollections.py thonny/plugins/esp/esp32_api_stubs/uctypes.py thonny/plugins/esp/esp32_api_stubs/uerrno.py thonny/plugins/esp/esp32_api_stubs/uhashlib.py thonny/plugins/esp/esp32_api_stubs/uheapq.py thonny/plugins/esp/esp32_api_stubs/uio.py thonny/plugins/esp/esp32_api_stubs/ujson.py thonny/plugins/esp/esp32_api_stubs/uos.py thonny/plugins/esp/esp32_api_stubs/upip.py thonny/plugins/esp/esp32_api_stubs/upip_utarfile.py thonny/plugins/esp/esp32_api_stubs/upysh.py thonny/plugins/esp/esp32_api_stubs/urandom.py thonny/plugins/esp/esp32_api_stubs/ure.py thonny/plugins/esp/esp32_api_stubs/urequests.py thonny/plugins/esp/esp32_api_stubs/uselect.py thonny/plugins/esp/esp32_api_stubs/usocket.py thonny/plugins/esp/esp32_api_stubs/ussl.py thonny/plugins/esp/esp32_api_stubs/ustruct.py thonny/plugins/esp/esp32_api_stubs/utime.py thonny/plugins/esp/esp32_api_stubs/utimeq.py thonny/plugins/esp/esp32_api_stubs/uzlib.py thonny/plugins/esp/esp32_api_stubs/webrepl.py thonny/plugins/esp/esp32_api_stubs/webrepl_setup.py thonny/plugins/esp/esp32_api_stubs/websocket.py thonny/plugins/esp/esp32_api_stubs/websocket_helper.py thonny/plugins/esp/esp32_api_stubs/zlib.py thonny/plugins/help/__init__.py thonny/plugins/help/birdseye.rst thonny/plugins/help/debuggers.rst thonny/plugins/help/debugging.rst thonny/plugins/help/dock.rst thonny/plugins/help/errors.rst thonny/plugins/help/flask.rst thonny/plugins/help/index.rst thonny/plugins/help/modes.rst thonny/plugins/help/packages.rst thonny/plugins/help/plotter.rst thonny/plugins/help/program_arguments.rst thonny/plugins/help/shell.rst thonny/plugins/help/turtle.rst thonny/plugins/microbit/__init__.py thonny/plugins/microbit/api_stubs/antigravity.py thonny/plugins/microbit/api_stubs/array.py thonny/plugins/microbit/api_stubs/audio.py thonny/plugins/microbit/api_stubs/builtins.py thonny/plugins/microbit/api_stubs/collections.py thonny/plugins/microbit/api_stubs/gc.py thonny/plugins/microbit/api_stubs/love.py thonny/plugins/microbit/api_stubs/machine.py thonny/plugins/microbit/api_stubs/math.py thonny/plugins/microbit/api_stubs/microbit.py thonny/plugins/microbit/api_stubs/micropython.py thonny/plugins/microbit/api_stubs/music.py thonny/plugins/microbit/api_stubs/neopixel.py thonny/plugins/microbit/api_stubs/os.py thonny/plugins/microbit/api_stubs/radio.py thonny/plugins/microbit/api_stubs/random.py thonny/plugins/microbit/api_stubs/speech.py thonny/plugins/microbit/api_stubs/struct.py thonny/plugins/microbit/api_stubs/sys.py thonny/plugins/microbit/api_stubs/this.py thonny/plugins/microbit/api_stubs/time.py thonny/plugins/microbit/api_stubs/ucollections.py thonny/plugins/microbit/api_stubs/ustruct.py thonny/plugins/microbit/api_stubs/utime.py thonny/plugins/micropython/__init__.py thonny/plugins/micropython/backend.py thonny/plugins/micropython/connection.py thonny/plugins/micropython/serial_connection.py thonny/plugins/micropython/webrepl_connection.py thonny/plugins/micropython/api_stubs/_onewire.py thonny/plugins/micropython/api_stubs/array.py thonny/plugins/micropython/api_stubs/binascii.py thonny/plugins/micropython/api_stubs/builtins.py thonny/plugins/micropython/api_stubs/cmath.py thonny/plugins/micropython/api_stubs/collections.py thonny/plugins/micropython/api_stubs/dht.py thonny/plugins/micropython/api_stubs/errno.py thonny/plugins/micropython/api_stubs/framebuf.py thonny/plugins/micropython/api_stubs/gc.py thonny/plugins/micropython/api_stubs/hashlib.py thonny/plugins/micropython/api_stubs/heapq.py thonny/plugins/micropython/api_stubs/io.py thonny/plugins/micropython/api_stubs/json.py thonny/plugins/micropython/api_stubs/lcd160cr.py thonny/plugins/micropython/api_stubs/machine.py thonny/plugins/micropython/api_stubs/math.py thonny/plugins/micropython/api_stubs/micropython.py thonny/plugins/micropython/api_stubs/network.py thonny/plugins/micropython/api_stubs/onewire.py thonny/plugins/micropython/api_stubs/os.py thonny/plugins/micropython/api_stubs/pyb.py thonny/plugins/micropython/api_stubs/random.py thonny/plugins/micropython/api_stubs/re.py thonny/plugins/micropython/api_stubs/select.py thonny/plugins/micropython/api_stubs/socket.py thonny/plugins/micropython/api_stubs/stm.py thonny/plugins/micropython/api_stubs/struct.py thonny/plugins/micropython/api_stubs/sys.py thonny/plugins/micropython/api_stubs/time.py thonny/plugins/micropython/api_stubs/ubinascii.py thonny/plugins/micropython/api_stubs/ucollections.py thonny/plugins/micropython/api_stubs/uctypes.py thonny/plugins/micropython/api_stubs/uerrno.py thonny/plugins/micropython/api_stubs/uhashlib.py thonny/plugins/micropython/api_stubs/uheapq.py thonny/plugins/micropython/api_stubs/uio.py thonny/plugins/micropython/api_stubs/ujson.py thonny/plugins/micropython/api_stubs/umachine.py thonny/plugins/micropython/api_stubs/uos.py thonny/plugins/micropython/api_stubs/urandom.py thonny/plugins/micropython/api_stubs/ure.py thonny/plugins/micropython/api_stubs/uselect.py thonny/plugins/micropython/api_stubs/usocket.py thonny/plugins/micropython/api_stubs/ustruct.py thonny/plugins/micropython/api_stubs/utime.py thonny/plugins/micropython/api_stubs/utimeq.py thonny/plugins/micropython/api_stubs/uzlib.py thonny/plugins/micropython/api_stubs/zlib.py thonny/plugins/mypy/__init__.py thonny/plugins/mypy/typeshed_extras/turtle.pyi thonny/plugins/pi/__init__.py thonny/plugins/pi/res/_disabled_debug-run-cursor.png thonny/plugins/pi/res/_disabled_debug-run-cursor48.png thonny/plugins/pi/res/_disabled_debug-run.png thonny/plugins/pi/res/_disabled_debug-run48.png thonny/plugins/pi/res/_disabled_debug-step-into.png thonny/plugins/pi/res/_disabled_debug-step-into48.png thonny/plugins/pi/res/_disabled_debug-step-out.png thonny/plugins/pi/res/_disabled_debug-step-out48.png thonny/plugins/pi/res/_disabled_debug-step-over.png thonny/plugins/pi/res/_disabled_debug-step-over48.png thonny/plugins/pi/res/_disabled_document-new.png thonny/plugins/pi/res/_disabled_document-new48.png thonny/plugins/pi/res/_disabled_document-open.png thonny/plugins/pi/res/_disabled_document-open48.png thonny/plugins/pi/res/_disabled_document-save.png thonny/plugins/pi/res/_disabled_document-save48.png thonny/plugins/pi/res/_disabled_media-playback-start.png thonny/plugins/pi/res/_disabled_media-playback-start48.png thonny/plugins/pi/res/_disabled_process-stop.png thonny/plugins/pi/res/_disabled_process-stop48.png thonny/plugins/pi/res/_disabled_quit.png thonny/plugins/pi/res/_disabled_quit48.png thonny/plugins/pi/res/_disabled_resume.png thonny/plugins/pi/res/_disabled_resume48.png thonny/plugins/pi/res/_disabled_scrollbar-button-down-insens.png thonny/plugins/pi/res/_disabled_scrollbar-button-down.png thonny/plugins/pi/res/_disabled_scrollbar-button-left-insens.png thonny/plugins/pi/res/_disabled_scrollbar-button-left.png thonny/plugins/pi/res/_disabled_scrollbar-button-right-insens.png thonny/plugins/pi/res/_disabled_scrollbar-button-right.png thonny/plugins/pi/res/_disabled_scrollbar-button-up-insens.png thonny/plugins/pi/res/_disabled_scrollbar-button-up.png thonny/plugins/pi/res/_disabled_window-close-act.png thonny/plugins/pi/res/_disabled_window-close.png thonny/plugins/pi/res/_disabled_zoom.png thonny/plugins/pi/res/_disabled_zoom48.png thonny/plugins/pi/res/debug-run-cursor.png thonny/plugins/pi/res/debug-run-cursor48.png thonny/plugins/pi/res/debug-run.png thonny/plugins/pi/res/debug-run48.png thonny/plugins/pi/res/debug-step-into.png thonny/plugins/pi/res/debug-step-into48.png thonny/plugins/pi/res/debug-step-out.png thonny/plugins/pi/res/debug-step-out48.png thonny/plugins/pi/res/debug-step-over.png thonny/plugins/pi/res/debug-step-over48.png thonny/plugins/pi/res/document-new.png thonny/plugins/pi/res/document-new48.png thonny/plugins/pi/res/document-open.png thonny/plugins/pi/res/document-open48.png thonny/plugins/pi/res/document-save.png thonny/plugins/pi/res/document-save48.png thonny/plugins/pi/res/media-playback-start.png thonny/plugins/pi/res/media-playback-start48.png thonny/plugins/pi/res/process-stop.png thonny/plugins/pi/res/process-stop48.png thonny/plugins/pi/res/quit.png thonny/plugins/pi/res/quit48.png thonny/plugins/pi/res/resume.png thonny/plugins/pi/res/resume48.png thonny/plugins/pi/res/scrollbar-button-down-insens.png thonny/plugins/pi/res/scrollbar-button-down.png thonny/plugins/pi/res/scrollbar-button-left-insens.png thonny/plugins/pi/res/scrollbar-button-left.png thonny/plugins/pi/res/scrollbar-button-right-insens.png thonny/plugins/pi/res/scrollbar-button-right.png thonny/plugins/pi/res/scrollbar-button-up-insens.png thonny/plugins/pi/res/scrollbar-button-up.png thonny/plugins/pi/res/window-close-act.png thonny/plugins/pi/res/window-close.png thonny/plugins/pi/res/zoom.png thonny/plugins/pi/res/zoom48.png thonny/plugins/printing/__init__.py thonny/plugins/printing/template.html thonny/plugins/system_shell/__init__.py thonny/plugins/system_shell/explain_environment.py thonny/res/16x16-blank.gif thonny/res/1x1-white.gif thonny/res/PrintLnkTarget.vbs thonny/res/_create_disabled_variants.py thonny/res/_disabled_16x16-blank.gif thonny/res/_disabled_1x1-white.gif thonny/res/_disabled_arrow-down.gif thonny/res/_disabled_birdseye.png thonny/res/_disabled_boxdot.png thonny/res/_disabled_boxdot_light.png thonny/res/_disabled_boxminus.png thonny/res/_disabled_boxminus_light.png thonny/res/_disabled_boxplus.png thonny/res/_disabled_boxplus_light.png thonny/res/_disabled_boxx.png thonny/res/_disabled_boxx_light.png thonny/res/_disabled_closed-folder.gif thonny/res/_disabled_debug-current-script.png thonny/res/_disabled_debug-current-script_2x.png thonny/res/_disabled_delete.gif thonny/res/_disabled_folder.gif thonny/res/_disabled_generic-file.gif thonny/res/_disabled_hard-drive.gif thonny/res/_disabled_harddisk.png thonny/res/_disabled_harddisk_2x.png thonny/res/_disabled_help.png thonny/res/_disabled_help_2x.png thonny/res/_disabled_information.png thonny/res/_disabled_information_2x.png thonny/res/_disabled_nav-backward.png thonny/res/_disabled_nav-backward_2x.png thonny/res/_disabled_nav-forward.png thonny/res/_disabled_nav-forward_2x.png thonny/res/_disabled_new-file.png thonny/res/_disabled_new-file_Linux.png thonny/res/_disabled_new-file_Linux_2x.png thonny/res/_disabled_open-file.png thonny/res/_disabled_open-file_Linux.png thonny/res/_disabled_open-file_Linux_2x.png thonny/res/_disabled_open_folder.gif thonny/res/_disabled_outline-class.png thonny/res/_disabled_outline-class_2x.png thonny/res/_disabled_outline-method.gif thonny/res/_disabled_python-file.gif thonny/res/_disabled_python-icon.gif thonny/res/_disabled_quit.png thonny/res/_disabled_quit_2x.png thonny/res/_disabled_resume.png thonny/res/_disabled_resume_2x.png thonny/res/_disabled_run-current-script.png thonny/res/_disabled_run-current-script_2x.png thonny/res/_disabled_run-to-cursor.png thonny/res/_disabled_run-to-cursor_2x.png thonny/res/_disabled_save-file.png thonny/res/_disabled_save-file_2x_alt.png thonny/res/_disabled_save-file_Linux.png thonny/res/_disabled_save-file_Linux_2x.png thonny/res/_disabled_save-file_alt.png thonny/res/_disabled_star.png thonny/res/_disabled_star_2x.png thonny/res/_disabled_step-into.png thonny/res/_disabled_step-into_2x.png thonny/res/_disabled_step-out.png thonny/res/_disabled_step-out_2x.png thonny/res/_disabled_step-over.png thonny/res/_disabled_step-over_2x.png thonny/res/_disabled_stop.png thonny/res/_disabled_stop_2x_alt.png thonny/res/_disabled_stop_alt.png thonny/res/_disabled_tab-close-active-clam-dark.gif thonny/res/_disabled_tab-close-active-clam.gif thonny/res/_disabled_tab-close-active.gif thonny/res/_disabled_tab-close-clam.gif thonny/res/_disabled_tab-close.gif thonny/res/_disabled_terminal.png thonny/res/_disabled_terminal_2x.png thonny/res/_disabled_text-file.gif thonny/res/_disabled_thonny.png thonny/res/_disabled_zoom.png thonny/res/arrow-down.gif thonny/res/birdseye.png thonny/res/boxdot.png thonny/res/boxdot_light.png thonny/res/boxminus.png thonny/res/boxminus_light.png thonny/res/boxplus.png thonny/res/boxplus_light.png thonny/res/boxx.png thonny/res/boxx_light.png thonny/res/closed-folder.gif thonny/res/debug-current-script.png thonny/res/debug-current-script_2x.png thonny/res/delete.gif thonny/res/folder.gif thonny/res/generic-file.gif thonny/res/hard-drive.gif thonny/res/harddisk.png thonny/res/harddisk_2x.png thonny/res/help.png thonny/res/help_2x.png thonny/res/information.png thonny/res/information_2x.png thonny/res/nav-backward.png thonny/res/nav-backward_2x.png thonny/res/nav-forward.png thonny/res/nav-forward_2x.png thonny/res/new-file.png thonny/res/new-file_Linux.png thonny/res/new-file_Linux_2x.png thonny/res/open-file.png thonny/res/open-file_Linux.png thonny/res/open-file_Linux_2x.png thonny/res/open_folder.gif thonny/res/outline-class.png thonny/res/outline-class_2x.png thonny/res/outline-method.gif thonny/res/python-file.gif thonny/res/python-icon.gif thonny/res/quit.png thonny/res/quit_2x.png thonny/res/resume.png thonny/res/resume_2x.png thonny/res/run-current-script.png thonny/res/run-current-script_2x.png thonny/res/run-to-cursor.png thonny/res/run-to-cursor_2x.png thonny/res/save-file.png thonny/res/save-file_2x_alt.png thonny/res/save-file_Linux.png thonny/res/save-file_Linux_2x.png thonny/res/save-file_alt.png thonny/res/star.png thonny/res/star_2x.png thonny/res/step-into.png thonny/res/step-into_2x.png thonny/res/step-out.png thonny/res/step-out_2x.png thonny/res/step-over.png thonny/res/step-over_2x.png thonny/res/stop.png thonny/res/stop_2x_alt.png thonny/res/stop_alt.png thonny/res/tab-close-active-clam-dark.gif thonny/res/tab-close-active-clam.gif thonny/res/tab-close-active.gif thonny/res/tab-close-clam.gif thonny/res/tab-close.gif thonny/res/terminal.png thonny/res/terminal_2x.png thonny/res/text-file.gif thonny/res/thonny.ico thonny/res/thonny.png thonny/res/thonny_small.ico thonny/res/zoom.png thonny/test/__init__.py thonny/test/test_common.py thonny/test/plugins/__init__.py thonny/test/plugins/test_locals_marker.py thonny/test/plugins/test_name_highlighter.pythonny-3.2.7/thonny.egg-info/PKG-INFO0000644000175000017500000000314213611777205020173 0ustar annamaaannamaa00000000000000Metadata-Version: 1.2 Name: thonny Version: 3.2.7 Summary: Python IDE for beginners Home-page: https://thonny.org Author: Aivar Annamaa and others Author-email: thonny@googlegroups.com License: MIT Project-URL: Source code, https://github.com/thonny/thonny Project-URL: Bug tracker, https://github.com/thonny/thonny/issues Description: Thonny is a simple Python IDE with features useful for learning programming. See https://thonny.org for more info. Keywords: IDE education debugger Platform: Windows Platform: macOS Platform: Linux Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: MacOS X Classifier: Environment :: Win32 (MS Windows) Classifier: Environment :: X11 Applications Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Education Classifier: Intended Audience :: End Users/Desktop Classifier: License :: Freeware Classifier: License :: OSI Approved :: MIT License Classifier: Natural Language :: English Classifier: Operating System :: MacOS Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Education Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Debuggers Classifier: Topic :: Text Editors Requires-Python: >=3.5 thonny-3.2.7/CHANGELOG.rst0000644000175000017500000012625113611776740016120 0ustar annamaaannamaa00000000000000=============== Version history =============== 3.2.7 (2020-01-22) ================== * TECHNICAL: Skip name hilighter tests for recent Jedi versions 3.2.6 (2020-01-01) ================== * FIXED #1035: Make highlight names work with recent Jedi versions * FIXED #1043: Can't load files from MicroPython device (regression introduced in 3.2.5) * FIXED: Missing "Local files" label on save target selection dialog 3.2.5 (2019-12-25) ================== * CHANGED: Python version in binary bundles upgraded from 3.7.5 to 3.7.6 * CHANGED: MyPy checks are now enabled by default (Tools => Options => Assistant) * CHANGED: New Pylint checks are enabled * UPDATED #32: Thonny can now display/copy/paste Unicode emojis with Python 3.7.6+ / 3.8.1+ in Windows and Linux. Selection can be still wonky, though and emojis can freeze Thonny on macOS. Fixed by https://github.com/python/cpython/pull/16545 * FIXED #815: "Open System Shell" fails when no script is open * FIXED #973: Scrollbar in Help and Assistant acts funny * FIXED #1019: Crash on startup when Shell gets text inserted too soon * FIXED #1023: Accept code completions without parent and full_name * FIXED #1025: Extra imports by Thonny's back-end make stdlib name shadowing more troublesome * FIXED #1026: Allow '+' in image data URI chars in Shell * FIXED #1028: Thonny now has preliminary support for `Friendly Traceback `_. * FIXED: Allow larger images in shell (don't squeeze image URI-s), #401 * FIXED: Fallback to English, when configured language can't be loaded * FIXED: Problem using esptool on PATH 3.2.4 (2019-12-07) ================== * NEW: Turkish translation by M. Burak Kalkan * NEW: Polish translation by Jarek Miszczak * NEW: Partial Italian translation by sailslack * UPDATED: Greek and Spanish translations * CHANGED: XXL bundle now includes also pandas * CHANGED: Make faster tracer show exceptions only with step_over and step_into * CHANGE #1018: Use traditional stack view by default in Simple mode * ENHANCEMENT: Improved performance for Faster debugger (proposed and supported by Raspberry Pi) * FIXED #975: Fix stepping through lambdas with faster debugger * FIXED #977: Don't report certain exceptions in faster debugger * FIXED #983: Propose replacing tabs with spaces only in the editor (not in debugger frames) * FIXED #986: Nicer debugger fails when run with breakpoints only in secondary files * FIXED #987: MicroPython autocomplete problems by adzierzanowski * FIXED #1003: Wrong interpretation of MicroPython file timestamps * FIXED #1005: Avoid testing included MicroPython stubs * FIXED #1015: Indicate disabled toolbar buttons on macOS 3.2.3 (2019-11-03) ================== * NEW: Greek translation by Nikos * UPDATE: Updated several translations (by Vytenis, rnLIKEm, Dleta, Alex ANDRÉ, NathanBnm, LionelVaux, Paul, Eric W, Frank Stengel, ...) * UPDATE: Propose opening files via dialog in case of macOS Catalina permission error (#813). 3.2.2 (2019-11-01) ================== * NEW: ESP plug-in has been merged into main Thonny package * FIXED #219: Implement sending EOF / restart for CPython * FIXED #873: More robust color preference loading in Pi theme * FIXED #876: Don't step into comprehension calls * FIXED #897: Redo shortcut not working in Linux and Mac * FIXED #899: Can't set THONNY_USER_DIR in customize.py * FIXED #904: Don't show remote MicroPython dialogs when device is busy * FIXED #905: Problems with Thonny menu on Mac after closing a dialog * FIXED #911: Allow restoring default scaling factor * FIXED #921: Make MicroPython backend play nicer with device resets * FIXED #923: CircuitPython on Trinket m0 gives small int overflow when listing files * FIXED #925: Save or open problem with network paths * FIXED #927: Visual glitch / ghosting in Expression Box in macOS * FIXED #928: Tooltips stay on top in macOS * FIXED #929: Indicate dirty state in macOS close button * FIXED #933: Scaling doesn't work right for Treeviews (Files, Variables) * FIXED #934: Pad button captions for certain languages * FIXED #936: Problem uploading files to some STM boards * FIXED #939: More robust handling of different line endings * FIXED #943: Wrong syntax highlighting with triple quoted string * FIXED #946: Handle broken UTF-8 codepoints in MicroPython output * FIXED #951: Use standard tabstops for program output * FIXED #953: Allow running system commands with MP back-end * FIXED #957: Wrong encoding in multiprocessing output * FIXED #960: File browser is not working in replayer * FIXED #966: Thonny encounters "internal error" in programs calling exit() * FIXED #969: Provide nicer message, when MicroPython backend can't get to the REPL * FIXED: Don't apply theming to menu in macOS (menu items were dull with dark themes) 3.2.1 (2019-09-06) ================== * NEW: Add European Portuguese translation (by Emanuel Angelo) * NEW: Add Lithuanian translation (by Vytenis) * NEW: Add Ukrainian translation (by borpol) * FIXED #802: Avoid scary traceback on MicroPython disconnect * FIXED #840: Problems with file dialogs in macOS 10.15 * FIXED #843: Make right-click select items in Files view in macOS * FIXED #845: Crash with older ESP plug-in * FIXED #851: Ignore warnings when exporting variables * FIXED #854: Make single instance mode work in multi-user systems * FIXED #855: Wrong coloring with paren matching * FIXED #859: Support relative paths when opening files with Thonny from command line * FIXED #874: Multiline strings break stepping focus background * FIXED: Dutch translation was inproperly set up * FIXED: Internal error in Object Inspector (by Emanuel Angelo) * FIXED: Problem with compacting user event logs * TECHNICAL: Make tests run with Python 3.8 3.2.0 (2019-08-12) ================== * FIXED #849: Uploading single file to MicroPython doesn't work * UPDATE: Updated translations 3.2.0rc1 (2019-08-09) ===================== * NEW: Several new commands for Files view (New directory, Move to Trash, Delete, Upload (to MicroPython device), Download (from MicroPython device), ...) * CHANGED: MicroPython files are now displayed in the upper pane of Files view * CHANGED: Saving or loading editor content to/from MicroPython device displays progress bar * TECHNICAL: New dependency: Send2Trash 3.2.0b7 (2019-07-19) ==================== * FIXED: Problem with translation markers disturbing import 3.2.0b6 (2019-07-19) ==================== * NEW: BBC micro:bit plug-in has been merged into main Thonny package * CHANGED: micro:bit flasher now downloads latest MicroPython from GitHub * FIXED: Problems with micro:bit file browser * FIXED #808: multiprocessing doesn't work in Windows * FIXED #814: Ctrl+V inserts text twice in Windows (regression introduced in previous betas) 3.2.0b5 (2019-07-16) ==================== * FIXED #810: Use regular spacing in simple mode toolbar 3.2.0b4 (2019-07-14) ==================== * FIXED #809: Advertise indent/dedent in Edit menu * FIXED: Marked more terms for translation * FIXED: Updated Estonian translation 3.2.0b3 (2019-07-13) ==================== * FIXED #803: %cd gives error on MP/CP backend * FIXED #804: Changing directories does not show in FilesView for MP/CP * FIXED #805: Thonny user dir was not created at startup 3.2.0b2 (2019-07-13) ==================== * NEW: Former thonny-pi plug-in (containing Raspberry Pi theme) is now part of main Thonny package * NEW: Former thonny-circuitpython plug-in (containing CircuitPython back-end) is now part of main Thonny package * NEW: pip GUI now allows installing from requirements.txt file * NEW: Portable/thumbdrive bundles for Windows, macOS and Linux (https://github.com/thonny/thonny/wiki/DeploymentOptions#portable-version) * FIXED #188: Tkinter windows won't close on macOS * FIXED #361: Include Python development files in binary bundles * FIXED #488: Modal dialogs may get stuck * FIXED #639: Unset misleading environment variables in Windows launcher * FIXED #676: Can't close matplotlib window when MacOSX backend is used * FIXED #706: In Linux Thonny hangs on close sometimes * FIXED #800: Can't load large files * FIXED: Plotter now listens for theme changes (ie. changes background without restart) * CHANGED: Welcome dialog is not show on Raspberry Pi * CHANGED: Usage event logging is now disabled by default and can be enabled in Tools => Options => General * CHANGED: MicroPython back-ends don't interrupt running process on connecting * TECHNICAL: MicroPython back-end got a big refactoring 3.2.0b1 (2019-06-17) ==================== * NEW: [Work in progress] UI and help content can be translated to other languages (big thanks to cspaier, Georges Khaznadar and translators). See docs/translate.md for contrubution instructions. * NEW: Shell supports ANSI color codes and line overwriting with ``\b`` and ``\r``. See "Help => Shell" for more info. * NEW: Shell now has extension called "Plotter", which visualizes series of numbers printed to the standard output. See "Help => Plotter" for more info. * NEW: Shell presents PNG data URL-s printed to stdout as images. Try print("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==") * NEW: Automatic change of working directory is now optional (Tools => Options => Run & Debug) * NEW: Files view now allows setting working directory (double-click on folder name) * NEW: Files view allows browsing device's filesystem with MicroPython back-ends * NEW: Files from MicroPython devices can be opened in the editor and edited directly * NEW: You can now choose which debugger is invoked when clicking on the "Debug" toolbar button (Tools => Options => Run & Debug) * NEW: On first run Thonny presents a dialog for selecting UI language and initial settings ("standard" or "Raspberry Pi"). With Raspberry Pi settings Thonny will start in simple mode, preferred debugger set to "faster" and UI theme set to "Raspberry Pi". * NEW: Shell IO font can be configured (Tools => Options => Fonts & Themes). By André Roberge * NEW: Support for running Flask programs with F5. Also fixed several issues which prevented running and debugging Flask programs. See "Help => Web development with Flask" for more info. * NEW: "File => Save copy" allows saving current editor content to a different location without changing editor file name. * FIXED #630: Pressing up then down in shell doesn't leave shell in previous state. Fixed by Chad Purdy * FIXED #691: No Show shell on run with no input() prompt. Fixed by Chad Purdy * FIXED #692: Cancelling Save As dialog causes error. Fixed by Chad Purdy * FIXED #700: Allow viewing all files in file dialogs in Linux * FIXED #703: Exception view was not legible with dark theme * FIXED #704: Suggest current filename with Save As. Fixed by Илья Кругликов * FIXED #708: Error when stacktrace includes Cython frames. * FIXED #711: Thonny can now handle UNC paths * FIXED #719: Buttons are too narrow in Search/Replace dialog * FIXED #725: When saving a file, respect the original fileformat. By badukaire * FIXED #727: Respect fileformat for unix files too. By badukaire * FIXED #731: Right click menu disappears immediately and executes unwanted Undo action * FIXED #738: Window appears lower on each start * FIXED #749: "Focus shell" should bring you to a new prompt. By Ivoz * CHANGED: In order to work around ``tkinter.Text`` performance problems, Shell squeezes very long lines into a button. The button opens a dialog for expanding, viewing or copying those lines. Shell also deletes old output to remain responsive. * CHANGED: Various changes in simple mode (Zoom and Quit buttons, merging Run and Resume buttons, automatic display of Variables view). * CHANGED: Disabled Tk clipboard management workaround in Linux (occasionally caused UI freezes). This means clipboard becomes emptied after closing Thonny. * CHANGED: MicroPython commands from "Device" menu have been redesigned (use Files view instead) or moved to other menus (Run and Tools). The goal is to get rid of Device menu and keep only magic commands which make sense from the back-end perspective. Several of these features were proposed and supported by Raspberry Pi Foundation. 3.1.2 (2019-02-13) ================== * FIXED: Make Terminal features work in Windows again * FIXED #685: Print cuts lines * FIXED #686: Stepping over user modules can be too slow * ENHANCEMENT: Include pip in binary bundles 3.1.1 (2019-02-09) ================== * FIXED #674: Print doesn't work on Mac * FIXED #675: Make focus editor / shell shortcuts usable on Mac * FIXED #677: Debugging fails with extended slice syntax 3.1.0 (2019-01-28) ================== * NEW: "Run => Pygame Zero mode" allows running Pygame Zero programs with F5 * NEW: Support for Birdseye debugger (Run => Debug current script (Birdseye)) by Alex Hall * NEW: Notes view for writing down code snippets, task descriptions, etc. * NEW: Allow running current script in system terminal * NEW: "File => Print..." allows printing current script (via default web browser) * NEW: Shell's context menu now has editing commands * ENHANCEMENT: Open the Shell window on Run if it is not open * ENHANCEMENT: More robust support for running system commands in Thonny Shell (with ! prefix) * ENHANCEMENT: Allow switching off Pylint and/or MyPy checks * ENHANCEMENT: Make it clear how to exit Heap mode (with notification box in the upper-right corner of the main window) * FIXED #621: Holding Enter in the Shell causes a crash * FIXED #623: Parameters code completion error * FIXED #627: Debugging stops after raise statement * FIXED #628: Wrong line highlighted when stepping in for-loop * FIXED #629: Interrupting system command (!) shows ugly traceback * FIXED #633: pasting can't affect read-only text anymore * FIXED #641: Better font scaling in Linux (see Tools => Options => General for more control) * FIXED #646: Simple open file to edit from command line failing * FIXED #655: Invalid f-string crashes Assistant * FIXED #666: Make stdin iterable * FIXED: Solved several problems related to stepping through raising an exception * FIXED: Issues with automatic indentation (Thanks to Alex Hall!) * CHANGED: Use Konsole as terminal in KDE * CHANGED: "Tools => Open system shell" now shows relevant commands differently * CHANGED: Make Assistant's MyPy checks disabled by default * CHANGED: Source code now lives at GitHub (https://github.com/thonny/thonny) 3.0.8 (2018-11-15) ================== * FIXED #424: Font scaling problems in Linux * FIXED #584: Guard against bad repr calls * TECHNICAL: Reduced required pyserial version (Fedora only has 3.1) 3.0.8 (2018-11-15) ================== * FIXED #597: The directory with Python scripts may not be in path for executing system commands from shell * FIXED: Make executing shell commands compatible with Python 3.5 * FIXED: Make MyPy support compatible with older MyPy versions * FIXED: Make turtle.pyi compatible with Python 3.5 and remove Windows linebreaks * FIXED: MyPy error col offset 3.0.7 (2018-11-14) ================== * FIXED #592: MyPy doesn't work when cwd == sys.prefix * FIXED #593: No-message exceptions crash the Assistant * FIXED #595: Running system commands causes an error * FIXED #596: Arguments are ignored when running system commands from shell in Posix 3.0.6 (2018-11-13) ================== * FIXED #538: Turtle programs may give false warnings (Typeshed stubs were not packaged) * FIXED #586: Import interception mechanism fails for some modules * FIXED #591: Assistant fails when filename is missing from error info 3.0.5 (2018-10-26) ================== * FIXED #573: "Highlight matching names" and "Highlight local variables" makes editor very slow * FIXED #574: Error in outline * FIXED #578: resizing local variable pane in debugger causes error 3.0.4 (2018-10-22) ================== * FIXED #564: In Windows "Highlight local variables" and "Higlight matching names" cause Thonny to load Jedi files 3.0.3 (2018-10-21) ================== * FIXED: Regression from 3.0.2 (incomplete code refactoring) 3.0.2 (2018-10-21) ================== * FIXED #563: Problems with HeapView and EventsView * FIXED #565: Don't replace tabs in shell 3.0.1 (2018-10-17) ================== * FIXED: Problems with executing "Run" and "Debug" commands together with "cd" command * FIXED: Editor file name issues * FIXED: MicroPython %cat command failed over serial 3.0.0 (2018-10-16) ================== * CHANGED: Line numbers are now visible by default * CHANGED: Stack and Assistant views are now in the bottom-right corner * CHANGED: Shell doesn't show full path of bundled interpreters anymore * ENHANCEMENT #555: Internal errors are now shown with more suitable dialog * FIXED #170: Command+k for clearing shell in Mac * FIXED #547: Recommend "..." button when plug-ins latest stable isn't suitable for this Thonny version * FIXED #548: Prevent inconsistent use of tabs and spaces error (when pasting or opening text containing tabs, Thonny proposes to replace them with spaces) * FIXED #557: Default window size too small for simple mode * FIXED #559: Make text copied to clipboard available even after closing Thonny * FIXED: Implemented workaround for https://bugs.python.org/issue34927 * TECHNICAL: MicroPython backend now shows the source of failing internal commands 3.0.0rc1 (2018-10-08) ===================== * ENHANCEMENT: Documented several features (see Help => Help contents) * FIXED #523: Open system shell doesn't work with pip 10 * FIXED #534: Add shortcut for step-back * FIXED #538: Turtle programs give false warnings 3.0.0b6 (2018-09-30) ==================== * CHANGED: In order to avoid pollution of user home directory, the configuration file and logs are now stored in directories recommended by platform style guides (%APPDATA%/Thonny on Windows, ~/Library/Thonny on Mac and ~/.config/Thonny on Linux). Old configuration and user logs will be imported on first run. * CHANGED: "Back end" configuration page was renamed to "Interpreter" (as it was in Thonny 2.1) * CHANGED: Python version in Thonny+Python bundles upgraded to 3.7.1rc1 * NEW: File menu received a submenu for easy opening of recent files. * ENHANCEMENT: Add shortcut for clearing shell (Ctrl+L) * ENHANCEMENT: Warn when script is saved with a common library module name (eg. turtle.py) * ENHANCEMENT: Allow switching between regular and simple mode (Tools => Options => General) * FIXED #72: "View => Full screen" (in Expert mode) is now also available on Mac * FIXED #262: Add ability to select an autocomplete suggestion with TAB * FIXED #316: Nice debugger doesn't handle named arguments properly * FIXED #339: Allow disabling sound Tools => Options => General * FIXED #389: AST marker fails with dict merge * FIXED #478: Add option to reopen all files on start-up * FIXED #479: Make Thonny save configuration when "Quit"-ed on Mac * FIXED #480: Thonny now properly remembers opened files * FIXED #498: Open System Shell doesn't work on Raspberry * FIXED #501: Assistant feedback preview link doesn't work on mac * FIXED #510: Error when listing available interpreters in config page * FIXED #518: add menu item: "device" / "Upload current script" for MicroPython (by Jens Diemer) * FIXED: Object inspector can show images (again) * FIXED: Pylint and MyPy processes don't hang anymore with large output. 3.0.0b5 (2018-09-01) ==================== * FIXED: requirements.txt was missing mypy 3.0.0b4 (2018-08-31) ==================== * NEW: When program has syntax error or crashes with an exception, Assistant pane opens and tries to help diagnose the problem. Uses Pylint, MyPy and custom dynamic analysis under the hood. (Big "Thank you!" to Raspberry Pi Foundation for the support!) * ENHANCEMENT: Resizing the main window doesn't mess up views' layout anymore. * ENHANCEMENT: Better support for debugging f-strings. * ENHANCEMENT: Nice debugger now recovers better when it is not able to understand a program. * FIXED #496: Regression which caused Variables view to skip variables updates during "nicer debugging". * FIXED #440: Copy&paste over a selection will now delete the text selection first (was problem for some Linuxes) * FIXED: Removed a nasty debugging statement left into b3, which may cause a crash in the end of debugging. 3.0.0b3 (2018-08-11) ==================== * FIXED: Various problems with pip GUI * FIXED: Variables view misses events * FIXED: Error when last back-end was not available anymore * TECHNICAL: Implemented ChoiceDialog 3.0.0b2 (2018-08-11) ==================== * FIXED: problems with pip GUI in virtualenv 3.0.0b1 (2018-08-11) ==================== Note: This version is successor of 2.2.0b4 and 2.1.21. Stable release of 2.2.0 was skipped. (Incrementing the major version felt more appropriate considering the amount of new and changed features.) * NEW: Thonny now has two debug modes: beside original AST based debug mode (the "nicer" one, Ctrl+F5) there is now also line-based mode (the "faster" one, Shift+F5), which is not so intuitive but much more efficient. * NEW: Both debug modes now support breakpoints (switch on line numbers and double-click on the margin). Big thanks to Raspberry Pi Foundation for the support! * NEW: Alternative presentation for call stack (in single window, just like in most debuggers; see Tools => Options => Debugger) * NEW: Clicking on the links in stacktrace now shows the variables of those frames. * NEW: You can re-run your changed program without closing it first (relevant for graphical programs). * NEW: Checking "Run => Dock user windows" makes your Tkinter windows stay on top and appear always on the same location. This allows tweaking your turtle programs while looking at current output. * NEW: "View => Program arguments" opens a box where you can write the argument string for your program * NEW: "Tools => Options => Backend => Custom Python interpreter" now allows creating virtual environments * NEW: "Tools => Manage packages" now allows installing new packages with all CPython backends, not only virtual environments. If the backend is not a virtual environment it installs to user site packages (with `pip install --user`) * NEW: Thonny now includes basic support for MicroPython (former `thonny_microbit` plug-in). See https://bitbucket.org/plas/thonny/wiki/MicroPython for more info. * CHANGED: Upgraded Python to version 3.7.0 in Thonny+Python bundles * CHANGED: Dropped support for Python 3.4 (both for front-end and back-end) * CHANGED: Dropped support for Tk 8.5. All bundles (including Mac's) now come with Tk 8.6.8 * CHANGED: Default back-end is now "Same as front-end" (was "A special virtual environment"). This makes deployment easier in classroom setting and it is simpler scheme in general. "Special virtual environment" backend may be removed in future versions. * CHANGED: Plug-ins will be now installed to regular user site packages directory (was ~/.thonny/plugins) * CHANGED: If Thonny (front-end) is run from a virtual environment, user directory (with configuration.ini and logs) will be .thonny under virtual environment's root directory (instead of usual ~/.thonny). * ENHANCEMENT: Better Windows installer (run as administrator for all-users install) * ENHANCEMENT: thonny.exe is now digitally signed * ENHANCEMENT: On Linux Thonny now uses native file dialogs (via zenity) * ENHANCEMENT: Nicer debugger can now step into your functions defined in other modules * ENHANCEMENT: Nicer debugger can now stop before the assignement of loop variable in for-loops * ENHANCEMENT: "Run to cursor" can be called by right-clicking desired line in the editor and selecting the command from context menu * ENHANCEMENT: Great time and memory optimizations in nicer debug mode. The ability to step back in time is not so expensive anymore. * ENHANCEMENT: Thonny now detects external file modifications and proposes to reload * ENHANCEMENT: New Windows installer (run as administrator for all-users install) * FIXED #163: Uninstaller now correctly removes "Open with Thonny" context menu entry * FIXED #340: Validate geometry before loading * FIXED #358: sys.exit() in user programs doesn't show stacktrace anymore * FIXED #363: subprocess.run causes Thonny backend to hang * FIXED #375: Files are now saved with linebreaks suitable for current platform * FIXED #419: logging doesn't work in user programs * FIXED #422: Make Ctrl+C, Ctrl+V etc. work on Greek keyboard * FIXED #440: In Linux paste over selection doesn't remove the selection * FIXED #450: Locals marker doesn't work with jedi 0.12 * FIXED #468: Problem with changing backend interpreter * FIXED #471: Problem when Thonny uses jedi 0.11 or newer * FIXED #475: Heap view misbehaving on startup * FIXED: "Run => Run to cursor" works again * FIXED: Thonny now honors PEP 263 style encoding markers when saving files. (UTF-8 is still the default) * FIXED: Problem when jedi 0.10 and parso are both installed * TECHNICAL: Plug-in writers can now control each import in user programs (thonny.backend.VM.add_import_handler) * TECHNICAL: Communication messages between back-end and front-end were changed * TECHNICAL: Thonny doesn't tweak PYTHONUSERBASE anymore to put plugins under ~/.thonny. Regular user site packages is used instead * TECHNICAL: Dependency to "packaging" introduced in 2.2 betas is now replaced with "setuptools" 2.2.0b4 (2018-06-05) ==================== * FIXED: Couldn't open menus with None backend 2.2.0b3 (2018-06-05) ==================== * FIXED #425: Too big automatic scaling * FIXED #427: Can't run files with spaces in filename * FIXED: Fixed a bug when debugging and encountering an exception (by Alar Leemet) * ENHANCEMENT: Show indicator about stepping in the past in the text of editor tabs * ENHANCEMENT: Added Thonny version guards for installing plug-ins * EXPERIMENTAL: Preliminary support for running system commands in Thonny shell (eg. `!ls` or `!dir`) * TECHNICAL: thonny.exe in Windows bundle is now signed * TECHNICAL: Delay starting of Runner until UI is shown * TECHNICAL: Various enhancements to support MicroPython plug-ins 2.2.0b2 (2018-05-04) ==================== * FIXED: Options dialog crashes when Variables view hasn't been created yet 2.2.0b1 (2018-05-04) ==================== * NEW: Added support for stepping back in time during debugging (Run => Step back) by Alar Leemet. If you accidentally stepped over an interesting part of code, then now you can step back and step into. * NEW: Added support for UI and syntax theming (https://bitbucket.org/plas/thonny/wiki/Theming) * NEW: Added several built-in dark themes * NEW: Added support for display scaling / high-DPI screens (Tools => Options => General) * NEW: Added closing buttons to the tabs of all views * NEW: Added support for (CPython) back-end plug-ins (https://bitbucket.org/plas/thonny/wiki/Plugins) * NEW: Current editor line can be highlighted (Tools => Options => Editor) * NEW: Thonny can be started in simple mode (https://bitbucket.org/plas/thonny/wiki/Modes) * NEW: Variables view now allows viewing variables from other modules beside __main__ (Tools => Options => General) * CHANGED: Dropped support for Python 3.4 (both for front-end and back-end) * CHANGED: Reorganized back-end configuration ("Tools => Options => Back-end" instead of "Tools => Options => Interpreter") * CHANGED: The roles of Interrupt and Stop commands are now more clear: Stop always restarts the backend and Interrupt only tries to interrupt * CHANGED: Editing the running program doesn't interrupt it anymore. * CHANGED: Object inspector now shows attributes and object overview on different tabs * CHANGED: Can't set thonny.THONNY_USER_DIR directly in customize.py anymore (https://bitbucket.org/plas/thonny/wiki/DeploymentOptions) * CHANGED: For plug-in writers: Unified early and late plug-ins (load_early_plugin should be renamed to load_plugin) * CHANGED: For plug-in writers: get_workbench and get_runner moved from thonny.globals to thonny * FIXED #358: Hide the stacktrace of SystemExit * FIXED #368: "Open system shell" doesn't work in Xfce (fix by Miro Hrončok) * FIXED #370: Made zooming with Ctrl++ / Ctrl+- work on the numpad on Linux * FIXED #372: Now it's possible to specify a link as backend interpreter (fix by Miro Hrončok) * FIXED #396: exec causes range marker to crash * FIXED #403: Window width may become negative * TECHNICAL: Changed the location and sharing of backend.py, common.py, ast_utils.py * TECHNICAL: Cleaner approach for sharing jedi with the back-end * TECHNICAL: Package manager now uses pypi.org instead of pypi.python.org * TECHNICAL: Several changes in Runner and BackendProxy interface * TECHNICAL: Saving an editor now forces writing to disk (see https://learn.adafruit.com/adafruit-circuit-playground-express/creating-and-editing-code#1-use-an-editor-that-writes-out-the-file-completely-when-you-save-it) 2.1.22 (2018-08-20) =================== Happy re-independence day to Estonia! * ENHANCEMENT: Less intrusive logging for AST marking problems * FIXED #340: Validate geometry before loading * FIXED #363: subprocess.run causes Thonny backend to hang * FIXED #419: logging doesn't work in user programs * FIXED #440: In Linux paste over selection doesn't remove the selection * FIXED #487: Use PyPI.org and turn off pip warnings in package manager * FIXED #490: Debugger gets confused with f-strings * FIXED: In case of back-end problems, kill backend instead of resetting * FIXED: Colorize f-string prefixes 2.1.21 (2018-07-17) =================== * FIXED #471: Another problem when Thonny uses jedi 0.11 or newer 2.1.20 (2018-07-16) =================== * FIXED: Problem when jedi 0.10 and parso are both installed 2.1.19 (2018-07-16) =================== Updates in this version are relevant only on Windows * FIXED #467: Error when running Thonny with pythonw on Windows (regression from 2.1.18) * ENHANCEMENT: New Windows installer (run as administrator for all-users install) * ENHANCEMENT: Upgraded Python to version 3.6.6 in Thonny+Python bundles 2.1.18 (2018-06-22) =================== * FIXED #450: Locals marker doesn't work with jedi 0.12 2.1.17 (2018-03-21) =================== * FIXED #409: Package manager crashed after release of pip 9.0.2 2.1.16 (2017-11-10) =================== * Tests moved under thonny package * Tests included in the source distribution * More icons included in the source distribution 2.1.15 (2017-11-07) =================== * Removed StartupNotify from Linux .desktop file (StartupNotify=true leaves cursor spinning in Debian) 2.1.14 (2017-11-02) =================== * Added some Linux-specific files to source distribution. No new features or fixes. 2.1.13 (2017-10-29) =================== * Temporary workaround for #351: Locals and name highlighter occasionally make Thonny freeze * Include only required licenses in source dist 2.1.12 (2017-10-13) =================== * FIXED #303: Allow specifying same interpreter for backend as frontend uses * FIXED #304: Allow specifying backend interpreter by relative path * FIXED #312: Closing unsaved tab causes error * FIXED #319: Linux install script needs quoting around the path(s) * FIXED #320: Install gets recursive if trying to install within extracted tarball * FIXED #321: Linux installer fails if invoked with relative, local user path * FIXED #334: init.tcl not found (Better control over back-end environment variables) * FIXED #343: Thonny now also works with jedi 0.11 2.1.11 (2017-07-22) =================== * FIXED #31: Infinite print loop freezes Thonny * FIXED #285: Previous used interpreters are not shown in options dialog * FIXED #296: Make it more explicit that pip GUI search box needs exact package name * FIXED #298: Python crashes keep backend hanging * FIXED #305: Variables table doesn't get updated, if it's blocked by another view 2.1.10 (2017-06-09) =================== * NEW: More flexibility for classroom setups (see https://bitbucket.org/plas/thonny/wiki/ClassroomSetup) * FIXED #276: Copy with Ctrl+C causes bell * FIXED #277: Triple-quoted strings keep keyword coloring * FIXED #278: Paste in shell causes bell * FIXED #281: Wrong unindentation with SHIFT+TAB when last line does not end with linebreak * FIXED #283: backend.log path doesn't take THONNY_USER_DIR into account * FIXED #284: Internal error when saving to a read-only folder/file (now proposes to choose another name) 2.1.9 (2017-06-01) ================== * FIXED #273: Memory leak in editor margin because of undo log * FIXED #275: Updating line numbers is very inefficient * FIXED: Pasted text occasionally was hidden below bottom edge of the editor * FIXED: sys.exit() didn't really close the backend 2.1.8 (2017-05-28) ================== * ENHANCEMENT: Code completion with Tab-key is now optional (see Tools => Options => Editor) * ENHANCEMENT: Clicking on the editor now closes code completion box * CHANGED: Code completion box doesn't offer names starting with double underscore anymore. * FIXED: Error caused by too fast typing with open code completions box * ENHANCEMENT: Find/Replace dialog can now be operated with F3 * ENHANCEMENT: Find/Replace pre-selects previously used search string * ENHANCEMENT: Find/Replace dialog doesn't block main window anymore * FIXED: Find/Replace doesn't ignore spaces in search string anymore * FIXED: Closed views reappeared after restart if they were only views in that notebook * FIXED #264: Debugger fails with with conditional list comprehension * FIXED #265: Error when using two word search string in pip GUI * FIXED #266: Occasional incorrect line numbering * FIXED #267: Kivy application main window didn't show in Windows * TECHNICAL: Better diagnostic logging 2.1.7 (2017-05-13) ================== * CHANGED: pip GUI now works in read-only mode unless backend is a virtual environment * FIXED: Error when non-default backend was used without previously generated Thonny-private virtual environment 2.1.6 (2017-05-12) ================== * FIXED #260: Strange behaviour when indenting with TAB * FIXED #261: Editing a triple-quoted string breaks coloring in following lines * FIXED: Made outdated pip detection more general 2.1.5 (2017-05-09) ================== * FIXED: Jedi version checking problem 2.1.4 (2017-05-09) ================== (This release is meant for making Thonny work better with system Python 3.4 in Debian Jessie) * FIXED #254: "Manage plug-ins" now gives instructions for installing pip if system is missing it or it's too old * FIXED #255: Name highlighter and locals marker are now quietly disabled when system has too old jedi * FIXED: Virtual env dialog now closes properly * TECHNICAL: SubprocessDialog now has more robust returncode checking in Linux 2.1.3 (2017-05-09) ================== * FIXED #250: Debugger focus was off by one line in function frames * FIXED #251: Debugger timing issue (wrong command type in the backend) * FIXED #252: Debugger timing issue (get_globals and debugger commands interfere) * FIXED #253: Creating default virtual env does not work when using Debian python3 without ensurepip 2.1.2 (2017-05-08) ================== * FIXED #220 and #237: Icon problems in Linux tasbar. * FIXED #245: Tooltips not working in Mac * FIXED #246: Current script did not get executed if cursor was not in the end of the shell * FIXED #249: Reset, Run and Debug caused double prompt 2.1.1 (2017-05-03) ================== * FIXED #241: Some menu items gave errors with micro:bit backend. * FIXED #242: Focus got stuck on first run (no entry was possible neither in shell nor editor when initialization dialog closed) 2.1.0 (2017-05-02) ================== * TECHNICAL: Changes in diagnostic logging 2.1.0b11 (2017-04-29) ===================== * TECHNICAL: Implemented more robust approach for installing Thonny plugins 2.1.0b10 (2017-04-29) ===================== * CHANGED: Installed plugins now end up under ~/.thonny/plugins * TECHNICAL: Backend preparation now occurs when main window has been opened 2.1.0b9 (2017-04-28) ==================== * FIXED: Backend related regression introduced in b8 2.1.0b8 (2017-04-27) ==================== * CHANGED: (FIXED #231) Stop/Reset button is now Interrupt/Reset button (tries to interrupt a running command instead of reseting. Resets if pressed in idle state) * FIXED #232: Ubuntu showed pip GUI captions with too big font * FIXED #233: Thonny now remembers which view was on top in a panel. * FIXED #234: Multiline support problems in shell (trailing whitespace was causing trouble) * FIXED: pip GUI shows latest version number when there is no stable version. * FIXED: pip GUI now can handle also packages without PyPI presence * TECHNICAL: Backends are not sent Reset command for initialization anymore. 2.1.0b7 (2017-04-25) ================== * FIXED: Removed some circular import to support Python 3.4 * FIXED: pip GUI now also lists installed pre-releases * EXPERIMENTAL: GUI for installing Thonny plug-ins (Tools => Manage plug-ins...) * TECHNICAL: Thonny+Python bundles again include pip (needed for installing plug-ins) * TECHNICAL: Refactored creation of several widgets to support theming * TECHNICAL: THONNY_USER_DIR environment variable can now specify where Thonny stores user data (conf files, default virtual env, ...) 2.1.0b6 (2017-04-19) ================== * ENHANCEMENT: Shell now shows location of external interpreter as welcome text * FIXED #224: Tab-indentation didn't work if tail of the text was selected and text didn't end with empty line * FIXED: Tab with selected text occasionally invoked code-completion * TECHNICAL: Tweaks in Windows console allocation * TECHNICAL: Thonny+Python bundles don't include pip anymore (venv gets pip via ensurepip) 2.1.0b5 (2017-04-18) ================== * FIXED: Typo in pipGUI (regression introduced in b4) 2.1.0b4 (2017-04-18) ==================== * CHANGED: If you want to use Thonny with external Python interpreter, then now you should select python.exe instead of pythonw.exe. * FIXED #223: Can't interrupt subprocess when Thonny is run via thonny.exe * FIXED: Private venv didn't find Tcl/Tk in ubuntu (commit 33eabff) * FIXED: Right-click on editor tabs now also works on macOS. 2.1.0b3 (2017-04-17) ==================== * NEW: Dialog for managing 3rd party packages / a simple pip GUI. Check it out: "Tools => Manage packages" * NEW: Shell now supports multiline commands * ENHANCEMENT: Window title now shows full path and cursor location of current file. * ENHANCEMENT: Editor lines can be selected by clicking and/or dragging on line-number margin (thanks to Sven). * ENHANCEMENT: Most programs can now be interrupted by Ctrl+C without restarting the process. * ENHANCEMENT: You can start editing the code that is still running (the process gets interrupted automatically). This is handy when developing tkinter applications. * ENHANCEMENT: Tab can be used as alternative code-completion shortcut. * ENHANCEMENT: Recommended pip-command now appears faster in System Shell. * ENHANCEMENT: Alternative interpreter doesn't need to have jedi installed in order to provide code-completions (see #171: Code auto-complete error) * ENHANCEMENT: Double-click on autocomplete list inserts the completion * EXPERIMENTAL: Ctrl-click on a name in code tries to locate its definition. NB! Not finished yet! * CHANGED: Bundled Python version has been upgraded to 3.6.1 * CHANGED: Bundled Python in Mac and Linux now uses SSL certs from certifi project (https://pypi.python.org/pypi/certifi). * REMOVED: Moved incomplete Exercise system to a separate plugin (https://bitbucket.org/plas/thonny-exersys). With this got rid of tkinterhtml, requests and beautifulsoup4 dependencies. * FIXED #16: Run doesn't clear variables (again?) * FIXED #98: Nested functions crashed the debugger. * FIXED #114: Crash when trying to change interpreter in macOS. * FIXED #142: "Open system shell" failed when Thonny path had spaces in it. Paths are now properly quoted. * FIXED #154: Problems with Notebook tabs' context menus * FIXED #159: Debugging list or set comprehension caused crash * FIXED #166: Can't delete one of two spaces with backspace * FIXED #180: Right-click doesn't focus editor * FIXED #187: Main modules launched by Thonny were missing ``__spec__`` attribute. * FIXED #195: Debugger crashes when using generators. * FIXED #201: "Tools => Open Thonny data folder" now works also in macOS. * FIXED #211: Linux installer was failing when using ``xdg-user-dir`` (thanks to Ryan McQuen) * FIXED #213: In single instance mode new Window doesn't get focus * FIXED #217: Debugger on Python 3.5 and later can't handle splat operator * FIXED #221: Context menus in Linux can now be closed by clicking elsewhere * FIXED: Event logger did not save filenames (eb34c5d). * FIXED: Problem in replayer (db78855). * TECHNICAL: Bundled Jedi version has been upgraded to 0.10.2. * TECHNICAL: 3rd party Thonny plugins must now be under ``thonnycontrib`` namespace package. * TECHNICAL: Introduced the concept of "eary plugins" (plugins, which get loaded before initializing the runner). * TECHNICAL: Refactored the interface between GUI and backend to allow different backend implementations * TECHNICAL: Previously, with bundled Python, Thonny was using nasty tricks to force pip install packages install under ~/.thonny. Now it creates a proper virtual environment under ~/.thonny and uses this as the backend by default (instead of using interpreter running the GUI directly). * TECHNICAL: Automatic tkinter updates on the backend are now less invasive 2.0.7 (2017-01-06) ================== * FIXED: Making font size too small would crash Thonny. * FIXED: Another take on configuration file corruption. * FIXED: Shift-Tab wasn’t working in some cases. * FIXED #165: "Open system shell" did not add Scripts dir to PATH in Windows. * FIXED #183: ``from __future__ import`` crashed the debugger. 2.0.6 (2017-01-06) ================== * FIXED: a bug in Linux installer (configuration file wasn’t created in new installations) 2.0.5 (2016-11-30) ================== * FIXED: Corrected shift key detection (a82bd4d) 2.0.4 (2016-10-26) ================== * FIXED: Configuration file was occasionally getting corrupted (for mysterious reasons, maybe a bug in Python’s configparser) * FIXED #104: Negative font size crashed Thonny * FIXED #143: Linux installer fails if desktop isn't named "Desktop". (Later turned out this wasn't fixed for all cases). * FIXED #134: "Open system shell" doesn't work in Centos 7 KDE 2.0.3 (2016-09-30) ================== * FIXED: Quoting in "Open system shell" in Mac. Again. 2.0.2 (2016-09-30) ================== * FIXED: Quoting in "Open system shell" in Mac. 2.0.1 (2016-09-30) ================== * FIXED #106: Don't let user logs grow too big 2.0.0 (2016-09-29) ================== * NEW: Added code completion (powered by Jedi: https://github.com/davidhalter/jedi) * NEW: Added new command "Tools => Open system shell" which opens terminal where current Python is in PATH. * CHANGED: Single instance mode is now optional (Tools => Options => General) * FIXED: Many bugs 1.2.0b2 (2016-02-10) ==================== * NEW: Thonny now runs in single instance mode. Previously, when you opened a py file with Thonny, a new Thonny instance (window) was created even if an instance existed already. This became nuisance if you opened several files. Now Thonny works as single instance program, meaning only one instance of Thonny runs at the time. When you open another file, it is opened in existing window. * NEW: Editor enhancements. Added option to show line numbers and right margin in the editor. In order to keep first impression cleaner, they are disabled by default. See Tools => Options => Editor. Don't forget that you don't need line numbers for locating lines mentioned in error messages -- you can click them and Thonny shows you the line. * FIXED: Some bugs where Thonny couldn't prepare some programs for debugging. Older versions ============== See https://github.com/thonny/thonny/issues and https://github.com/thonny/thonny/commits thonny-3.2.7/README.rst0000644000175000017500000000053213611773167015557 0ustar annamaaannamaa00000000000000====== Thonny ====== Thonny is a Python IDE meant for learning programming. End users --------- See https://thonny.org and `wiki `_ for more info. Contributors ------------ Contributions are welcome! See `CONTRIBUTING.rst `_ for more info. thonny-3.2.7/LICENSE.txt0000644000175000017500000000207113611773167015713 0ustar annamaaannamaa00000000000000The MIT License (MIT) Copyright (c) 2020 Aivar Annamaa Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. thonny-3.2.7/setup.py0000644000175000017500000000600613611773167015604 0ustar annamaaannamaa00000000000000import os.path import sys from setuptools import find_packages, setup def recursive_files(directory): paths = [] for (path, _, filenames) in os.walk(directory): for filename in filenames: paths.append(os.path.join('..', path, filename)) return paths if sys.version_info < (3, 5): raise RuntimeError("Thonny requires Python 3.5 or later") setupdir = os.path.dirname(__file__) with open(os.path.join(setupdir, "thonny", "VERSION"), encoding="ASCII") as f: version = f.read().strip() requirements = [] for line in open(os.path.join(setupdir, "requirements.txt"), encoding="ASCII"): if line.strip() and not line.startswith("#"): requirements.append(line) setup( name="thonny", version=version, description="Python IDE for beginners", long_description="Thonny is a simple Python IDE with features useful for learning programming. See https://thonny.org for more info.", url="https://thonny.org", author="Aivar Annamaa and others", author_email="thonny@googlegroups.com", license="MIT", classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: MacOS X", "Environment :: Win32 (MS Windows)", "Environment :: X11 Applications", "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: End Users/Desktop", "License :: Freeware", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: MacOS", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Education", "Topic :: Software Development", "Topic :: Software Development :: Debuggers", "Topic :: Text Editors", ], keywords="IDE education debugger", project_urls={ "Source code": "https://github.com/thonny/thonny", "Bug tracker": "https://github.com/thonny/thonny/issues", }, platforms=["Windows", "macOS", "Linux"], install_requires=requirements, python_requires=">=3.5", packages=find_packages(), package_data={ "": ["VERSION", "res/*"] + recursive_files("thonny/locale"), "thonny.plugins.help": ["*.rst"], "thonny.plugins.pi": ["res/*.*"], "thonny.plugins.printing": ["*.html"], "thonny.plugins.micropython": ["api_stubs/*.*"], "thonny.plugins.circuitpython": ["api_stubs/*.*"], "thonny.plugins.microbit": ["api_stubs/*.*"], "thonny.plugins.esp": ["esp32_api_stubs/*.*", "esp_8266_api_stubs/*.*"], "thonny.plugins.mypy": ["typeshed_extras/*.pyi"], }, entry_points={"gui_scripts": ["thonny = thonny:launch"]}, ) thonny-3.2.7/CREDITS.rst0000644000175000017500000000604313611774245015720 0ustar annamaaannamaa00000000000000======= Credits ======= Thonny is thankful to: Its home -------- Thonny grew up in University of Tartu (https://www.ut.ee), Institute of Computer Science (https://www.cs.ut.ee). Supporters ---------- * Development of several features in Thonny 3.0 was proposed and supported by Raspberry Pi Foundation (https://www.raspberrypi.org). * Since September 2018, development of Thonny is partially supported by Cybernetica AS (https://cyber.ee). Python ------ It's a really nice language for teaching programming. It also has some nice technical properties, that made Thonny's program animation features pleasure to implement. Libraries, resources and tools ------------------------------ * asttokens (https://github.com/gristlabs/asttokens) provides source locations to AST nodes. * jedi (http://jedi.readthedocs.io) is used for code completion, go to definition, etc. * pylint (https://www.pylint.org/) is used as one of the engines behind warnings presented by the Assistant. * mypy (http://mypy-lang.org/) is used, just like pylint, as a warning engine in the Assistant. * pyserial (https://github.com/pyserial/pyserial) is used for communicating with MicroPython devices. * docutils (http://docutils.sourceforge.net/) is used for parsing help content written in reStructuredText. * send2trash (https://github.com/hsoft/send2trash) is used by the Files view. * certifi (https://pypi.python.org/pypi/certifi) provides SSL certs for bundled Python in Linux and Mac. * distro (https://pypi.python.org/pypi/distro) is optionally used for detecting Linux version in About dialog. * Most icons are taken from Eclipse project (https://www.eclipse.org/, https://github.com/eclipse/eclipse.platform.debug/tree/master/org.eclipse.debug.ui/icons/full/, https://github.com/eclipse/eclipse.platform.ui/tree/master/bundles/org.eclipse.ui/icons/full/, https://github.com/eclipse/eclipse.jdt.ui/tree/master/org.eclipse.jdt.ui/icons/full/), on Linux, some are overriden by Tango icons (http://tango.freedesktop.org/) * POEditor (https://poeditor.com/) is used for managing translations of UI strings. Source contributors, advisors, translators and frequent bug-reporters --------------------------------------------------------------------- * adzierzanowski * Aivar Annamaa * Alar Leemet * Aleks ANDRÉ * Alex Hall * Anatoly Techtonik * André Roberge * Antonio Carlos * Austin Bart * badukaire * borpol * cefn * Celso Isayah Dias * Chad Purdy * cspaier * cubimon * Dominic Twyman * Dominik George * Emanuel Angelo * Filip Schouwenaars * Fizban * fstengel * Georges Khaznadar * Ivanhercaz * Ivan.schamann * Илья Кругликов * Jarek Miszczak * Jens Diemer * Juan Falgueras * Kauri Raba * M. Burak Kalkan * Matt Iversen * Miro Hrončok * NathanBnm * Peter Marshall * Phil Duby * Rene Lehtma * sailslack * segalion * Simon Gijsen * Simon Long * Sven Duzont * Taavi Ilp * Toomas Mölder * Tusamten * Vytenis (svajoklis-1) * Xin Rong * 涂紳騰 (Shen-Teng Tu) * 張文宏 (Wen-Hung, Chang) Please let us know if we have forgotten to add your name to this list! Also, let us know if you want to remove your name. thonny-3.2.7/setup.cfg0000644000175000017500000000004613611777205015706 0ustar annamaaannamaa00000000000000[egg_info] tag_build = tag_date = 0 thonny-3.2.7/PKG-INFO0000644000175000017500000000314213611777205015162 0ustar annamaaannamaa00000000000000Metadata-Version: 1.2 Name: thonny Version: 3.2.7 Summary: Python IDE for beginners Home-page: https://thonny.org Author: Aivar Annamaa and others Author-email: thonny@googlegroups.com License: MIT Project-URL: Source code, https://github.com/thonny/thonny Project-URL: Bug tracker, https://github.com/thonny/thonny/issues Description: Thonny is a simple Python IDE with features useful for learning programming. See https://thonny.org for more info. Keywords: IDE education debugger Platform: Windows Platform: macOS Platform: Linux Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: MacOS X Classifier: Environment :: Win32 (MS Windows) Classifier: Environment :: X11 Applications Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Education Classifier: Intended Audience :: End Users/Desktop Classifier: License :: Freeware Classifier: License :: OSI Approved :: MIT License Classifier: Natural Language :: English Classifier: Operating System :: MacOS Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Education Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Debuggers Classifier: Topic :: Text Editors Requires-Python: >=3.5