prasb commited on
Commit
91434d2
·
verified ·
1 Parent(s): 41b2461

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. my_container_sandbox/workspace/anaconda3/lib/python3.8/collections/abc.py +2 -0
  3. my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/cmd.py +403 -0
  4. my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/config.py +130 -0
  5. my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/dir_util.py +210 -0
  6. my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/extension.py +240 -0
  7. my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/log.py +77 -0
  8. my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/msvc9compiler.py +789 -0
  9. my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/sysconfig.py +554 -0
  10. my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/text_file.py +286 -0
  11. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/HISTORY.txt +296 -0
  12. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/NEWS2x.txt +660 -0
  13. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/TODO.txt +210 -0
  14. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/__init__.py +10 -0
  15. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/autocomplete.py +223 -0
  16. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/autoexpand.py +96 -0
  17. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/calltip.py +205 -0
  18. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/codecontext.py +270 -0
  19. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/colorizer.py +340 -0
  20. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config-extensions.def +62 -0
  21. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config-highlight.def +105 -0
  22. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config-keys.def +309 -0
  23. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config-main.def +93 -0
  24. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config.py +911 -0
  25. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/configdialog.py +0 -0
  26. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/debugger.py +550 -0
  27. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/debugger_r.py +393 -0
  28. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/debugobj.py +142 -0
  29. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/debugobj_r.py +41 -0
  30. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/delegator.py +33 -0
  31. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/editor.py +1672 -0
  32. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/extend.txt +83 -0
  33. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/filelist.py +131 -0
  34. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/format.py +426 -0
  35. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/grep.py +221 -0
  36. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/help.html +1014 -0
  37. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/help.py +294 -0
  38. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/help_about.py +207 -0
  39. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/history.py +106 -0
  40. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/hyperparser.py +312 -0
  41. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/idle.bat +4 -0
  42. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/idle.py +14 -0
  43. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/idle.pyw +17 -0
  44. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/macosx.py +287 -0
  45. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/multicall.py +448 -0
  46. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/outwin.py +187 -0
  47. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/parenmatch.py +183 -0
  48. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/pathbrowser.py +111 -0
  49. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/pyparse.py +593 -0
  50. my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/pyshell.py +1579 -0
.gitattributes CHANGED
@@ -172,3 +172,4 @@ my_container_sandbox/workspace/anaconda3/pkgs/ca-certificates-2024.2.2-hbcca054_
172
  my_container_sandbox/workspace/anaconda3/pkgs/ncurses-6.4-h6a678d5_0.conda filter=lfs diff=lfs merge=lfs -text
173
  my_container_sandbox/workspace/anaconda3/pkgs/ca-certificates-2021.7.5-h06a4308_1.conda filter=lfs diff=lfs merge=lfs -text
174
  my_container_sandbox/workspace/anaconda3/pkgs/conda-package-handling-2.2.0-pyh38be061_0.conda filter=lfs diff=lfs merge=lfs -text
 
 
172
  my_container_sandbox/workspace/anaconda3/pkgs/ncurses-6.4-h6a678d5_0.conda filter=lfs diff=lfs merge=lfs -text
173
  my_container_sandbox/workspace/anaconda3/pkgs/ca-certificates-2021.7.5-h06a4308_1.conda filter=lfs diff=lfs merge=lfs -text
174
  my_container_sandbox/workspace/anaconda3/pkgs/conda-package-handling-2.2.0-pyh38be061_0.conda filter=lfs diff=lfs merge=lfs -text
175
+ my_container_sandbox/workspace/anaconda3/pkgs/sqlite-3.36.0-hc218d9a_0.conda filter=lfs diff=lfs merge=lfs -text
my_container_sandbox/workspace/anaconda3/lib/python3.8/collections/abc.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ from _collections_abc import *
2
+ from _collections_abc import __all__
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/cmd.py ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """distutils.cmd
2
+
3
+ Provides the Command class, the base class for the command classes
4
+ in the distutils.command package.
5
+ """
6
+
7
+ import sys, os, re
8
+ from distutils.errors import DistutilsOptionError
9
+ from distutils import util, dir_util, file_util, archive_util, dep_util
10
+ from distutils import log
11
+
12
+ class Command:
13
+ """Abstract base class for defining command classes, the "worker bees"
14
+ of the Distutils. A useful analogy for command classes is to think of
15
+ them as subroutines with local variables called "options". The options
16
+ are "declared" in 'initialize_options()' and "defined" (given their
17
+ final values, aka "finalized") in 'finalize_options()', both of which
18
+ must be defined by every command class. The distinction between the
19
+ two is necessary because option values might come from the outside
20
+ world (command line, config file, ...), and any options dependent on
21
+ other options must be computed *after* these outside influences have
22
+ been processed -- hence 'finalize_options()'. The "body" of the
23
+ subroutine, where it does all its work based on the values of its
24
+ options, is the 'run()' method, which must also be implemented by every
25
+ command class.
26
+ """
27
+
28
+ # 'sub_commands' formalizes the notion of a "family" of commands,
29
+ # eg. "install" as the parent with sub-commands "install_lib",
30
+ # "install_headers", etc. The parent of a family of commands
31
+ # defines 'sub_commands' as a class attribute; it's a list of
32
+ # (command_name : string, predicate : unbound_method | string | None)
33
+ # tuples, where 'predicate' is a method of the parent command that
34
+ # determines whether the corresponding command is applicable in the
35
+ # current situation. (Eg. we "install_headers" is only applicable if
36
+ # we have any C header files to install.) If 'predicate' is None,
37
+ # that command is always applicable.
38
+ #
39
+ # 'sub_commands' is usually defined at the *end* of a class, because
40
+ # predicates can be unbound methods, so they must already have been
41
+ # defined. The canonical example is the "install" command.
42
+ sub_commands = []
43
+
44
+
45
+ # -- Creation/initialization methods -------------------------------
46
+
47
+ def __init__(self, dist):
48
+ """Create and initialize a new Command object. Most importantly,
49
+ invokes the 'initialize_options()' method, which is the real
50
+ initializer and depends on the actual command being
51
+ instantiated.
52
+ """
53
+ # late import because of mutual dependence between these classes
54
+ from distutils.dist import Distribution
55
+
56
+ if not isinstance(dist, Distribution):
57
+ raise TypeError("dist must be a Distribution instance")
58
+ if self.__class__ is Command:
59
+ raise RuntimeError("Command is an abstract class")
60
+
61
+ self.distribution = dist
62
+ self.initialize_options()
63
+
64
+ # Per-command versions of the global flags, so that the user can
65
+ # customize Distutils' behaviour command-by-command and let some
66
+ # commands fall back on the Distribution's behaviour. None means
67
+ # "not defined, check self.distribution's copy", while 0 or 1 mean
68
+ # false and true (duh). Note that this means figuring out the real
69
+ # value of each flag is a touch complicated -- hence "self._dry_run"
70
+ # will be handled by __getattr__, below.
71
+ # XXX This needs to be fixed.
72
+ self._dry_run = None
73
+
74
+ # verbose is largely ignored, but needs to be set for
75
+ # backwards compatibility (I think)?
76
+ self.verbose = dist.verbose
77
+
78
+ # Some commands define a 'self.force' option to ignore file
79
+ # timestamps, but methods defined *here* assume that
80
+ # 'self.force' exists for all commands. So define it here
81
+ # just to be safe.
82
+ self.force = None
83
+
84
+ # The 'help' flag is just used for command-line parsing, so
85
+ # none of that complicated bureaucracy is needed.
86
+ self.help = 0
87
+
88
+ # 'finalized' records whether or not 'finalize_options()' has been
89
+ # called. 'finalize_options()' itself should not pay attention to
90
+ # this flag: it is the business of 'ensure_finalized()', which
91
+ # always calls 'finalize_options()', to respect/update it.
92
+ self.finalized = 0
93
+
94
+ # XXX A more explicit way to customize dry_run would be better.
95
+ def __getattr__(self, attr):
96
+ if attr == 'dry_run':
97
+ myval = getattr(self, "_" + attr)
98
+ if myval is None:
99
+ return getattr(self.distribution, attr)
100
+ else:
101
+ return myval
102
+ else:
103
+ raise AttributeError(attr)
104
+
105
+ def ensure_finalized(self):
106
+ if not self.finalized:
107
+ self.finalize_options()
108
+ self.finalized = 1
109
+
110
+ # Subclasses must define:
111
+ # initialize_options()
112
+ # provide default values for all options; may be customized by
113
+ # setup script, by options from config file(s), or by command-line
114
+ # options
115
+ # finalize_options()
116
+ # decide on the final values for all options; this is called
117
+ # after all possible intervention from the outside world
118
+ # (command-line, option file, etc.) has been processed
119
+ # run()
120
+ # run the command: do whatever it is we're here to do,
121
+ # controlled by the command's various option values
122
+
123
+ def initialize_options(self):
124
+ """Set default values for all the options that this command
125
+ supports. Note that these defaults may be overridden by other
126
+ commands, by the setup script, by config files, or by the
127
+ command-line. Thus, this is not the place to code dependencies
128
+ between options; generally, 'initialize_options()' implementations
129
+ are just a bunch of "self.foo = None" assignments.
130
+
131
+ This method must be implemented by all command classes.
132
+ """
133
+ raise RuntimeError("abstract method -- subclass %s must override"
134
+ % self.__class__)
135
+
136
+ def finalize_options(self):
137
+ """Set final values for all the options that this command supports.
138
+ This is always called as late as possible, ie. after any option
139
+ assignments from the command-line or from other commands have been
140
+ done. Thus, this is the place to code option dependencies: if
141
+ 'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
142
+ long as 'foo' still has the same value it was assigned in
143
+ 'initialize_options()'.
144
+
145
+ This method must be implemented by all command classes.
146
+ """
147
+ raise RuntimeError("abstract method -- subclass %s must override"
148
+ % self.__class__)
149
+
150
+
151
+ def dump_options(self, header=None, indent=""):
152
+ from distutils.fancy_getopt import longopt_xlate
153
+ if header is None:
154
+ header = "command options for '%s':" % self.get_command_name()
155
+ self.announce(indent + header, level=log.INFO)
156
+ indent = indent + " "
157
+ for (option, _, _) in self.user_options:
158
+ option = option.translate(longopt_xlate)
159
+ if option[-1] == "=":
160
+ option = option[:-1]
161
+ value = getattr(self, option)
162
+ self.announce(indent + "%s = %s" % (option, value),
163
+ level=log.INFO)
164
+
165
+ def run(self):
166
+ """A command's raison d'etre: carry out the action it exists to
167
+ perform, controlled by the options initialized in
168
+ 'initialize_options()', customized by other commands, the setup
169
+ script, the command-line, and config files, and finalized in
170
+ 'finalize_options()'. All terminal output and filesystem
171
+ interaction should be done by 'run()'.
172
+
173
+ This method must be implemented by all command classes.
174
+ """
175
+ raise RuntimeError("abstract method -- subclass %s must override"
176
+ % self.__class__)
177
+
178
+ def announce(self, msg, level=1):
179
+ """If the current verbosity level is of greater than or equal to
180
+ 'level' print 'msg' to stdout.
181
+ """
182
+ log.log(level, msg)
183
+
184
+ def debug_print(self, msg):
185
+ """Print 'msg' to stdout if the global DEBUG (taken from the
186
+ DISTUTILS_DEBUG environment variable) flag is true.
187
+ """
188
+ from distutils.debug import DEBUG
189
+ if DEBUG:
190
+ print(msg)
191
+ sys.stdout.flush()
192
+
193
+
194
+ # -- Option validation methods -------------------------------------
195
+ # (these are very handy in writing the 'finalize_options()' method)
196
+ #
197
+ # NB. the general philosophy here is to ensure that a particular option
198
+ # value meets certain type and value constraints. If not, we try to
199
+ # force it into conformance (eg. if we expect a list but have a string,
200
+ # split the string on comma and/or whitespace). If we can't force the
201
+ # option into conformance, raise DistutilsOptionError. Thus, command
202
+ # classes need do nothing more than (eg.)
203
+ # self.ensure_string_list('foo')
204
+ # and they can be guaranteed that thereafter, self.foo will be
205
+ # a list of strings.
206
+
207
+ def _ensure_stringlike(self, option, what, default=None):
208
+ val = getattr(self, option)
209
+ if val is None:
210
+ setattr(self, option, default)
211
+ return default
212
+ elif not isinstance(val, str):
213
+ raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
214
+ % (option, what, val))
215
+ return val
216
+
217
+ def ensure_string(self, option, default=None):
218
+ """Ensure that 'option' is a string; if not defined, set it to
219
+ 'default'.
220
+ """
221
+ self._ensure_stringlike(option, "string", default)
222
+
223
+ def ensure_string_list(self, option):
224
+ r"""Ensure that 'option' is a list of strings. If 'option' is
225
+ currently a string, we split it either on /,\s*/ or /\s+/, so
226
+ "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
227
+ ["foo", "bar", "baz"].
228
+ """
229
+ val = getattr(self, option)
230
+ if val is None:
231
+ return
232
+ elif isinstance(val, str):
233
+ setattr(self, option, re.split(r',\s*|\s+', val))
234
+ else:
235
+ if isinstance(val, list):
236
+ ok = all(isinstance(v, str) for v in val)
237
+ else:
238
+ ok = False
239
+ if not ok:
240
+ raise DistutilsOptionError(
241
+ "'%s' must be a list of strings (got %r)"
242
+ % (option, val))
243
+
244
+ def _ensure_tested_string(self, option, tester, what, error_fmt,
245
+ default=None):
246
+ val = self._ensure_stringlike(option, what, default)
247
+ if val is not None and not tester(val):
248
+ raise DistutilsOptionError(("error in '%s' option: " + error_fmt)
249
+ % (option, val))
250
+
251
+ def ensure_filename(self, option):
252
+ """Ensure that 'option' is the name of an existing file."""
253
+ self._ensure_tested_string(option, os.path.isfile,
254
+ "filename",
255
+ "'%s' does not exist or is not a file")
256
+
257
+ def ensure_dirname(self, option):
258
+ self._ensure_tested_string(option, os.path.isdir,
259
+ "directory name",
260
+ "'%s' does not exist or is not a directory")
261
+
262
+
263
+ # -- Convenience methods for commands ------------------------------
264
+
265
+ def get_command_name(self):
266
+ if hasattr(self, 'command_name'):
267
+ return self.command_name
268
+ else:
269
+ return self.__class__.__name__
270
+
271
+ def set_undefined_options(self, src_cmd, *option_pairs):
272
+ """Set the values of any "undefined" options from corresponding
273
+ option values in some other command object. "Undefined" here means
274
+ "is None", which is the convention used to indicate that an option
275
+ has not been changed between 'initialize_options()' and
276
+ 'finalize_options()'. Usually called from 'finalize_options()' for
277
+ options that depend on some other command rather than another
278
+ option of the same command. 'src_cmd' is the other command from
279
+ which option values will be taken (a command object will be created
280
+ for it if necessary); the remaining arguments are
281
+ '(src_option,dst_option)' tuples which mean "take the value of
282
+ 'src_option' in the 'src_cmd' command object, and copy it to
283
+ 'dst_option' in the current command object".
284
+ """
285
+ # Option_pairs: list of (src_option, dst_option) tuples
286
+ src_cmd_obj = self.distribution.get_command_obj(src_cmd)
287
+ src_cmd_obj.ensure_finalized()
288
+ for (src_option, dst_option) in option_pairs:
289
+ if getattr(self, dst_option) is None:
290
+ setattr(self, dst_option, getattr(src_cmd_obj, src_option))
291
+
292
+ def get_finalized_command(self, command, create=1):
293
+ """Wrapper around Distribution's 'get_command_obj()' method: find
294
+ (create if necessary and 'create' is true) the command object for
295
+ 'command', call its 'ensure_finalized()' method, and return the
296
+ finalized command object.
297
+ """
298
+ cmd_obj = self.distribution.get_command_obj(command, create)
299
+ cmd_obj.ensure_finalized()
300
+ return cmd_obj
301
+
302
+ # XXX rename to 'get_reinitialized_command()'? (should do the
303
+ # same in dist.py, if so)
304
+ def reinitialize_command(self, command, reinit_subcommands=0):
305
+ return self.distribution.reinitialize_command(command,
306
+ reinit_subcommands)
307
+
308
+ def run_command(self, command):
309
+ """Run some other command: uses the 'run_command()' method of
310
+ Distribution, which creates and finalizes the command object if
311
+ necessary and then invokes its 'run()' method.
312
+ """
313
+ self.distribution.run_command(command)
314
+
315
+ def get_sub_commands(self):
316
+ """Determine the sub-commands that are relevant in the current
317
+ distribution (ie., that need to be run). This is based on the
318
+ 'sub_commands' class attribute: each tuple in that list may include
319
+ a method that we call to determine if the subcommand needs to be
320
+ run for the current distribution. Return a list of command names.
321
+ """
322
+ commands = []
323
+ for (cmd_name, method) in self.sub_commands:
324
+ if method is None or method(self):
325
+ commands.append(cmd_name)
326
+ return commands
327
+
328
+
329
+ # -- External world manipulation -----------------------------------
330
+
331
+ def warn(self, msg):
332
+ log.warn("warning: %s: %s\n", self.get_command_name(), msg)
333
+
334
+ def execute(self, func, args, msg=None, level=1):
335
+ util.execute(func, args, msg, dry_run=self.dry_run)
336
+
337
+ def mkpath(self, name, mode=0o777):
338
+ dir_util.mkpath(name, mode, dry_run=self.dry_run)
339
+
340
+ def copy_file(self, infile, outfile, preserve_mode=1, preserve_times=1,
341
+ link=None, level=1):
342
+ """Copy a file respecting verbose, dry-run and force flags. (The
343
+ former two default to whatever is in the Distribution object, and
344
+ the latter defaults to false for commands that don't define it.)"""
345
+ return file_util.copy_file(infile, outfile, preserve_mode,
346
+ preserve_times, not self.force, link,
347
+ dry_run=self.dry_run)
348
+
349
+ def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1,
350
+ preserve_symlinks=0, level=1):
351
+ """Copy an entire directory tree respecting verbose, dry-run,
352
+ and force flags.
353
+ """
354
+ return dir_util.copy_tree(infile, outfile, preserve_mode,
355
+ preserve_times, preserve_symlinks,
356
+ not self.force, dry_run=self.dry_run)
357
+
358
+ def move_file (self, src, dst, level=1):
359
+ """Move a file respecting dry-run flag."""
360
+ return file_util.move_file(src, dst, dry_run=self.dry_run)
361
+
362
+ def spawn(self, cmd, search_path=1, level=1):
363
+ """Spawn an external command respecting dry-run flag."""
364
+ from distutils.spawn import spawn
365
+ spawn(cmd, search_path, dry_run=self.dry_run)
366
+
367
+ def make_archive(self, base_name, format, root_dir=None, base_dir=None,
368
+ owner=None, group=None):
369
+ return archive_util.make_archive(base_name, format, root_dir, base_dir,
370
+ dry_run=self.dry_run,
371
+ owner=owner, group=group)
372
+
373
+ def make_file(self, infiles, outfile, func, args,
374
+ exec_msg=None, skip_msg=None, level=1):
375
+ """Special case of 'execute()' for operations that process one or
376
+ more input files and generate one output file. Works just like
377
+ 'execute()', except the operation is skipped and a different
378
+ message printed if 'outfile' already exists and is newer than all
379
+ files listed in 'infiles'. If the command defined 'self.force',
380
+ and it is true, then the command is unconditionally run -- does no
381
+ timestamp checks.
382
+ """
383
+ if skip_msg is None:
384
+ skip_msg = "skipping %s (inputs unchanged)" % outfile
385
+
386
+ # Allow 'infiles' to be a single string
387
+ if isinstance(infiles, str):
388
+ infiles = (infiles,)
389
+ elif not isinstance(infiles, (list, tuple)):
390
+ raise TypeError(
391
+ "'infiles' must be a string, or a list or tuple of strings")
392
+
393
+ if exec_msg is None:
394
+ exec_msg = "generating %s from %s" % (outfile, ', '.join(infiles))
395
+
396
+ # If 'outfile' must be regenerated (either because it doesn't
397
+ # exist, is out-of-date, or the 'force' flag is true) then
398
+ # perform the action that presumably regenerates it
399
+ if self.force or dep_util.newer_group(infiles, outfile):
400
+ self.execute(func, args, exec_msg, level)
401
+ # Otherwise, print the "skip" message
402
+ else:
403
+ log.debug(skip_msg)
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/config.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """distutils.pypirc
2
+
3
+ Provides the PyPIRCCommand class, the base class for the command classes
4
+ that uses .pypirc in the distutils.command package.
5
+ """
6
+ import os
7
+ from configparser import RawConfigParser
8
+
9
+ from distutils.cmd import Command
10
+
11
+ DEFAULT_PYPIRC = """\
12
+ [distutils]
13
+ index-servers =
14
+ pypi
15
+
16
+ [pypi]
17
+ username:%s
18
+ password:%s
19
+ """
20
+
21
+ class PyPIRCCommand(Command):
22
+ """Base command that knows how to handle the .pypirc file
23
+ """
24
+ DEFAULT_REPOSITORY = 'https://upload.pypi.org/legacy/'
25
+ DEFAULT_REALM = 'pypi'
26
+ repository = None
27
+ realm = None
28
+
29
+ user_options = [
30
+ ('repository=', 'r',
31
+ "url of repository [default: %s]" % \
32
+ DEFAULT_REPOSITORY),
33
+ ('show-response', None,
34
+ 'display full response text from server')]
35
+
36
+ boolean_options = ['show-response']
37
+
38
+ def _get_rc_file(self):
39
+ """Returns rc file path."""
40
+ return os.path.join(os.path.expanduser('~'), '.pypirc')
41
+
42
+ def _store_pypirc(self, username, password):
43
+ """Creates a default .pypirc file."""
44
+ rc = self._get_rc_file()
45
+ with os.fdopen(os.open(rc, os.O_CREAT | os.O_WRONLY, 0o600), 'w') as f:
46
+ f.write(DEFAULT_PYPIRC % (username, password))
47
+
48
+ def _read_pypirc(self):
49
+ """Reads the .pypirc file."""
50
+ rc = self._get_rc_file()
51
+ if os.path.exists(rc):
52
+ self.announce('Using PyPI login from %s' % rc)
53
+ repository = self.repository or self.DEFAULT_REPOSITORY
54
+
55
+ config = RawConfigParser()
56
+ config.read(rc)
57
+ sections = config.sections()
58
+ if 'distutils' in sections:
59
+ # let's get the list of servers
60
+ index_servers = config.get('distutils', 'index-servers')
61
+ _servers = [server.strip() for server in
62
+ index_servers.split('\n')
63
+ if server.strip() != '']
64
+ if _servers == []:
65
+ # nothing set, let's try to get the default pypi
66
+ if 'pypi' in sections:
67
+ _servers = ['pypi']
68
+ else:
69
+ # the file is not properly defined, returning
70
+ # an empty dict
71
+ return {}
72
+ for server in _servers:
73
+ current = {'server': server}
74
+ current['username'] = config.get(server, 'username')
75
+
76
+ # optional params
77
+ for key, default in (('repository',
78
+ self.DEFAULT_REPOSITORY),
79
+ ('realm', self.DEFAULT_REALM),
80
+ ('password', None)):
81
+ if config.has_option(server, key):
82
+ current[key] = config.get(server, key)
83
+ else:
84
+ current[key] = default
85
+
86
+ # work around people having "repository" for the "pypi"
87
+ # section of their config set to the HTTP (rather than
88
+ # HTTPS) URL
89
+ if (server == 'pypi' and
90
+ repository in (self.DEFAULT_REPOSITORY, 'pypi')):
91
+ current['repository'] = self.DEFAULT_REPOSITORY
92
+ return current
93
+
94
+ if (current['server'] == repository or
95
+ current['repository'] == repository):
96
+ return current
97
+ elif 'server-login' in sections:
98
+ # old format
99
+ server = 'server-login'
100
+ if config.has_option(server, 'repository'):
101
+ repository = config.get(server, 'repository')
102
+ else:
103
+ repository = self.DEFAULT_REPOSITORY
104
+ return {'username': config.get(server, 'username'),
105
+ 'password': config.get(server, 'password'),
106
+ 'repository': repository,
107
+ 'server': server,
108
+ 'realm': self.DEFAULT_REALM}
109
+
110
+ return {}
111
+
112
+ def _read_pypi_response(self, response):
113
+ """Read and decode a PyPI HTTP response."""
114
+ import cgi
115
+ content_type = response.getheader('content-type', 'text/plain')
116
+ encoding = cgi.parse_header(content_type)[1].get('charset', 'ascii')
117
+ return response.read().decode(encoding)
118
+
119
+ def initialize_options(self):
120
+ """Initialize options."""
121
+ self.repository = None
122
+ self.realm = None
123
+ self.show_response = 0
124
+
125
+ def finalize_options(self):
126
+ """Finalizes options."""
127
+ if self.repository is None:
128
+ self.repository = self.DEFAULT_REPOSITORY
129
+ if self.realm is None:
130
+ self.realm = self.DEFAULT_REALM
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/dir_util.py ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """distutils.dir_util
2
+
3
+ Utility functions for manipulating directories and directory trees."""
4
+
5
+ import os
6
+ import errno
7
+ from distutils.errors import DistutilsFileError, DistutilsInternalError
8
+ from distutils import log
9
+
10
+ # cache for by mkpath() -- in addition to cheapening redundant calls,
11
+ # eliminates redundant "creating /foo/bar/baz" messages in dry-run mode
12
+ _path_created = {}
13
+
14
+ # I don't use os.makedirs because a) it's new to Python 1.5.2, and
15
+ # b) it blows up if the directory already exists (I want to silently
16
+ # succeed in that case).
17
+ def mkpath(name, mode=0o777, verbose=1, dry_run=0):
18
+ """Create a directory and any missing ancestor directories.
19
+
20
+ If the directory already exists (or if 'name' is the empty string, which
21
+ means the current directory, which of course exists), then do nothing.
22
+ Raise DistutilsFileError if unable to create some directory along the way
23
+ (eg. some sub-path exists, but is a file rather than a directory).
24
+ If 'verbose' is true, print a one-line summary of each mkdir to stdout.
25
+ Return the list of directories actually created.
26
+ """
27
+
28
+ global _path_created
29
+
30
+ # Detect a common bug -- name is None
31
+ if not isinstance(name, str):
32
+ raise DistutilsInternalError(
33
+ "mkpath: 'name' must be a string (got %r)" % (name,))
34
+
35
+ # XXX what's the better way to handle verbosity? print as we create
36
+ # each directory in the path (the current behaviour), or only announce
37
+ # the creation of the whole path? (quite easy to do the latter since
38
+ # we're not using a recursive algorithm)
39
+
40
+ name = os.path.normpath(name)
41
+ created_dirs = []
42
+ if os.path.isdir(name) or name == '':
43
+ return created_dirs
44
+ if _path_created.get(os.path.abspath(name)):
45
+ return created_dirs
46
+
47
+ (head, tail) = os.path.split(name)
48
+ tails = [tail] # stack of lone dirs to create
49
+
50
+ while head and tail and not os.path.isdir(head):
51
+ (head, tail) = os.path.split(head)
52
+ tails.insert(0, tail) # push next higher dir onto stack
53
+
54
+ # now 'head' contains the deepest directory that already exists
55
+ # (that is, the child of 'head' in 'name' is the highest directory
56
+ # that does *not* exist)
57
+ for d in tails:
58
+ #print "head = %s, d = %s: " % (head, d),
59
+ head = os.path.join(head, d)
60
+ abs_head = os.path.abspath(head)
61
+
62
+ if _path_created.get(abs_head):
63
+ continue
64
+
65
+ if verbose >= 1:
66
+ log.info("creating %s", head)
67
+
68
+ if not dry_run:
69
+ try:
70
+ os.mkdir(head, mode)
71
+ except OSError as exc:
72
+ if not (exc.errno == errno.EEXIST and os.path.isdir(head)):
73
+ raise DistutilsFileError(
74
+ "could not create '%s': %s" % (head, exc.args[-1]))
75
+ created_dirs.append(head)
76
+
77
+ _path_created[abs_head] = 1
78
+ return created_dirs
79
+
80
+ def create_tree(base_dir, files, mode=0o777, verbose=1, dry_run=0):
81
+ """Create all the empty directories under 'base_dir' needed to put 'files'
82
+ there.
83
+
84
+ 'base_dir' is just the name of a directory which doesn't necessarily
85
+ exist yet; 'files' is a list of filenames to be interpreted relative to
86
+ 'base_dir'. 'base_dir' + the directory portion of every file in 'files'
87
+ will be created if it doesn't already exist. 'mode', 'verbose' and
88
+ 'dry_run' flags are as for 'mkpath()'.
89
+ """
90
+ # First get the list of directories to create
91
+ need_dir = set()
92
+ for file in files:
93
+ need_dir.add(os.path.join(base_dir, os.path.dirname(file)))
94
+
95
+ # Now create them
96
+ for dir in sorted(need_dir):
97
+ mkpath(dir, mode, verbose=verbose, dry_run=dry_run)
98
+
99
+ def copy_tree(src, dst, preserve_mode=1, preserve_times=1,
100
+ preserve_symlinks=0, update=0, verbose=1, dry_run=0):
101
+ """Copy an entire directory tree 'src' to a new location 'dst'.
102
+
103
+ Both 'src' and 'dst' must be directory names. If 'src' is not a
104
+ directory, raise DistutilsFileError. If 'dst' does not exist, it is
105
+ created with 'mkpath()'. The end result of the copy is that every
106
+ file in 'src' is copied to 'dst', and directories under 'src' are
107
+ recursively copied to 'dst'. Return the list of files that were
108
+ copied or might have been copied, using their output name. The
109
+ return value is unaffected by 'update' or 'dry_run': it is simply
110
+ the list of all files under 'src', with the names changed to be
111
+ under 'dst'.
112
+
113
+ 'preserve_mode' and 'preserve_times' are the same as for
114
+ 'copy_file'; note that they only apply to regular files, not to
115
+ directories. If 'preserve_symlinks' is true, symlinks will be
116
+ copied as symlinks (on platforms that support them!); otherwise
117
+ (the default), the destination of the symlink will be copied.
118
+ 'update' and 'verbose' are the same as for 'copy_file'.
119
+ """
120
+ from distutils.file_util import copy_file
121
+
122
+ if not dry_run and not os.path.isdir(src):
123
+ raise DistutilsFileError(
124
+ "cannot copy tree '%s': not a directory" % src)
125
+ try:
126
+ names = os.listdir(src)
127
+ except OSError as e:
128
+ if dry_run:
129
+ names = []
130
+ else:
131
+ raise DistutilsFileError(
132
+ "error listing files in '%s': %s" % (src, e.strerror))
133
+
134
+ if not dry_run:
135
+ mkpath(dst, verbose=verbose)
136
+
137
+ outputs = []
138
+
139
+ for n in names:
140
+ src_name = os.path.join(src, n)
141
+ dst_name = os.path.join(dst, n)
142
+
143
+ if n.startswith('.nfs'):
144
+ # skip NFS rename files
145
+ continue
146
+
147
+ if preserve_symlinks and os.path.islink(src_name):
148
+ link_dest = os.readlink(src_name)
149
+ if verbose >= 1:
150
+ log.info("linking %s -> %s", dst_name, link_dest)
151
+ if not dry_run:
152
+ os.symlink(link_dest, dst_name)
153
+ outputs.append(dst_name)
154
+
155
+ elif os.path.isdir(src_name):
156
+ outputs.extend(
157
+ copy_tree(src_name, dst_name, preserve_mode,
158
+ preserve_times, preserve_symlinks, update,
159
+ verbose=verbose, dry_run=dry_run))
160
+ else:
161
+ copy_file(src_name, dst_name, preserve_mode,
162
+ preserve_times, update, verbose=verbose,
163
+ dry_run=dry_run)
164
+ outputs.append(dst_name)
165
+
166
+ return outputs
167
+
168
+ def _build_cmdtuple(path, cmdtuples):
169
+ """Helper for remove_tree()."""
170
+ for f in os.listdir(path):
171
+ real_f = os.path.join(path,f)
172
+ if os.path.isdir(real_f) and not os.path.islink(real_f):
173
+ _build_cmdtuple(real_f, cmdtuples)
174
+ else:
175
+ cmdtuples.append((os.remove, real_f))
176
+ cmdtuples.append((os.rmdir, path))
177
+
178
+ def remove_tree(directory, verbose=1, dry_run=0):
179
+ """Recursively remove an entire directory tree.
180
+
181
+ Any errors are ignored (apart from being reported to stdout if 'verbose'
182
+ is true).
183
+ """
184
+ global _path_created
185
+
186
+ if verbose >= 1:
187
+ log.info("removing '%s' (and everything under it)", directory)
188
+ if dry_run:
189
+ return
190
+ cmdtuples = []
191
+ _build_cmdtuple(directory, cmdtuples)
192
+ for cmd in cmdtuples:
193
+ try:
194
+ cmd[0](cmd[1])
195
+ # remove dir from cache if it's already there
196
+ abspath = os.path.abspath(cmd[1])
197
+ if abspath in _path_created:
198
+ del _path_created[abspath]
199
+ except OSError as exc:
200
+ log.warn("error removing %s: %s", directory, exc)
201
+
202
+ def ensure_relative(path):
203
+ """Take the full path 'path', and make it a relative path.
204
+
205
+ This is useful to make 'path' the second argument to os.path.join().
206
+ """
207
+ drive, path = os.path.splitdrive(path)
208
+ if path[0:1] == os.sep:
209
+ path = drive + path[1:]
210
+ return path
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/extension.py ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """distutils.extension
2
+
3
+ Provides the Extension class, used to describe C/C++ extension
4
+ modules in setup scripts."""
5
+
6
+ import os
7
+ import warnings
8
+
9
+ # This class is really only used by the "build_ext" command, so it might
10
+ # make sense to put it in distutils.command.build_ext. However, that
11
+ # module is already big enough, and I want to make this class a bit more
12
+ # complex to simplify some common cases ("foo" module in "foo.c") and do
13
+ # better error-checking ("foo.c" actually exists).
14
+ #
15
+ # Also, putting this in build_ext.py means every setup script would have to
16
+ # import that large-ish module (indirectly, through distutils.core) in
17
+ # order to do anything.
18
+
19
+ class Extension:
20
+ """Just a collection of attributes that describes an extension
21
+ module and everything needed to build it (hopefully in a portable
22
+ way, but there are hooks that let you be as unportable as you need).
23
+
24
+ Instance attributes:
25
+ name : string
26
+ the full name of the extension, including any packages -- ie.
27
+ *not* a filename or pathname, but Python dotted name
28
+ sources : [string]
29
+ list of source filenames, relative to the distribution root
30
+ (where the setup script lives), in Unix form (slash-separated)
31
+ for portability. Source files may be C, C++, SWIG (.i),
32
+ platform-specific resource files, or whatever else is recognized
33
+ by the "build_ext" command as source for a Python extension.
34
+ include_dirs : [string]
35
+ list of directories to search for C/C++ header files (in Unix
36
+ form for portability)
37
+ define_macros : [(name : string, value : string|None)]
38
+ list of macros to define; each macro is defined using a 2-tuple,
39
+ where 'value' is either the string to define it to or None to
40
+ define it without a particular value (equivalent of "#define
41
+ FOO" in source or -DFOO on Unix C compiler command line)
42
+ undef_macros : [string]
43
+ list of macros to undefine explicitly
44
+ library_dirs : [string]
45
+ list of directories to search for C/C++ libraries at link time
46
+ libraries : [string]
47
+ list of library names (not filenames or paths) to link against
48
+ runtime_library_dirs : [string]
49
+ list of directories to search for C/C++ libraries at run time
50
+ (for shared extensions, this is when the extension is loaded)
51
+ extra_objects : [string]
52
+ list of extra files to link with (eg. object files not implied
53
+ by 'sources', static library that must be explicitly specified,
54
+ binary resource files, etc.)
55
+ extra_compile_args : [string]
56
+ any extra platform- and compiler-specific information to use
57
+ when compiling the source files in 'sources'. For platforms and
58
+ compilers where "command line" makes sense, this is typically a
59
+ list of command-line arguments, but for other platforms it could
60
+ be anything.
61
+ extra_link_args : [string]
62
+ any extra platform- and compiler-specific information to use
63
+ when linking object files together to create the extension (or
64
+ to create a new static Python interpreter). Similar
65
+ interpretation as for 'extra_compile_args'.
66
+ export_symbols : [string]
67
+ list of symbols to be exported from a shared extension. Not
68
+ used on all platforms, and not generally necessary for Python
69
+ extensions, which typically export exactly one symbol: "init" +
70
+ extension_name.
71
+ swig_opts : [string]
72
+ any extra options to pass to SWIG if a source file has the .i
73
+ extension.
74
+ depends : [string]
75
+ list of files that the extension depends on
76
+ language : string
77
+ extension language (i.e. "c", "c++", "objc"). Will be detected
78
+ from the source extensions if not provided.
79
+ optional : boolean
80
+ specifies that a build failure in the extension should not abort the
81
+ build process, but simply not install the failing extension.
82
+ """
83
+
84
+ # When adding arguments to this constructor, be sure to update
85
+ # setup_keywords in core.py.
86
+ def __init__(self, name, sources,
87
+ include_dirs=None,
88
+ define_macros=None,
89
+ undef_macros=None,
90
+ library_dirs=None,
91
+ libraries=None,
92
+ runtime_library_dirs=None,
93
+ extra_objects=None,
94
+ extra_compile_args=None,
95
+ extra_link_args=None,
96
+ export_symbols=None,
97
+ swig_opts = None,
98
+ depends=None,
99
+ language=None,
100
+ optional=None,
101
+ **kw # To catch unknown keywords
102
+ ):
103
+ if not isinstance(name, str):
104
+ raise AssertionError("'name' must be a string")
105
+ if not (isinstance(sources, list) and
106
+ all(isinstance(v, str) for v in sources)):
107
+ raise AssertionError("'sources' must be a list of strings")
108
+
109
+ self.name = name
110
+ self.sources = sources
111
+ self.include_dirs = include_dirs or []
112
+ self.define_macros = define_macros or []
113
+ self.undef_macros = undef_macros or []
114
+ self.library_dirs = library_dirs or []
115
+ self.libraries = libraries or []
116
+ self.runtime_library_dirs = runtime_library_dirs or []
117
+ self.extra_objects = extra_objects or []
118
+ self.extra_compile_args = extra_compile_args or []
119
+ self.extra_link_args = extra_link_args or []
120
+ self.export_symbols = export_symbols or []
121
+ self.swig_opts = swig_opts or []
122
+ self.depends = depends or []
123
+ self.language = language
124
+ self.optional = optional
125
+
126
+ # If there are unknown keyword options, warn about them
127
+ if len(kw) > 0:
128
+ options = [repr(option) for option in kw]
129
+ options = ', '.join(sorted(options))
130
+ msg = "Unknown Extension options: %s" % options
131
+ warnings.warn(msg)
132
+
133
+ def __repr__(self):
134
+ return '<%s.%s(%r) at %#x>' % (
135
+ self.__class__.__module__,
136
+ self.__class__.__qualname__,
137
+ self.name,
138
+ id(self))
139
+
140
+
141
+ def read_setup_file(filename):
142
+ """Reads a Setup file and returns Extension instances."""
143
+ from distutils.sysconfig import (parse_makefile, expand_makefile_vars,
144
+ _variable_rx)
145
+
146
+ from distutils.text_file import TextFile
147
+ from distutils.util import split_quoted
148
+
149
+ # First pass over the file to gather "VAR = VALUE" assignments.
150
+ vars = parse_makefile(filename)
151
+
152
+ # Second pass to gobble up the real content: lines of the form
153
+ # <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...]
154
+ file = TextFile(filename,
155
+ strip_comments=1, skip_blanks=1, join_lines=1,
156
+ lstrip_ws=1, rstrip_ws=1)
157
+ try:
158
+ extensions = []
159
+
160
+ while True:
161
+ line = file.readline()
162
+ if line is None: # eof
163
+ break
164
+ if _variable_rx.match(line): # VAR=VALUE, handled in first pass
165
+ continue
166
+
167
+ if line[0] == line[-1] == "*":
168
+ file.warn("'%s' lines not handled yet" % line)
169
+ continue
170
+
171
+ line = expand_makefile_vars(line, vars)
172
+ words = split_quoted(line)
173
+
174
+ # NB. this parses a slightly different syntax than the old
175
+ # makesetup script: here, there must be exactly one extension per
176
+ # line, and it must be the first word of the line. I have no idea
177
+ # why the old syntax supported multiple extensions per line, as
178
+ # they all wind up being the same.
179
+
180
+ module = words[0]
181
+ ext = Extension(module, [])
182
+ append_next_word = None
183
+
184
+ for word in words[1:]:
185
+ if append_next_word is not None:
186
+ append_next_word.append(word)
187
+ append_next_word = None
188
+ continue
189
+
190
+ suffix = os.path.splitext(word)[1]
191
+ switch = word[0:2] ; value = word[2:]
192
+
193
+ if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"):
194
+ # hmm, should we do something about C vs. C++ sources?
195
+ # or leave it up to the CCompiler implementation to
196
+ # worry about?
197
+ ext.sources.append(word)
198
+ elif switch == "-I":
199
+ ext.include_dirs.append(value)
200
+ elif switch == "-D":
201
+ equals = value.find("=")
202
+ if equals == -1: # bare "-DFOO" -- no value
203
+ ext.define_macros.append((value, None))
204
+ else: # "-DFOO=blah"
205
+ ext.define_macros.append((value[0:equals],
206
+ value[equals+2:]))
207
+ elif switch == "-U":
208
+ ext.undef_macros.append(value)
209
+ elif switch == "-C": # only here 'cause makesetup has it!
210
+ ext.extra_compile_args.append(word)
211
+ elif switch == "-l":
212
+ ext.libraries.append(value)
213
+ elif switch == "-L":
214
+ ext.library_dirs.append(value)
215
+ elif switch == "-R":
216
+ ext.runtime_library_dirs.append(value)
217
+ elif word == "-rpath":
218
+ append_next_word = ext.runtime_library_dirs
219
+ elif word == "-Xlinker":
220
+ append_next_word = ext.extra_link_args
221
+ elif word == "-Xcompiler":
222
+ append_next_word = ext.extra_compile_args
223
+ elif switch == "-u":
224
+ ext.extra_link_args.append(word)
225
+ if not value:
226
+ append_next_word = ext.extra_link_args
227
+ elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
228
+ # NB. a really faithful emulation of makesetup would
229
+ # append a .o file to extra_objects only if it
230
+ # had a slash in it; otherwise, it would s/.o/.c/
231
+ # and append it to sources. Hmmmm.
232
+ ext.extra_objects.append(word)
233
+ else:
234
+ file.warn("unrecognized argument '%s'" % word)
235
+
236
+ extensions.append(ext)
237
+ finally:
238
+ file.close()
239
+
240
+ return extensions
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/log.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A simple log mechanism styled after PEP 282."""
2
+
3
+ # The class here is styled after PEP 282 so that it could later be
4
+ # replaced with a standard Python logging implementation.
5
+
6
+ DEBUG = 1
7
+ INFO = 2
8
+ WARN = 3
9
+ ERROR = 4
10
+ FATAL = 5
11
+
12
+ import sys
13
+
14
+ class Log:
15
+
16
+ def __init__(self, threshold=WARN):
17
+ self.threshold = threshold
18
+
19
+ def _log(self, level, msg, args):
20
+ if level not in (DEBUG, INFO, WARN, ERROR, FATAL):
21
+ raise ValueError('%s wrong log level' % str(level))
22
+
23
+ if level >= self.threshold:
24
+ if args:
25
+ msg = msg % args
26
+ if level in (WARN, ERROR, FATAL):
27
+ stream = sys.stderr
28
+ else:
29
+ stream = sys.stdout
30
+ try:
31
+ stream.write('%s\n' % msg)
32
+ except UnicodeEncodeError:
33
+ # emulate backslashreplace error handler
34
+ encoding = stream.encoding
35
+ msg = msg.encode(encoding, "backslashreplace").decode(encoding)
36
+ stream.write('%s\n' % msg)
37
+ stream.flush()
38
+
39
+ def log(self, level, msg, *args):
40
+ self._log(level, msg, args)
41
+
42
+ def debug(self, msg, *args):
43
+ self._log(DEBUG, msg, args)
44
+
45
+ def info(self, msg, *args):
46
+ self._log(INFO, msg, args)
47
+
48
+ def warn(self, msg, *args):
49
+ self._log(WARN, msg, args)
50
+
51
+ def error(self, msg, *args):
52
+ self._log(ERROR, msg, args)
53
+
54
+ def fatal(self, msg, *args):
55
+ self._log(FATAL, msg, args)
56
+
57
+ _global_log = Log()
58
+ log = _global_log.log
59
+ debug = _global_log.debug
60
+ info = _global_log.info
61
+ warn = _global_log.warn
62
+ error = _global_log.error
63
+ fatal = _global_log.fatal
64
+
65
+ def set_threshold(level):
66
+ # return the old threshold for use from tests
67
+ old = _global_log.threshold
68
+ _global_log.threshold = level
69
+ return old
70
+
71
+ def set_verbosity(v):
72
+ if v <= 0:
73
+ set_threshold(WARN)
74
+ elif v == 1:
75
+ set_threshold(INFO)
76
+ elif v >= 2:
77
+ set_threshold(DEBUG)
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/msvc9compiler.py ADDED
@@ -0,0 +1,789 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """distutils.msvc9compiler
2
+
3
+ Contains MSVCCompiler, an implementation of the abstract CCompiler class
4
+ for the Microsoft Visual Studio 2008.
5
+
6
+ The module is compatible with VS 2005 and VS 2008. You can find legacy support
7
+ for older versions of VS in distutils.msvccompiler.
8
+ """
9
+
10
+ # Written by Perry Stoll
11
+ # hacked by Robin Becker and Thomas Heller to do a better job of
12
+ # finding DevStudio (through the registry)
13
+ # ported to VS2005 and VS 2008 by Christian Heimes
14
+
15
+ import os
16
+ import subprocess
17
+ import sys
18
+ import re
19
+
20
+ from distutils.errors import DistutilsExecError, DistutilsPlatformError, \
21
+ CompileError, LibError, LinkError
22
+ from distutils.ccompiler import CCompiler, gen_preprocess_options, \
23
+ gen_lib_options
24
+ from distutils import log
25
+ from distutils.util import get_platform
26
+
27
+ import winreg
28
+
29
+ RegOpenKeyEx = winreg.OpenKeyEx
30
+ RegEnumKey = winreg.EnumKey
31
+ RegEnumValue = winreg.EnumValue
32
+ RegError = winreg.error
33
+
34
+ HKEYS = (winreg.HKEY_USERS,
35
+ winreg.HKEY_CURRENT_USER,
36
+ winreg.HKEY_LOCAL_MACHINE,
37
+ winreg.HKEY_CLASSES_ROOT)
38
+
39
+ NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32)
40
+ if NATIVE_WIN64:
41
+ # Visual C++ is a 32-bit application, so we need to look in
42
+ # the corresponding registry branch, if we're running a
43
+ # 64-bit Python on Win64
44
+ VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f"
45
+ WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows"
46
+ NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework"
47
+ else:
48
+ VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
49
+ WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
50
+ NET_BASE = r"Software\Microsoft\.NETFramework"
51
+
52
+ # A map keyed by get_platform() return values to values accepted by
53
+ # 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is
54
+ # the param to cross-compile on x86 targeting amd64.)
55
+ PLAT_TO_VCVARS = {
56
+ 'win32' : 'x86',
57
+ 'win-amd64' : 'amd64',
58
+ }
59
+
60
+ class Reg:
61
+ """Helper class to read values from the registry
62
+ """
63
+
64
+ def get_value(cls, path, key):
65
+ for base in HKEYS:
66
+ d = cls.read_values(base, path)
67
+ if d and key in d:
68
+ return d[key]
69
+ raise KeyError(key)
70
+ get_value = classmethod(get_value)
71
+
72
+ def read_keys(cls, base, key):
73
+ """Return list of registry keys."""
74
+ try:
75
+ handle = RegOpenKeyEx(base, key)
76
+ except RegError:
77
+ return None
78
+ L = []
79
+ i = 0
80
+ while True:
81
+ try:
82
+ k = RegEnumKey(handle, i)
83
+ except RegError:
84
+ break
85
+ L.append(k)
86
+ i += 1
87
+ return L
88
+ read_keys = classmethod(read_keys)
89
+
90
+ def read_values(cls, base, key):
91
+ """Return dict of registry keys and values.
92
+
93
+ All names are converted to lowercase.
94
+ """
95
+ try:
96
+ handle = RegOpenKeyEx(base, key)
97
+ except RegError:
98
+ return None
99
+ d = {}
100
+ i = 0
101
+ while True:
102
+ try:
103
+ name, value, type = RegEnumValue(handle, i)
104
+ except RegError:
105
+ break
106
+ name = name.lower()
107
+ d[cls.convert_mbcs(name)] = cls.convert_mbcs(value)
108
+ i += 1
109
+ return d
110
+ read_values = classmethod(read_values)
111
+
112
+ def convert_mbcs(s):
113
+ dec = getattr(s, "decode", None)
114
+ if dec is not None:
115
+ try:
116
+ s = dec("mbcs")
117
+ except UnicodeError:
118
+ pass
119
+ return s
120
+ convert_mbcs = staticmethod(convert_mbcs)
121
+
122
+ class MacroExpander:
123
+
124
+ def __init__(self, version):
125
+ self.macros = {}
126
+ self.vsbase = VS_BASE % version
127
+ self.load_macros(version)
128
+
129
+ def set_macro(self, macro, path, key):
130
+ self.macros["$(%s)" % macro] = Reg.get_value(path, key)
131
+
132
+ def load_macros(self, version):
133
+ self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir")
134
+ self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir")
135
+ self.set_macro("FrameworkDir", NET_BASE, "installroot")
136
+ try:
137
+ if version >= 8.0:
138
+ self.set_macro("FrameworkSDKDir", NET_BASE,
139
+ "sdkinstallrootv2.0")
140
+ else:
141
+ raise KeyError("sdkinstallrootv2.0")
142
+ except KeyError:
143
+ raise DistutilsPlatformError(
144
+ """Python was built with Visual Studio 2008;
145
+ extensions must be built with a compiler than can generate compatible binaries.
146
+ Visual Studio 2008 was not found on this system. If you have Cygwin installed,
147
+ you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
148
+
149
+ if version >= 9.0:
150
+ self.set_macro("FrameworkVersion", self.vsbase, "clr version")
151
+ self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder")
152
+ else:
153
+ p = r"Software\Microsoft\NET Framework Setup\Product"
154
+ for base in HKEYS:
155
+ try:
156
+ h = RegOpenKeyEx(base, p)
157
+ except RegError:
158
+ continue
159
+ key = RegEnumKey(h, 0)
160
+ d = Reg.get_value(base, r"%s\%s" % (p, key))
161
+ self.macros["$(FrameworkVersion)"] = d["version"]
162
+
163
+ def sub(self, s):
164
+ for k, v in self.macros.items():
165
+ s = s.replace(k, v)
166
+ return s
167
+
168
+ def get_build_version():
169
+ """Return the version of MSVC that was used to build Python.
170
+
171
+ For Python 2.3 and up, the version number is included in
172
+ sys.version. For earlier versions, assume the compiler is MSVC 6.
173
+ """
174
+ prefix = "MSC v."
175
+ i = sys.version.find(prefix)
176
+ if i == -1:
177
+ return 6
178
+ i = i + len(prefix)
179
+ s, rest = sys.version[i:].split(" ", 1)
180
+ majorVersion = int(s[:-2]) - 6
181
+ if majorVersion >= 13:
182
+ # v13 was skipped and should be v14
183
+ majorVersion += 1
184
+ minorVersion = int(s[2:3]) / 10.0
185
+ # I don't think paths are affected by minor version in version 6
186
+ if majorVersion == 6:
187
+ minorVersion = 0
188
+ if majorVersion >= 6:
189
+ return majorVersion + minorVersion
190
+ # else we don't know what version of the compiler this is
191
+ return None
192
+
193
+ def normalize_and_reduce_paths(paths):
194
+ """Return a list of normalized paths with duplicates removed.
195
+
196
+ The current order of paths is maintained.
197
+ """
198
+ # Paths are normalized so things like: /a and /a/ aren't both preserved.
199
+ reduced_paths = []
200
+ for p in paths:
201
+ np = os.path.normpath(p)
202
+ # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
203
+ if np not in reduced_paths:
204
+ reduced_paths.append(np)
205
+ return reduced_paths
206
+
207
+ def removeDuplicates(variable):
208
+ """Remove duplicate values of an environment variable.
209
+ """
210
+ oldList = variable.split(os.pathsep)
211
+ newList = []
212
+ for i in oldList:
213
+ if i not in newList:
214
+ newList.append(i)
215
+ newVariable = os.pathsep.join(newList)
216
+ return newVariable
217
+
218
+ def find_vcvarsall(version):
219
+ """Find the vcvarsall.bat file
220
+
221
+ At first it tries to find the productdir of VS 2008 in the registry. If
222
+ that fails it falls back to the VS90COMNTOOLS env var.
223
+ """
224
+ vsbase = VS_BASE % version
225
+ try:
226
+ productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
227
+ "productdir")
228
+ except KeyError:
229
+ log.debug("Unable to find productdir in registry")
230
+ productdir = None
231
+
232
+ if not productdir or not os.path.isdir(productdir):
233
+ toolskey = "VS%0.f0COMNTOOLS" % version
234
+ toolsdir = os.environ.get(toolskey, None)
235
+
236
+ if toolsdir and os.path.isdir(toolsdir):
237
+ productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
238
+ productdir = os.path.abspath(productdir)
239
+ if not os.path.isdir(productdir):
240
+ log.debug("%s is not a valid directory" % productdir)
241
+ return None
242
+ else:
243
+ log.debug("Env var %s is not set or invalid" % toolskey)
244
+ if not productdir:
245
+ log.debug("No productdir found")
246
+ return None
247
+ vcvarsall = os.path.join(productdir, "vcvarsall.bat")
248
+ if os.path.isfile(vcvarsall):
249
+ return vcvarsall
250
+ log.debug("Unable to find vcvarsall.bat")
251
+ return None
252
+
253
+ def query_vcvarsall(version, arch="x86"):
254
+ """Launch vcvarsall.bat and read the settings from its environment
255
+ """
256
+ vcvarsall = find_vcvarsall(version)
257
+ interesting = {"include", "lib", "libpath", "path"}
258
+ result = {}
259
+
260
+ if vcvarsall is None:
261
+ raise DistutilsPlatformError("Unable to find vcvarsall.bat")
262
+ log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version)
263
+ popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch),
264
+ stdout=subprocess.PIPE,
265
+ stderr=subprocess.PIPE)
266
+ try:
267
+ stdout, stderr = popen.communicate()
268
+ if popen.wait() != 0:
269
+ raise DistutilsPlatformError(stderr.decode("mbcs"))
270
+
271
+ stdout = stdout.decode("mbcs")
272
+ for line in stdout.split("\n"):
273
+ line = Reg.convert_mbcs(line)
274
+ if '=' not in line:
275
+ continue
276
+ line = line.strip()
277
+ key, value = line.split('=', 1)
278
+ key = key.lower()
279
+ if key in interesting:
280
+ if value.endswith(os.pathsep):
281
+ value = value[:-1]
282
+ result[key] = removeDuplicates(value)
283
+
284
+ finally:
285
+ popen.stdout.close()
286
+ popen.stderr.close()
287
+
288
+ if len(result) != len(interesting):
289
+ raise ValueError(str(list(result.keys())))
290
+
291
+ return result
292
+
293
+ # More globals
294
+ VERSION = get_build_version()
295
+ if VERSION < 8.0:
296
+ raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
297
+ # MACROS = MacroExpander(VERSION)
298
+
299
+ class MSVCCompiler(CCompiler) :
300
+ """Concrete class that implements an interface to Microsoft Visual C++,
301
+ as defined by the CCompiler abstract class."""
302
+
303
+ compiler_type = 'msvc'
304
+
305
+ # Just set this so CCompiler's constructor doesn't barf. We currently
306
+ # don't use the 'set_executables()' bureaucracy provided by CCompiler,
307
+ # as it really isn't necessary for this sort of single-compiler class.
308
+ # Would be nice to have a consistent interface with UnixCCompiler,
309
+ # though, so it's worth thinking about.
310
+ executables = {}
311
+
312
+ # Private class data (need to distinguish C from C++ source for compiler)
313
+ _c_extensions = ['.c']
314
+ _cpp_extensions = ['.cc', '.cpp', '.cxx']
315
+ _rc_extensions = ['.rc']
316
+ _mc_extensions = ['.mc']
317
+
318
+ # Needed for the filename generation methods provided by the
319
+ # base class, CCompiler.
320
+ src_extensions = (_c_extensions + _cpp_extensions +
321
+ _rc_extensions + _mc_extensions)
322
+ res_extension = '.res'
323
+ obj_extension = '.obj'
324
+ static_lib_extension = '.lib'
325
+ shared_lib_extension = '.dll'
326
+ static_lib_format = shared_lib_format = '%s%s'
327
+ exe_extension = '.exe'
328
+
329
+ def __init__(self, verbose=0, dry_run=0, force=0):
330
+ CCompiler.__init__ (self, verbose, dry_run, force)
331
+ self.__version = VERSION
332
+ self.__root = r"Software\Microsoft\VisualStudio"
333
+ # self.__macros = MACROS
334
+ self.__paths = []
335
+ # target platform (.plat_name is consistent with 'bdist')
336
+ self.plat_name = None
337
+ self.__arch = None # deprecated name
338
+ self.initialized = False
339
+
340
+ def initialize(self, plat_name=None):
341
+ # multi-init means we would need to check platform same each time...
342
+ assert not self.initialized, "don't init multiple times"
343
+ if plat_name is None:
344
+ plat_name = get_platform()
345
+ # sanity check for platforms to prevent obscure errors later.
346
+ ok_plats = 'win32', 'win-amd64'
347
+ if plat_name not in ok_plats:
348
+ raise DistutilsPlatformError("--plat-name must be one of %s" %
349
+ (ok_plats,))
350
+
351
+ if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
352
+ # Assume that the SDK set up everything alright; don't try to be
353
+ # smarter
354
+ self.cc = "cl.exe"
355
+ self.linker = "link.exe"
356
+ self.lib = "lib.exe"
357
+ self.rc = "rc.exe"
358
+ self.mc = "mc.exe"
359
+ else:
360
+ # On x86, 'vcvars32.bat amd64' creates an env that doesn't work;
361
+ # to cross compile, you use 'x86_amd64'.
362
+ # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
363
+ # compile use 'x86' (ie, it runs the x86 compiler directly)
364
+ if plat_name == get_platform() or plat_name == 'win32':
365
+ # native build or cross-compile to win32
366
+ plat_spec = PLAT_TO_VCVARS[plat_name]
367
+ else:
368
+ # cross compile from win32 -> some 64bit
369
+ plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \
370
+ PLAT_TO_VCVARS[plat_name]
371
+
372
+ vc_env = query_vcvarsall(VERSION, plat_spec)
373
+
374
+ self.__paths = vc_env['path'].split(os.pathsep)
375
+ os.environ['lib'] = vc_env['lib']
376
+ os.environ['include'] = vc_env['include']
377
+
378
+ if len(self.__paths) == 0:
379
+ raise DistutilsPlatformError("Python was built with %s, "
380
+ "and extensions need to be built with the same "
381
+ "version of the compiler, but it isn't installed."
382
+ % self.__product)
383
+
384
+ self.cc = self.find_exe("cl.exe")
385
+ self.linker = self.find_exe("link.exe")
386
+ self.lib = self.find_exe("lib.exe")
387
+ self.rc = self.find_exe("rc.exe") # resource compiler
388
+ self.mc = self.find_exe("mc.exe") # message compiler
389
+ #self.set_path_env_var('lib')
390
+ #self.set_path_env_var('include')
391
+
392
+ # extend the MSVC path with the current path
393
+ try:
394
+ for p in os.environ['path'].split(';'):
395
+ self.__paths.append(p)
396
+ except KeyError:
397
+ pass
398
+ self.__paths = normalize_and_reduce_paths(self.__paths)
399
+ os.environ['path'] = ";".join(self.__paths)
400
+
401
+ self.preprocess_options = None
402
+ if self.__arch == "x86":
403
+ self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3',
404
+ '/DNDEBUG']
405
+ self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3',
406
+ '/Z7', '/D_DEBUG']
407
+ else:
408
+ # Win64
409
+ self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
410
+ '/DNDEBUG']
411
+ self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
412
+ '/Z7', '/D_DEBUG']
413
+
414
+ self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
415
+ if self.__version >= 7:
416
+ self.ldflags_shared_debug = [
417
+ '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
418
+ ]
419
+ self.ldflags_static = [ '/nologo']
420
+
421
+ self.initialized = True
422
+
423
+ # -- Worker methods ------------------------------------------------
424
+
425
+ def object_filenames(self,
426
+ source_filenames,
427
+ strip_dir=0,
428
+ output_dir=''):
429
+ # Copied from ccompiler.py, extended to return .res as 'object'-file
430
+ # for .rc input file
431
+ if output_dir is None: output_dir = ''
432
+ obj_names = []
433
+ for src_name in source_filenames:
434
+ (base, ext) = os.path.splitext (src_name)
435
+ base = os.path.splitdrive(base)[1] # Chop off the drive
436
+ base = base[os.path.isabs(base):] # If abs, chop off leading /
437
+ if ext not in self.src_extensions:
438
+ # Better to raise an exception instead of silently continuing
439
+ # and later complain about sources and targets having
440
+ # different lengths
441
+ raise CompileError ("Don't know how to compile %s" % src_name)
442
+ if strip_dir:
443
+ base = os.path.basename (base)
444
+ if ext in self._rc_extensions:
445
+ obj_names.append (os.path.join (output_dir,
446
+ base + self.res_extension))
447
+ elif ext in self._mc_extensions:
448
+ obj_names.append (os.path.join (output_dir,
449
+ base + self.res_extension))
450
+ else:
451
+ obj_names.append (os.path.join (output_dir,
452
+ base + self.obj_extension))
453
+ return obj_names
454
+
455
+
456
+ def compile(self, sources,
457
+ output_dir=None, macros=None, include_dirs=None, debug=0,
458
+ extra_preargs=None, extra_postargs=None, depends=None):
459
+
460
+ if not self.initialized:
461
+ self.initialize()
462
+ compile_info = self._setup_compile(output_dir, macros, include_dirs,
463
+ sources, depends, extra_postargs)
464
+ macros, objects, extra_postargs, pp_opts, build = compile_info
465
+
466
+ compile_opts = extra_preargs or []
467
+ compile_opts.append ('/c')
468
+ if debug:
469
+ compile_opts.extend(self.compile_options_debug)
470
+ else:
471
+ compile_opts.extend(self.compile_options)
472
+
473
+ for obj in objects:
474
+ try:
475
+ src, ext = build[obj]
476
+ except KeyError:
477
+ continue
478
+ if debug:
479
+ # pass the full pathname to MSVC in debug mode,
480
+ # this allows the debugger to find the source file
481
+ # without asking the user to browse for it
482
+ src = os.path.abspath(src)
483
+
484
+ if ext in self._c_extensions:
485
+ input_opt = "/Tc" + src
486
+ elif ext in self._cpp_extensions:
487
+ input_opt = "/Tp" + src
488
+ elif ext in self._rc_extensions:
489
+ # compile .RC to .RES file
490
+ input_opt = src
491
+ output_opt = "/fo" + obj
492
+ try:
493
+ self.spawn([self.rc] + pp_opts +
494
+ [output_opt] + [input_opt])
495
+ except DistutilsExecError as msg:
496
+ raise CompileError(msg)
497
+ continue
498
+ elif ext in self._mc_extensions:
499
+ # Compile .MC to .RC file to .RES file.
500
+ # * '-h dir' specifies the directory for the
501
+ # generated include file
502
+ # * '-r dir' specifies the target directory of the
503
+ # generated RC file and the binary message resource
504
+ # it includes
505
+ #
506
+ # For now (since there are no options to change this),
507
+ # we use the source-directory for the include file and
508
+ # the build directory for the RC file and message
509
+ # resources. This works at least for win32all.
510
+ h_dir = os.path.dirname(src)
511
+ rc_dir = os.path.dirname(obj)
512
+ try:
513
+ # first compile .MC to .RC and .H file
514
+ self.spawn([self.mc] +
515
+ ['-h', h_dir, '-r', rc_dir] + [src])
516
+ base, _ = os.path.splitext (os.path.basename (src))
517
+ rc_file = os.path.join (rc_dir, base + '.rc')
518
+ # then compile .RC to .RES file
519
+ self.spawn([self.rc] +
520
+ ["/fo" + obj] + [rc_file])
521
+
522
+ except DistutilsExecError as msg:
523
+ raise CompileError(msg)
524
+ continue
525
+ else:
526
+ # how to handle this file?
527
+ raise CompileError("Don't know how to compile %s to %s"
528
+ % (src, obj))
529
+
530
+ output_opt = "/Fo" + obj
531
+ try:
532
+ self.spawn([self.cc] + compile_opts + pp_opts +
533
+ [input_opt, output_opt] +
534
+ extra_postargs)
535
+ except DistutilsExecError as msg:
536
+ raise CompileError(msg)
537
+
538
+ return objects
539
+
540
+
541
+ def create_static_lib(self,
542
+ objects,
543
+ output_libname,
544
+ output_dir=None,
545
+ debug=0,
546
+ target_lang=None):
547
+
548
+ if not self.initialized:
549
+ self.initialize()
550
+ (objects, output_dir) = self._fix_object_args(objects, output_dir)
551
+ output_filename = self.library_filename(output_libname,
552
+ output_dir=output_dir)
553
+
554
+ if self._need_link(objects, output_filename):
555
+ lib_args = objects + ['/OUT:' + output_filename]
556
+ if debug:
557
+ pass # XXX what goes here?
558
+ try:
559
+ self.spawn([self.lib] + lib_args)
560
+ except DistutilsExecError as msg:
561
+ raise LibError(msg)
562
+ else:
563
+ log.debug("skipping %s (up-to-date)", output_filename)
564
+
565
+
566
+ def link(self,
567
+ target_desc,
568
+ objects,
569
+ output_filename,
570
+ output_dir=None,
571
+ libraries=None,
572
+ library_dirs=None,
573
+ runtime_library_dirs=None,
574
+ export_symbols=None,
575
+ debug=0,
576
+ extra_preargs=None,
577
+ extra_postargs=None,
578
+ build_temp=None,
579
+ target_lang=None):
580
+
581
+ if not self.initialized:
582
+ self.initialize()
583
+ (objects, output_dir) = self._fix_object_args(objects, output_dir)
584
+ fixed_args = self._fix_lib_args(libraries, library_dirs,
585
+ runtime_library_dirs)
586
+ (libraries, library_dirs, runtime_library_dirs) = fixed_args
587
+
588
+ if runtime_library_dirs:
589
+ self.warn ("I don't know what to do with 'runtime_library_dirs': "
590
+ + str (runtime_library_dirs))
591
+
592
+ lib_opts = gen_lib_options(self,
593
+ library_dirs, runtime_library_dirs,
594
+ libraries)
595
+ if output_dir is not None:
596
+ output_filename = os.path.join(output_dir, output_filename)
597
+
598
+ if self._need_link(objects, output_filename):
599
+ if target_desc == CCompiler.EXECUTABLE:
600
+ if debug:
601
+ ldflags = self.ldflags_shared_debug[1:]
602
+ else:
603
+ ldflags = self.ldflags_shared[1:]
604
+ else:
605
+ if debug:
606
+ ldflags = self.ldflags_shared_debug
607
+ else:
608
+ ldflags = self.ldflags_shared
609
+
610
+ export_opts = []
611
+ for sym in (export_symbols or []):
612
+ export_opts.append("/EXPORT:" + sym)
613
+
614
+ ld_args = (ldflags + lib_opts + export_opts +
615
+ objects + ['/OUT:' + output_filename])
616
+
617
+ # The MSVC linker generates .lib and .exp files, which cannot be
618
+ # suppressed by any linker switches. The .lib files may even be
619
+ # needed! Make sure they are generated in the temporary build
620
+ # directory. Since they have different names for debug and release
621
+ # builds, they can go into the same directory.
622
+ build_temp = os.path.dirname(objects[0])
623
+ if export_symbols is not None:
624
+ (dll_name, dll_ext) = os.path.splitext(
625
+ os.path.basename(output_filename))
626
+ implib_file = os.path.join(
627
+ build_temp,
628
+ self.library_filename(dll_name))
629
+ ld_args.append ('/IMPLIB:' + implib_file)
630
+
631
+ self.manifest_setup_ldargs(output_filename, build_temp, ld_args)
632
+
633
+ if extra_preargs:
634
+ ld_args[:0] = extra_preargs
635
+ if extra_postargs:
636
+ ld_args.extend(extra_postargs)
637
+
638
+ self.mkpath(os.path.dirname(output_filename))
639
+ try:
640
+ self.spawn([self.linker] + ld_args)
641
+ except DistutilsExecError as msg:
642
+ raise LinkError(msg)
643
+
644
+ # embed the manifest
645
+ # XXX - this is somewhat fragile - if mt.exe fails, distutils
646
+ # will still consider the DLL up-to-date, but it will not have a
647
+ # manifest. Maybe we should link to a temp file? OTOH, that
648
+ # implies a build environment error that shouldn't go undetected.
649
+ mfinfo = self.manifest_get_embed_info(target_desc, ld_args)
650
+ if mfinfo is not None:
651
+ mffilename, mfid = mfinfo
652
+ out_arg = '-outputresource:%s;%s' % (output_filename, mfid)
653
+ try:
654
+ self.spawn(['mt.exe', '-nologo', '-manifest',
655
+ mffilename, out_arg])
656
+ except DistutilsExecError as msg:
657
+ raise LinkError(msg)
658
+ else:
659
+ log.debug("skipping %s (up-to-date)", output_filename)
660
+
661
+ def manifest_setup_ldargs(self, output_filename, build_temp, ld_args):
662
+ # If we need a manifest at all, an embedded manifest is recommended.
663
+ # See MSDN article titled
664
+ # "How to: Embed a Manifest Inside a C/C++ Application"
665
+ # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
666
+ # Ask the linker to generate the manifest in the temp dir, so
667
+ # we can check it, and possibly embed it, later.
668
+ temp_manifest = os.path.join(
669
+ build_temp,
670
+ os.path.basename(output_filename) + ".manifest")
671
+ ld_args.append('/MANIFESTFILE:' + temp_manifest)
672
+
673
+ def manifest_get_embed_info(self, target_desc, ld_args):
674
+ # If a manifest should be embedded, return a tuple of
675
+ # (manifest_filename, resource_id). Returns None if no manifest
676
+ # should be embedded. See http://bugs.python.org/issue7833 for why
677
+ # we want to avoid any manifest for extension modules if we can)
678
+ for arg in ld_args:
679
+ if arg.startswith("/MANIFESTFILE:"):
680
+ temp_manifest = arg.split(":", 1)[1]
681
+ break
682
+ else:
683
+ # no /MANIFESTFILE so nothing to do.
684
+ return None
685
+ if target_desc == CCompiler.EXECUTABLE:
686
+ # by default, executables always get the manifest with the
687
+ # CRT referenced.
688
+ mfid = 1
689
+ else:
690
+ # Extension modules try and avoid any manifest if possible.
691
+ mfid = 2
692
+ temp_manifest = self._remove_visual_c_ref(temp_manifest)
693
+ if temp_manifest is None:
694
+ return None
695
+ return temp_manifest, mfid
696
+
697
+ def _remove_visual_c_ref(self, manifest_file):
698
+ try:
699
+ # Remove references to the Visual C runtime, so they will
700
+ # fall through to the Visual C dependency of Python.exe.
701
+ # This way, when installed for a restricted user (e.g.
702
+ # runtimes are not in WinSxS folder, but in Python's own
703
+ # folder), the runtimes do not need to be in every folder
704
+ # with .pyd's.
705
+ # Returns either the filename of the modified manifest or
706
+ # None if no manifest should be embedded.
707
+ manifest_f = open(manifest_file)
708
+ try:
709
+ manifest_buf = manifest_f.read()
710
+ finally:
711
+ manifest_f.close()
712
+ pattern = re.compile(
713
+ r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
714
+ r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
715
+ re.DOTALL)
716
+ manifest_buf = re.sub(pattern, "", manifest_buf)
717
+ pattern = r"<dependentAssembly>\s*</dependentAssembly>"
718
+ manifest_buf = re.sub(pattern, "", manifest_buf)
719
+ # Now see if any other assemblies are referenced - if not, we
720
+ # don't want a manifest embedded.
721
+ pattern = re.compile(
722
+ r"""<assemblyIdentity.*?name=(?:"|')(.+?)(?:"|')"""
723
+ r""".*?(?:/>|</assemblyIdentity>)""", re.DOTALL)
724
+ if re.search(pattern, manifest_buf) is None:
725
+ return None
726
+
727
+ manifest_f = open(manifest_file, 'w')
728
+ try:
729
+ manifest_f.write(manifest_buf)
730
+ return manifest_file
731
+ finally:
732
+ manifest_f.close()
733
+ except OSError:
734
+ pass
735
+
736
+ # -- Miscellaneous methods -----------------------------------------
737
+ # These are all used by the 'gen_lib_options() function, in
738
+ # ccompiler.py.
739
+
740
+ def library_dir_option(self, dir):
741
+ return "/LIBPATH:" + dir
742
+
743
+ def runtime_library_dir_option(self, dir):
744
+ raise DistutilsPlatformError(
745
+ "don't know how to set runtime library search path for MSVC++")
746
+
747
+ def library_option(self, lib):
748
+ return self.library_filename(lib)
749
+
750
+
751
+ def find_library_file(self, dirs, lib, debug=0):
752
+ # Prefer a debugging library if found (and requested), but deal
753
+ # with it if we don't have one.
754
+ if debug:
755
+ try_names = [lib + "_d", lib]
756
+ else:
757
+ try_names = [lib]
758
+ for dir in dirs:
759
+ for name in try_names:
760
+ libfile = os.path.join(dir, self.library_filename (name))
761
+ if os.path.exists(libfile):
762
+ return libfile
763
+ else:
764
+ # Oops, didn't find it in *any* of 'dirs'
765
+ return None
766
+
767
+ # Helper methods for using the MSVC registry settings
768
+
769
+ def find_exe(self, exe):
770
+ """Return path to an MSVC executable program.
771
+
772
+ Tries to find the program in several places: first, one of the
773
+ MSVC program search paths from the registry; next, the directories
774
+ in the PATH environment variable. If any of those work, return an
775
+ absolute path that is known to exist. If none of them work, just
776
+ return the original program name, 'exe'.
777
+ """
778
+ for p in self.__paths:
779
+ fn = os.path.join(os.path.abspath(p), exe)
780
+ if os.path.isfile(fn):
781
+ return fn
782
+
783
+ # didn't find it; try existing path
784
+ for p in os.environ['Path'].split(';'):
785
+ fn = os.path.join(os.path.abspath(p),exe)
786
+ if os.path.isfile(fn):
787
+ return fn
788
+
789
+ return exe
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/sysconfig.py ADDED
@@ -0,0 +1,554 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Provide access to Python's configuration information. The specific
2
+ configuration variables available depend heavily on the platform and
3
+ configuration. The values may be retrieved using
4
+ get_config_var(name), and the list of variables is available via
5
+ get_config_vars().keys(). Additional convenience functions are also
6
+ available.
7
+
8
+ Written by: Fred L. Drake, Jr.
9
+ Email: <fdrake@acm.org>
10
+ """
11
+
12
+ import _imp
13
+ import os
14
+ import re
15
+ import sys
16
+
17
+ from .errors import DistutilsPlatformError
18
+ from .util import get_platform, get_host_platform
19
+
20
+ # These are needed in a couple of spots, so just compute them once.
21
+ PREFIX = os.path.normpath(sys.prefix)
22
+ EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
23
+ BASE_PREFIX = os.path.normpath(sys.base_prefix)
24
+ BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
25
+
26
+ # Path to the base directory of the project. On Windows the binary may
27
+ # live in project/PCbuild/win32 or project/PCbuild/amd64.
28
+ # set for cross builds
29
+ if "_PYTHON_PROJECT_BASE" in os.environ:
30
+ project_base = os.path.abspath(os.environ["_PYTHON_PROJECT_BASE"])
31
+ else:
32
+ if sys.executable:
33
+ project_base = os.path.dirname(os.path.abspath(sys.executable))
34
+ else:
35
+ # sys.executable can be empty if argv[0] has been changed and Python is
36
+ # unable to retrieve the real program name
37
+ project_base = os.getcwd()
38
+
39
+
40
+ # python_build: (Boolean) if true, we're either building Python or
41
+ # building an extension with an un-installed Python, so we use
42
+ # different (hard-wired) directories.
43
+ def _is_python_source_dir(d):
44
+ for fn in ("Setup", "Setup.local"):
45
+ if os.path.isfile(os.path.join(d, "Modules", fn)):
46
+ return True
47
+ return False
48
+
49
+ _sys_home = getattr(sys, '_home', None)
50
+
51
+ if os.name == 'nt':
52
+ def _fix_pcbuild(d):
53
+ if d and os.path.normcase(d).startswith(
54
+ os.path.normcase(os.path.join(PREFIX, "PCbuild"))):
55
+ return PREFIX
56
+ return d
57
+ project_base = _fix_pcbuild(project_base)
58
+ _sys_home = _fix_pcbuild(_sys_home)
59
+
60
+ def _python_build():
61
+ if _sys_home:
62
+ return _is_python_source_dir(_sys_home)
63
+ return _is_python_source_dir(project_base)
64
+
65
+ python_build = _python_build()
66
+
67
+
68
+ # Calculate the build qualifier flags if they are defined. Adding the flags
69
+ # to the include and lib directories only makes sense for an installation, not
70
+ # an in-source build.
71
+ build_flags = ''
72
+ try:
73
+ if not python_build:
74
+ build_flags = sys.abiflags
75
+ except AttributeError:
76
+ # It's not a configure-based build, so the sys module doesn't have
77
+ # this attribute, which is fine.
78
+ pass
79
+
80
+ def get_python_version():
81
+ """Return a string containing the major and minor Python version,
82
+ leaving off the patchlevel. Sample return values could be '1.5'
83
+ or '2.2'.
84
+ """
85
+ return '%d.%d' % sys.version_info[:2]
86
+
87
+
88
+ def get_python_inc(plat_specific=0, prefix=None):
89
+ """Return the directory containing installed Python header files.
90
+
91
+ If 'plat_specific' is false (the default), this is the path to the
92
+ non-platform-specific header files, i.e. Python.h and so on;
93
+ otherwise, this is the path to platform-specific header files
94
+ (namely pyconfig.h).
95
+
96
+ If 'prefix' is supplied, use it instead of sys.base_prefix or
97
+ sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
98
+ """
99
+ if prefix is None:
100
+ prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
101
+ if os.name == "posix":
102
+ if python_build:
103
+ # Assume the executable is in the build directory. The
104
+ # pyconfig.h file should be in the same directory. Since
105
+ # the build directory may not be the source directory, we
106
+ # must use "srcdir" from the makefile to find the "Include"
107
+ # directory.
108
+ if plat_specific:
109
+ return _sys_home or project_base
110
+ else:
111
+ incdir = os.path.join(get_config_var('srcdir'), 'Include')
112
+ return os.path.normpath(incdir)
113
+ python_dir = 'python' + get_python_version() + build_flags
114
+ return os.path.join(prefix, "include", python_dir)
115
+ elif os.name == "nt":
116
+ if python_build:
117
+ # Include both the include and PC dir to ensure we can find
118
+ # pyconfig.h
119
+ return (os.path.join(prefix, "include") + os.path.pathsep +
120
+ os.path.join(prefix, "PC"))
121
+ return os.path.join(prefix, "include")
122
+ else:
123
+ raise DistutilsPlatformError(
124
+ "I don't know where Python installs its C header files "
125
+ "on platform '%s'" % os.name)
126
+
127
+
128
+ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
129
+ """Return the directory containing the Python library (standard or
130
+ site additions).
131
+
132
+ If 'plat_specific' is true, return the directory containing
133
+ platform-specific modules, i.e. any module from a non-pure-Python
134
+ module distribution; otherwise, return the platform-shared library
135
+ directory. If 'standard_lib' is true, return the directory
136
+ containing standard Python library modules; otherwise, return the
137
+ directory for site-specific modules.
138
+
139
+ If 'prefix' is supplied, use it instead of sys.base_prefix or
140
+ sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
141
+ """
142
+ if prefix is None:
143
+ if standard_lib:
144
+ prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
145
+ else:
146
+ prefix = plat_specific and EXEC_PREFIX or PREFIX
147
+
148
+ if os.name == "posix":
149
+ libpython = os.path.join(prefix,
150
+ "lib", "python" + get_python_version())
151
+ if standard_lib:
152
+ return libpython
153
+ else:
154
+ return os.path.join(libpython, "site-packages")
155
+ elif os.name == "nt":
156
+ if standard_lib:
157
+ return os.path.join(prefix, "Lib")
158
+ else:
159
+ return os.path.join(prefix, "Lib", "site-packages")
160
+ else:
161
+ raise DistutilsPlatformError(
162
+ "I don't know where Python installs its library "
163
+ "on platform '%s'" % os.name)
164
+
165
+
166
+
167
+ def customize_compiler(compiler):
168
+ """Do any platform-specific customization of a CCompiler instance.
169
+
170
+ Mainly needed on Unix, so we can plug in the information that
171
+ varies across Unices and is stored in Python's Makefile.
172
+ """
173
+ if compiler.compiler_type == "unix":
174
+ if sys.platform == "darwin":
175
+ # Perform first-time customization of compiler-related
176
+ # config vars on OS X now that we know we need a compiler.
177
+ # This is primarily to support Pythons from binary
178
+ # installers. The kind and paths to build tools on
179
+ # the user system may vary significantly from the system
180
+ # that Python itself was built on. Also the user OS
181
+ # version and build tools may not support the same set
182
+ # of CPU architectures for universal builds.
183
+ global _config_vars
184
+ # Use get_config_var() to ensure _config_vars is initialized.
185
+ if not get_config_var('CUSTOMIZED_OSX_COMPILER'):
186
+ import _osx_support
187
+ _osx_support.customize_compiler(_config_vars)
188
+ _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
189
+
190
+ (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \
191
+ get_config_vars('CC', 'CXX', 'CFLAGS',
192
+ 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
193
+
194
+ if 'CC' in os.environ:
195
+ newcc = os.environ['CC']
196
+ if (sys.platform == 'darwin'
197
+ and 'LDSHARED' not in os.environ
198
+ and ldshared.startswith(cc)):
199
+ # On OS X, if CC is overridden, use that as the default
200
+ # command for LDSHARED as well
201
+ ldshared = newcc + ldshared[len(cc):]
202
+ cc = newcc
203
+ if 'CXX' in os.environ:
204
+ cxx = os.environ['CXX']
205
+ if 'LDSHARED' in os.environ:
206
+ ldshared = os.environ['LDSHARED']
207
+ if 'CPP' in os.environ:
208
+ cpp = os.environ['CPP']
209
+ else:
210
+ cpp = cc + " -E" # not always
211
+ if 'LDFLAGS' in os.environ:
212
+ ldshared = ldshared + ' ' + os.environ['LDFLAGS']
213
+ if 'CFLAGS' in os.environ:
214
+ cflags = cflags + ' ' + os.environ['CFLAGS']
215
+ ldshared = ldshared + ' ' + os.environ['CFLAGS']
216
+ if 'CPPFLAGS' in os.environ:
217
+ cpp = cpp + ' ' + os.environ['CPPFLAGS']
218
+ cflags = cflags + ' ' + os.environ['CPPFLAGS']
219
+ ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
220
+ if 'AR' in os.environ:
221
+ ar = os.environ['AR']
222
+ if 'ARFLAGS' in os.environ:
223
+ archiver = ar + ' ' + os.environ['ARFLAGS']
224
+ else:
225
+ archiver = ar + ' ' + ar_flags
226
+
227
+ cc_cmd = cc + ' ' + cflags
228
+ compiler.set_executables(
229
+ preprocessor=cpp,
230
+ compiler=cc_cmd,
231
+ compiler_so=cc_cmd + ' ' + ccshared,
232
+ compiler_cxx=cxx,
233
+ linker_so=ldshared,
234
+ linker_exe=cc,
235
+ archiver=archiver)
236
+
237
+ if 'RANLIB' in os.environ and 'ranlib' in compiler.executables:
238
+ compiler.set_executables(ranlib=os.environ['RANLIB'])
239
+
240
+ compiler.shared_lib_extension = shlib_suffix
241
+
242
+
243
+ def get_config_h_filename():
244
+ """Return full pathname of installed pyconfig.h file."""
245
+ if python_build:
246
+ if os.name == "nt":
247
+ inc_dir = os.path.join(_sys_home or project_base, "PC")
248
+ else:
249
+ inc_dir = _sys_home or project_base
250
+ else:
251
+ inc_dir = get_python_inc(plat_specific=1)
252
+
253
+ return os.path.join(inc_dir, 'pyconfig.h')
254
+
255
+
256
+ def get_makefile_filename():
257
+ """Return full pathname of installed Makefile from the Python build."""
258
+ if python_build:
259
+ return os.path.join(_sys_home or project_base, "Makefile")
260
+ lib_dir = get_python_lib(plat_specific=0, standard_lib=1)
261
+ config_file = 'config-{}{}'.format(get_python_version(), build_flags)
262
+ if hasattr(sys.implementation, '_multiarch'):
263
+ config_file += '-%s' % sys.implementation._multiarch
264
+ return os.path.join(lib_dir, config_file, 'Makefile')
265
+
266
+
267
+ def parse_config_h(fp, g=None):
268
+ """Parse a config.h-style file.
269
+
270
+ A dictionary containing name/value pairs is returned. If an
271
+ optional dictionary is passed in as the second argument, it is
272
+ used instead of a new dictionary.
273
+ """
274
+ if g is None:
275
+ g = {}
276
+ define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
277
+ undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
278
+ #
279
+ while True:
280
+ line = fp.readline()
281
+ if not line:
282
+ break
283
+ m = define_rx.match(line)
284
+ if m:
285
+ n, v = m.group(1, 2)
286
+ try: v = int(v)
287
+ except ValueError: pass
288
+ g[n] = v
289
+ else:
290
+ m = undef_rx.match(line)
291
+ if m:
292
+ g[m.group(1)] = 0
293
+ return g
294
+
295
+
296
+ # Regexes needed for parsing Makefile (and similar syntaxes,
297
+ # like old-style Setup files).
298
+ _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
299
+ _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
300
+ _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
301
+
302
+ def parse_makefile(fn, g=None):
303
+ """Parse a Makefile-style file.
304
+
305
+ A dictionary containing name/value pairs is returned. If an
306
+ optional dictionary is passed in as the second argument, it is
307
+ used instead of a new dictionary.
308
+ """
309
+ from distutils.text_file import TextFile
310
+ fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape")
311
+
312
+ if g is None:
313
+ g = {}
314
+ done = {}
315
+ notdone = {}
316
+
317
+ while True:
318
+ line = fp.readline()
319
+ if line is None: # eof
320
+ break
321
+ m = _variable_rx.match(line)
322
+ if m:
323
+ n, v = m.group(1, 2)
324
+ v = v.strip()
325
+ # `$$' is a literal `$' in make
326
+ tmpv = v.replace('$$', '')
327
+
328
+ if "$" in tmpv:
329
+ notdone[n] = v
330
+ else:
331
+ try:
332
+ v = int(v)
333
+ except ValueError:
334
+ # insert literal `$'
335
+ done[n] = v.replace('$$', '$')
336
+ else:
337
+ done[n] = v
338
+
339
+ # Variables with a 'PY_' prefix in the makefile. These need to
340
+ # be made available without that prefix through sysconfig.
341
+ # Special care is needed to ensure that variable expansion works, even
342
+ # if the expansion uses the name without a prefix.
343
+ renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
344
+
345
+ # do variable interpolation here
346
+ while notdone:
347
+ for name in list(notdone):
348
+ value = notdone[name]
349
+ m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
350
+ if m:
351
+ n = m.group(1)
352
+ found = True
353
+ if n in done:
354
+ item = str(done[n])
355
+ elif n in notdone:
356
+ # get it on a subsequent round
357
+ found = False
358
+ elif n in os.environ:
359
+ # do it like make: fall back to environment
360
+ item = os.environ[n]
361
+
362
+ elif n in renamed_variables:
363
+ if name.startswith('PY_') and name[3:] in renamed_variables:
364
+ item = ""
365
+
366
+ elif 'PY_' + n in notdone:
367
+ found = False
368
+
369
+ else:
370
+ item = str(done['PY_' + n])
371
+ else:
372
+ done[n] = item = ""
373
+ if found:
374
+ after = value[m.end():]
375
+ value = value[:m.start()] + item + after
376
+ if "$" in after:
377
+ notdone[name] = value
378
+ else:
379
+ try: value = int(value)
380
+ except ValueError:
381
+ done[name] = value.strip()
382
+ else:
383
+ done[name] = value
384
+ del notdone[name]
385
+
386
+ if name.startswith('PY_') \
387
+ and name[3:] in renamed_variables:
388
+
389
+ name = name[3:]
390
+ if name not in done:
391
+ done[name] = value
392
+ else:
393
+ # bogus variable reference; just drop it since we can't deal
394
+ del notdone[name]
395
+
396
+ fp.close()
397
+
398
+ # strip spurious spaces
399
+ for k, v in done.items():
400
+ if isinstance(v, str):
401
+ done[k] = v.strip()
402
+
403
+ # save the results in the global dictionary
404
+ g.update(done)
405
+ return g
406
+
407
+
408
+ def expand_makefile_vars(s, vars):
409
+ """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
410
+ 'string' according to 'vars' (a dictionary mapping variable names to
411
+ values). Variables not present in 'vars' are silently expanded to the
412
+ empty string. The variable values in 'vars' should not contain further
413
+ variable expansions; if 'vars' is the output of 'parse_makefile()',
414
+ you're fine. Returns a variable-expanded version of 's'.
415
+ """
416
+
417
+ # This algorithm does multiple expansion, so if vars['foo'] contains
418
+ # "${bar}", it will expand ${foo} to ${bar}, and then expand
419
+ # ${bar}... and so forth. This is fine as long as 'vars' comes from
420
+ # 'parse_makefile()', which takes care of such expansions eagerly,
421
+ # according to make's variable expansion semantics.
422
+
423
+ while True:
424
+ m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
425
+ if m:
426
+ (beg, end) = m.span()
427
+ s = s[0:beg] + vars.get(m.group(1)) + s[end:]
428
+ else:
429
+ break
430
+ return s
431
+
432
+
433
+ _config_vars = None
434
+
435
+ def _init_posix():
436
+ """Initialize the module as appropriate for POSIX systems."""
437
+ # _sysconfigdata is generated at build time, see the sysconfig module
438
+ name = os.environ.get('_PYTHON_SYSCONFIGDATA_NAME',
439
+ os.environ.get('_CONDA_PYTHON_SYSCONFIGDATA_NAME',
440
+ '_sysconfigdata_{abi}_{platform}_{multiarch}'.format(
441
+ abi=sys.abiflags,
442
+ platform=sys.platform,
443
+ multiarch=getattr(sys.implementation, '_multiarch', ''))
444
+ )
445
+ )
446
+ _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
447
+ build_time_vars = _temp.build_time_vars
448
+ global _config_vars
449
+ _config_vars = {}
450
+ _config_vars.update(build_time_vars)
451
+
452
+
453
+ def _init_nt():
454
+ """Initialize the module as appropriate for NT"""
455
+ g = {}
456
+ # set basic install directories
457
+ g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
458
+ g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
459
+
460
+ # XXX hmmm.. a normal install puts include files here
461
+ g['INCLUDEPY'] = get_python_inc(plat_specific=0)
462
+
463
+ g['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
464
+ g['EXE'] = ".exe"
465
+ g['VERSION'] = get_python_version().replace(".", "")
466
+ g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable))
467
+
468
+ global _config_vars
469
+ _config_vars = g
470
+
471
+
472
+ def get_config_vars(*args):
473
+ """With no arguments, return a dictionary of all configuration
474
+ variables relevant for the current platform. Generally this includes
475
+ everything needed to build extensions and install both pure modules and
476
+ extensions. On Unix, this means every variable defined in Python's
477
+ installed Makefile; on Windows it's a much smaller set.
478
+
479
+ With arguments, return a list of values that result from looking up
480
+ each argument in the configuration variable dictionary.
481
+ """
482
+ global _config_vars
483
+ if _config_vars is None:
484
+ func = globals().get("_init_" + os.name)
485
+ if func:
486
+ func()
487
+ else:
488
+ _config_vars = {}
489
+
490
+ # Normalized versions of prefix and exec_prefix are handy to have;
491
+ # in fact, these are the standard versions used most places in the
492
+ # Distutils.
493
+ _config_vars['prefix'] = PREFIX
494
+ _config_vars['exec_prefix'] = EXEC_PREFIX
495
+
496
+ # For backward compatibility, see issue19555
497
+ SO = _config_vars.get('EXT_SUFFIX')
498
+ if SO is not None:
499
+ _config_vars['SO'] = SO
500
+
501
+ # Always convert srcdir to an absolute path
502
+ srcdir = _config_vars.get('srcdir', project_base)
503
+ if os.name == 'posix':
504
+ if python_build:
505
+ # If srcdir is a relative path (typically '.' or '..')
506
+ # then it should be interpreted relative to the directory
507
+ # containing Makefile.
508
+ base = os.path.dirname(get_makefile_filename())
509
+ srcdir = os.path.join(base, srcdir)
510
+ else:
511
+ # srcdir is not meaningful since the installation is
512
+ # spread about the filesystem. We choose the
513
+ # directory containing the Makefile since we know it
514
+ # exists.
515
+ srcdir = os.path.dirname(get_makefile_filename())
516
+ _config_vars['srcdir'] = os.path.abspath(os.path.normpath(srcdir))
517
+
518
+ # Convert srcdir into an absolute path if it appears necessary.
519
+ # Normally it is relative to the build directory. However, during
520
+ # testing, for example, we might be running a non-installed python
521
+ # from a different directory.
522
+ if python_build and os.name == "posix":
523
+ base = project_base
524
+ if (not os.path.isabs(_config_vars['srcdir']) and
525
+ base != os.getcwd()):
526
+ # srcdir is relative and we are not in the same directory
527
+ # as the executable. Assume executable is in the build
528
+ # directory and make srcdir absolute.
529
+ srcdir = os.path.join(base, _config_vars['srcdir'])
530
+ _config_vars['srcdir'] = os.path.normpath(srcdir)
531
+
532
+ # OS X platforms require special customization to handle
533
+ # multi-architecture, multi-os-version installers
534
+ if sys.platform == 'darwin':
535
+ import _osx_support
536
+ _osx_support.customize_config_vars(_config_vars)
537
+
538
+ if args:
539
+ vals = []
540
+ for name in args:
541
+ vals.append(_config_vars.get(name))
542
+ return vals
543
+ else:
544
+ return _config_vars
545
+
546
+ def get_config_var(name):
547
+ """Return the value of a single variable using the dictionary
548
+ returned by 'get_config_vars()'. Equivalent to
549
+ get_config_vars().get(name)
550
+ """
551
+ if name == 'SO':
552
+ import warnings
553
+ warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
554
+ return get_config_vars().get(name)
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/text_file.py ADDED
@@ -0,0 +1,286 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """text_file
2
+
3
+ provides the TextFile class, which gives an interface to text files
4
+ that (optionally) takes care of stripping comments, ignoring blank
5
+ lines, and joining lines with backslashes."""
6
+
7
+ import sys, io
8
+
9
+
10
+ class TextFile:
11
+ """Provides a file-like object that takes care of all the things you
12
+ commonly want to do when processing a text file that has some
13
+ line-by-line syntax: strip comments (as long as "#" is your
14
+ comment character), skip blank lines, join adjacent lines by
15
+ escaping the newline (ie. backslash at end of line), strip
16
+ leading and/or trailing whitespace. All of these are optional
17
+ and independently controllable.
18
+
19
+ Provides a 'warn()' method so you can generate warning messages that
20
+ report physical line number, even if the logical line in question
21
+ spans multiple physical lines. Also provides 'unreadline()' for
22
+ implementing line-at-a-time lookahead.
23
+
24
+ Constructor is called as:
25
+
26
+ TextFile (filename=None, file=None, **options)
27
+
28
+ It bombs (RuntimeError) if both 'filename' and 'file' are None;
29
+ 'filename' should be a string, and 'file' a file object (or
30
+ something that provides 'readline()' and 'close()' methods). It is
31
+ recommended that you supply at least 'filename', so that TextFile
32
+ can include it in warning messages. If 'file' is not supplied,
33
+ TextFile creates its own using 'io.open()'.
34
+
35
+ The options are all boolean, and affect the value returned by
36
+ 'readline()':
37
+ strip_comments [default: true]
38
+ strip from "#" to end-of-line, as well as any whitespace
39
+ leading up to the "#" -- unless it is escaped by a backslash
40
+ lstrip_ws [default: false]
41
+ strip leading whitespace from each line before returning it
42
+ rstrip_ws [default: true]
43
+ strip trailing whitespace (including line terminator!) from
44
+ each line before returning it
45
+ skip_blanks [default: true}
46
+ skip lines that are empty *after* stripping comments and
47
+ whitespace. (If both lstrip_ws and rstrip_ws are false,
48
+ then some lines may consist of solely whitespace: these will
49
+ *not* be skipped, even if 'skip_blanks' is true.)
50
+ join_lines [default: false]
51
+ if a backslash is the last non-newline character on a line
52
+ after stripping comments and whitespace, join the following line
53
+ to it to form one "logical line"; if N consecutive lines end
54
+ with a backslash, then N+1 physical lines will be joined to
55
+ form one logical line.
56
+ collapse_join [default: false]
57
+ strip leading whitespace from lines that are joined to their
58
+ predecessor; only matters if (join_lines and not lstrip_ws)
59
+ errors [default: 'strict']
60
+ error handler used to decode the file content
61
+
62
+ Note that since 'rstrip_ws' can strip the trailing newline, the
63
+ semantics of 'readline()' must differ from those of the builtin file
64
+ object's 'readline()' method! In particular, 'readline()' returns
65
+ None for end-of-file: an empty string might just be a blank line (or
66
+ an all-whitespace line), if 'rstrip_ws' is true but 'skip_blanks' is
67
+ not."""
68
+
69
+ default_options = { 'strip_comments': 1,
70
+ 'skip_blanks': 1,
71
+ 'lstrip_ws': 0,
72
+ 'rstrip_ws': 1,
73
+ 'join_lines': 0,
74
+ 'collapse_join': 0,
75
+ 'errors': 'strict',
76
+ }
77
+
78
+ def __init__(self, filename=None, file=None, **options):
79
+ """Construct a new TextFile object. At least one of 'filename'
80
+ (a string) and 'file' (a file-like object) must be supplied.
81
+ They keyword argument options are described above and affect
82
+ the values returned by 'readline()'."""
83
+ if filename is None and file is None:
84
+ raise RuntimeError("you must supply either or both of 'filename' and 'file'")
85
+
86
+ # set values for all options -- either from client option hash
87
+ # or fallback to default_options
88
+ for opt in self.default_options.keys():
89
+ if opt in options:
90
+ setattr(self, opt, options[opt])
91
+ else:
92
+ setattr(self, opt, self.default_options[opt])
93
+
94
+ # sanity check client option hash
95
+ for opt in options.keys():
96
+ if opt not in self.default_options:
97
+ raise KeyError("invalid TextFile option '%s'" % opt)
98
+
99
+ if file is None:
100
+ self.open(filename)
101
+ else:
102
+ self.filename = filename
103
+ self.file = file
104
+ self.current_line = 0 # assuming that file is at BOF!
105
+
106
+ # 'linebuf' is a stack of lines that will be emptied before we
107
+ # actually read from the file; it's only populated by an
108
+ # 'unreadline()' operation
109
+ self.linebuf = []
110
+
111
+ def open(self, filename):
112
+ """Open a new file named 'filename'. This overrides both the
113
+ 'filename' and 'file' arguments to the constructor."""
114
+ self.filename = filename
115
+ self.file = io.open(self.filename, 'r', errors=self.errors)
116
+ self.current_line = 0
117
+
118
+ def close(self):
119
+ """Close the current file and forget everything we know about it
120
+ (filename, current line number)."""
121
+ file = self.file
122
+ self.file = None
123
+ self.filename = None
124
+ self.current_line = None
125
+ file.close()
126
+
127
+ def gen_error(self, msg, line=None):
128
+ outmsg = []
129
+ if line is None:
130
+ line = self.current_line
131
+ outmsg.append(self.filename + ", ")
132
+ if isinstance(line, (list, tuple)):
133
+ outmsg.append("lines %d-%d: " % tuple(line))
134
+ else:
135
+ outmsg.append("line %d: " % line)
136
+ outmsg.append(str(msg))
137
+ return "".join(outmsg)
138
+
139
+ def error(self, msg, line=None):
140
+ raise ValueError("error: " + self.gen_error(msg, line))
141
+
142
+ def warn(self, msg, line=None):
143
+ """Print (to stderr) a warning message tied to the current logical
144
+ line in the current file. If the current logical line in the
145
+ file spans multiple physical lines, the warning refers to the
146
+ whole range, eg. "lines 3-5". If 'line' supplied, it overrides
147
+ the current line number; it may be a list or tuple to indicate a
148
+ range of physical lines, or an integer for a single physical
149
+ line."""
150
+ sys.stderr.write("warning: " + self.gen_error(msg, line) + "\n")
151
+
152
+ def readline(self):
153
+ """Read and return a single logical line from the current file (or
154
+ from an internal buffer if lines have previously been "unread"
155
+ with 'unreadline()'). If the 'join_lines' option is true, this
156
+ may involve reading multiple physical lines concatenated into a
157
+ single string. Updates the current line number, so calling
158
+ 'warn()' after 'readline()' emits a warning about the physical
159
+ line(s) just read. Returns None on end-of-file, since the empty
160
+ string can occur if 'rstrip_ws' is true but 'strip_blanks' is
161
+ not."""
162
+ # If any "unread" lines waiting in 'linebuf', return the top
163
+ # one. (We don't actually buffer read-ahead data -- lines only
164
+ # get put in 'linebuf' if the client explicitly does an
165
+ # 'unreadline()'.
166
+ if self.linebuf:
167
+ line = self.linebuf[-1]
168
+ del self.linebuf[-1]
169
+ return line
170
+
171
+ buildup_line = ''
172
+
173
+ while True:
174
+ # read the line, make it None if EOF
175
+ line = self.file.readline()
176
+ if line == '':
177
+ line = None
178
+
179
+ if self.strip_comments and line:
180
+
181
+ # Look for the first "#" in the line. If none, never
182
+ # mind. If we find one and it's the first character, or
183
+ # is not preceded by "\", then it starts a comment --
184
+ # strip the comment, strip whitespace before it, and
185
+ # carry on. Otherwise, it's just an escaped "#", so
186
+ # unescape it (and any other escaped "#"'s that might be
187
+ # lurking in there) and otherwise leave the line alone.
188
+
189
+ pos = line.find("#")
190
+ if pos == -1: # no "#" -- no comments
191
+ pass
192
+
193
+ # It's definitely a comment -- either "#" is the first
194
+ # character, or it's elsewhere and unescaped.
195
+ elif pos == 0 or line[pos-1] != "\\":
196
+ # Have to preserve the trailing newline, because it's
197
+ # the job of a later step (rstrip_ws) to remove it --
198
+ # and if rstrip_ws is false, we'd better preserve it!
199
+ # (NB. this means that if the final line is all comment
200
+ # and has no trailing newline, we will think that it's
201
+ # EOF; I think that's OK.)
202
+ eol = (line[-1] == '\n') and '\n' or ''
203
+ line = line[0:pos] + eol
204
+
205
+ # If all that's left is whitespace, then skip line
206
+ # *now*, before we try to join it to 'buildup_line' --
207
+ # that way constructs like
208
+ # hello \\
209
+ # # comment that should be ignored
210
+ # there
211
+ # result in "hello there".
212
+ if line.strip() == "":
213
+ continue
214
+ else: # it's an escaped "#"
215
+ line = line.replace("\\#", "#")
216
+
217
+ # did previous line end with a backslash? then accumulate
218
+ if self.join_lines and buildup_line:
219
+ # oops: end of file
220
+ if line is None:
221
+ self.warn("continuation line immediately precedes "
222
+ "end-of-file")
223
+ return buildup_line
224
+
225
+ if self.collapse_join:
226
+ line = line.lstrip()
227
+ line = buildup_line + line
228
+
229
+ # careful: pay attention to line number when incrementing it
230
+ if isinstance(self.current_line, list):
231
+ self.current_line[1] = self.current_line[1] + 1
232
+ else:
233
+ self.current_line = [self.current_line,
234
+ self.current_line + 1]
235
+ # just an ordinary line, read it as usual
236
+ else:
237
+ if line is None: # eof
238
+ return None
239
+
240
+ # still have to be careful about incrementing the line number!
241
+ if isinstance(self.current_line, list):
242
+ self.current_line = self.current_line[1] + 1
243
+ else:
244
+ self.current_line = self.current_line + 1
245
+
246
+ # strip whitespace however the client wants (leading and
247
+ # trailing, or one or the other, or neither)
248
+ if self.lstrip_ws and self.rstrip_ws:
249
+ line = line.strip()
250
+ elif self.lstrip_ws:
251
+ line = line.lstrip()
252
+ elif self.rstrip_ws:
253
+ line = line.rstrip()
254
+
255
+ # blank line (whether we rstrip'ed or not)? skip to next line
256
+ # if appropriate
257
+ if (line == '' or line == '\n') and self.skip_blanks:
258
+ continue
259
+
260
+ if self.join_lines:
261
+ if line[-1] == '\\':
262
+ buildup_line = line[:-1]
263
+ continue
264
+
265
+ if line[-2:] == '\\\n':
266
+ buildup_line = line[0:-2] + '\n'
267
+ continue
268
+
269
+ # well, I guess there's some actual content there: return it
270
+ return line
271
+
272
+ def readlines(self):
273
+ """Read and return the list of all logical lines remaining in the
274
+ current file."""
275
+ lines = []
276
+ while True:
277
+ line = self.readline()
278
+ if line is None:
279
+ return lines
280
+ lines.append(line)
281
+
282
+ def unreadline(self, line):
283
+ """Push 'line' (a string) onto an internal buffer that will be
284
+ checked by future 'readline()' calls. Handy for implementing
285
+ a parser with line-at-a-time lookahead."""
286
+ self.linebuf.append(line)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/HISTORY.txt ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ IDLE History
2
+ ============
3
+
4
+ This file contains the release messages for previous IDLE releases.
5
+ As you read on you go back to the dark ages of IDLE's history.
6
+
7
+
8
+ What's New in IDLEfork 0.8.1?
9
+ =============================
10
+
11
+ *Release date: 22-Jul-2001*
12
+
13
+ - New tarball released as a result of the 'revitalisation' of the IDLEfork
14
+ project.
15
+
16
+ - This release requires python 2.1 or better. Compatibility with earlier
17
+ versions of python (especially ancient ones like 1.5x) is no longer a
18
+ priority in IDLEfork development.
19
+
20
+ - This release is based on a merging of the earlier IDLE fork work with current
21
+ cvs IDLE (post IDLE version 0.8), with some minor additional coding by Kurt
22
+ B. Kaiser and Stephen M. Gava.
23
+
24
+ - This release is basically functional but also contains some known breakages,
25
+ particularly with running things from the shell window. Also the debugger is
26
+ not working, but I believe this was the case with the previous IDLE fork
27
+ release (0.7.1) as well.
28
+
29
+ - This release is being made now to mark the point at which IDLEfork is
30
+ launching into a new stage of development.
31
+
32
+ - IDLEfork CVS will now be branched to enable further development and
33
+ exploration of the two "execution in a remote process" patches submitted by
34
+ David Scherer (David's is currently in IDLEfork) and GvR, while stabilisation
35
+ and development of less heavyweight improvements (like user customisation)
36
+ can continue on the trunk.
37
+
38
+
39
+ What's New in IDLEfork 0.7.1?
40
+ ==============================
41
+
42
+ *Release date: 15-Aug-2000*
43
+
44
+ - First project tarball released.
45
+
46
+ - This was the first release of IDLE fork, which at this stage was a
47
+ combination of IDLE 0.5 and the VPython idle fork, with additional changes
48
+ coded by David Scherer, Peter Schneider-Kamp and Nicholas Riley.
49
+
50
+
51
+
52
+ IDLEfork 0.7.1 - 29 May 2000
53
+ -----------------------------
54
+
55
+ David Scherer <dscherer@cmu.edu>
56
+
57
+ - This is a modification of the CVS version of IDLE 0.5, updated as of
58
+ 2000-03-09. It is alpha software and might be unstable. If it breaks, you
59
+ get to keep both pieces.
60
+
61
+ - If you have problems or suggestions, you should either contact me or post to
62
+ the list at http://www.python.org/mailman/listinfo/idle-dev (making it clear
63
+ that you are using this modified version of IDLE).
64
+
65
+ - Changes:
66
+
67
+ - The ExecBinding module, a replacement for ScriptBinding, executes programs
68
+ in a separate process, piping standard I/O through an RPC mechanism to an
69
+ OnDemandOutputWindow in IDLE. It supports executing unnamed programs
70
+ (through a temporary file). It does not yet support debugging.
71
+
72
+ - When running programs with ExecBinding, tracebacks will be clipped to
73
+ exclude system modules. If, however, a system module calls back into the
74
+ user program, that part of the traceback will be shown.
75
+
76
+ - The OnDemandOutputWindow class has been improved. In particular, it now
77
+ supports a readline() function used to implement user input, and a
78
+ scroll_clear() operation which is used to hide the output of a previous run
79
+ by scrolling it out of the window.
80
+
81
+ - Startup behavior has been changed. By default IDLE starts up with just a
82
+ blank editor window, rather than an interactive window. Opening a file in
83
+ such a blank window replaces the (nonexistent) contents of that window
84
+ instead of creating another window. Because of the need to have a
85
+ well-known port for the ExecBinding protocol, only one copy of IDLE can be
86
+ running. Additional invocations use the RPC mechanism to report their
87
+ command line arguments to the copy already running.
88
+
89
+ - The menus have been reorganized. In particular, the excessively large
90
+ 'edit' menu has been split up into 'edit', 'format', and 'run'.
91
+
92
+ - 'Python Documentation' now works on Windows, if the win32api module is
93
+ present.
94
+
95
+ - A few key bindings have been changed: F1 now loads Python Documentation
96
+ instead of the IDLE help; shift-TAB is now a synonym for unindent.
97
+
98
+ - New modules:
99
+
100
+ ExecBinding.py Executes program through loader
101
+ loader.py Bootstraps user program
102
+ protocol.py RPC protocol
103
+ Remote.py User-process interpreter
104
+ spawn.py OS-specific code to start programs
105
+
106
+ - Files modified:
107
+
108
+ autoindent.py ( bindings tweaked )
109
+ bindings.py ( menus reorganized )
110
+ config.txt ( execbinding enabled )
111
+ editorwindow.py ( new menus, fixed 'Python Documentation' )
112
+ filelist.py ( hook for "open in same window" )
113
+ formatparagraph.py ( bindings tweaked )
114
+ idle.bat ( removed absolute pathname )
115
+ idle.pyw ( weird bug due to import with same name? )
116
+ iobinding.py ( open in same window, EOL convention )
117
+ keydefs.py ( bindings tweaked )
118
+ outputwindow.py ( readline, scroll_clear, etc )
119
+ pyshell.py ( changed startup behavior )
120
+ readme.txt ( <Recursion on file with id=1234567> )
121
+
122
+
123
+
124
+ IDLE 0.5 - February 2000 - Release Notes
125
+ ----------------------------------------
126
+
127
+ This is an early release of IDLE, my own attempt at a Tkinter-based
128
+ IDE for Python.
129
+
130
+ (For a more detailed change log, see the file ChangeLog.)
131
+
132
+ FEATURES
133
+
134
+ IDLE has the following features:
135
+
136
+ - coded in 100% pure Python, using the Tkinter GUI toolkit (i.e. Tcl/Tk)
137
+
138
+ - cross-platform: works on Windows and Unix (on the Mac, there are
139
+ currently problems with Tcl/Tk)
140
+
141
+ - multi-window text editor with multiple undo, Python colorizing
142
+ and many other features, e.g. smart indent and call tips
143
+
144
+ - Python shell window (a.k.a. interactive interpreter)
145
+
146
+ - debugger (not complete, but you can set breakpoints, view and step)
147
+
148
+ USAGE
149
+
150
+ The main program is in the file "idle.py"; on Unix, you should be able
151
+ to run it by typing "./idle.py" to your shell. On Windows, you can
152
+ run it by double-clicking it; you can use idle.pyw to avoid popping up
153
+ a DOS console. If you want to pass command line arguments on Windows,
154
+ use the batch file idle.bat.
155
+
156
+ Command line arguments: files passed on the command line are executed,
157
+ not opened for editing, unless you give the -e command line option.
158
+ Try "./idle.py -h" to see other command line options.
159
+
160
+ IDLE requires Python 1.5.2, so it is currently only usable with a
161
+ Python 1.5.2 distribution. (An older version of IDLE is distributed
162
+ with Python 1.5.2; you can drop this version on top of it.)
163
+
164
+ COPYRIGHT
165
+
166
+ IDLE is covered by the standard Python copyright notice
167
+ (http://www.python.org/doc/Copyright.html).
168
+
169
+
170
+ New in IDLE 0.5 (2/15/2000)
171
+ ---------------------------
172
+
173
+ Tons of stuff, much of it contributed by Tim Peters and Mark Hammond:
174
+
175
+ - Status bar, displaying current line/column (Moshe Zadka).
176
+
177
+ - Better stack viewer, using tree widget. (XXX Only used by Stack
178
+ Viewer menu, not by the debugger.)
179
+
180
+ - Format paragraph now recognizes Python block comments and reformats
181
+ them correctly (MH)
182
+
183
+ - New version of pyclbr.py parses top-level functions and understands
184
+ much more of Python's syntax; this is reflected in the class and path
185
+ browsers (TP)
186
+
187
+ - Much better auto-indent; knows how to indent the insides of
188
+ multi-line statements (TP)
189
+
190
+ - Call tip window pops up when you type the name of a known function
191
+ followed by an open parenthesis. Hit ESC or click elsewhere in the
192
+ window to close the tip window (MH)
193
+
194
+ - Comment out region now inserts ## to make it stand out more (TP)
195
+
196
+ - New path and class browsers based on a tree widget that looks
197
+ familiar to Windows users
198
+
199
+ - Reworked script running commands to be more intuitive: I/O now
200
+ always goes to the *Python Shell* window, and raw_input() works
201
+ correctly. You use F5 to import/reload a module: this adds the module
202
+ name to the __main__ namespace. You use Control-F5 to run a script:
203
+ this runs the script *in* the __main__ namespace. The latter also
204
+ sets sys.argv[] to the script name
205
+
206
+
207
+ New in IDLE 0.4 (4/7/99)
208
+ ------------------------
209
+
210
+ Most important change: a new menu entry "File -> Path browser", shows
211
+ a 4-column hierarchical browser which lets you browse sys.path,
212
+ directories, modules, and classes. Yes, it's a superset of the Class
213
+ browser menu entry. There's also a new internal module,
214
+ MultiScrolledLists.py, which provides the framework for this dialog.
215
+
216
+
217
+ New in IDLE 0.3 (2/17/99)
218
+ -------------------------
219
+
220
+ Most important changes:
221
+
222
+ - Enabled support for running a module, with or without the debugger.
223
+ Output goes to a new window. Pressing F5 in a module is effectively a
224
+ reload of that module; Control-F5 loads it under the debugger.
225
+
226
+ - Re-enable tearing off the Windows menu, and make a torn-off Windows
227
+ menu update itself whenever a window is opened or closed.
228
+
229
+ - Menu items can now be have a checkbox (when the menu label starts
230
+ with "!"); use this for the Debugger and "Auto-open stack viewer"
231
+ (was: JIT stack viewer) menu items.
232
+
233
+ - Added a Quit button to the Debugger API.
234
+
235
+ - The current directory is explicitly inserted into sys.path.
236
+
237
+ - Fix the debugger (when using Python 1.5.2b2) to use canonical
238
+ filenames for breakpoints, so these actually work. (There's still a
239
+ lot of work to be done to the management of breakpoints in the
240
+ debugger though.)
241
+
242
+ - Closing a window that is still colorizing now actually works.
243
+
244
+ - Allow dragging of the separator between the two list boxes in the
245
+ class browser.
246
+
247
+ - Bind ESC to "close window" of the debugger, stack viewer and class
248
+ browser. It removes the selection highlighting in regular text
249
+ windows. (These are standard Windows conventions.)
250
+
251
+
252
+ New in IDLE 0.2 (1/8/99)
253
+ ------------------------
254
+
255
+ Lots of changes; here are the highlights:
256
+
257
+ General:
258
+
259
+ - You can now write and configure your own IDLE extension modules; see
260
+ extend.txt.
261
+
262
+
263
+ File menu:
264
+
265
+ The command to open the Python shell window is now in the File menu.
266
+
267
+
268
+ Edit menu:
269
+
270
+ New Find dialog with more options; replace dialog; find in files dialog.
271
+
272
+ Commands to tabify or untabify a region.
273
+
274
+ Command to format a paragraph.
275
+
276
+
277
+ Debug menu:
278
+
279
+ JIT (Just-In-Time) stack viewer toggle -- if set, the stack viewer
280
+ automaticall pops up when you get a traceback.
281
+
282
+ Windows menu:
283
+
284
+ Zoom height -- make the window full height.
285
+
286
+
287
+ Help menu:
288
+
289
+ The help text now show up in a regular window so you can search and
290
+ even edit it if you like.
291
+
292
+
293
+
294
+ IDLE 0.1 was distributed with the Python 1.5.2b1 release on 12/22/98.
295
+
296
+ ======================================================================
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/NEWS2x.txt ADDED
@@ -0,0 +1,660 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ What's New in IDLE 2.7? (Merged into 3.1 before 2.7 release.)
2
+ =======================
3
+ *Release date: XX-XXX-2010*
4
+
5
+ - idle.py modified and simplified to better support developing experimental
6
+ versions of IDLE which are not installed in the standard location.
7
+
8
+ - OutputWindow/PyShell right click menu "Go to file/line" wasn't working with
9
+ file paths containing spaces. Bug 5559.
10
+
11
+ - Windows: Version string for the .chm help file changed, file not being
12
+ accessed Patch 5783 Guilherme Polo
13
+
14
+ - Allow multiple IDLE GUI/subprocess pairs to exist simultaneously. Thanks to
15
+ David Scherer for suggesting the use of an ephemeral port for the GUI.
16
+ Patch 1529142 Weeble.
17
+
18
+ - Remove port spec from run.py and fix bug where subprocess fails to
19
+ extract port from command line when warnings are present.
20
+
21
+ - Tk 8.5 Text widget requires 'wordprocessor' tabstyle attr to handle
22
+ mixed space/tab properly. Issue 5129, patch by Guilherme Polo.
23
+
24
+ - Issue #3549: On MacOS the preferences menu was not present
25
+
26
+ - IDLE would print a "Unhandled server exception!" message when internal
27
+ debugging is enabled.
28
+
29
+ - Issue #4455: IDLE failed to display the windows list when two windows have
30
+ the same title.
31
+
32
+ - Issue #4383: When IDLE cannot make the connection to its subprocess, it would
33
+ fail to properly display the error message.
34
+
35
+ - help() was not paging to the shell. Issue1650.
36
+
37
+ - CodeContext was not importing.
38
+
39
+ - Corrected two 3.0 compatibility errors reported by Mark Summerfield:
40
+ http://mail.python.org/pipermail/python-3000/2007-December/011491.html
41
+
42
+ - Shell was not colorizing due to bug introduced at r57998, Bug 1586.
43
+
44
+ - Issue #1585: IDLE uses non-existent xrange() function.
45
+
46
+ - Windows EOL sequence not converted correctly, encoding error.
47
+ Caused file save to fail. Bug 1130.
48
+
49
+ - IDLE converted to Python 3000 syntax.
50
+
51
+ - Strings became Unicode.
52
+
53
+ - CallTips module now uses the inspect module to produce the argspec.
54
+
55
+ - IDLE modules now use absolute import instead of implied relative import.
56
+
57
+ - atexit call replaces sys.exitfunc. The functionality of delete-exitfunc flag
58
+ in config-main.cfg remains unchanged: if set, registered exit functions will
59
+ be cleared before IDLE exits.
60
+
61
+
62
+ What's New in IDLE 2.6
63
+ ======================
64
+ *Release date: 01-Oct-2008*, merged into 3.0 releases detailed above (3.0rc2)
65
+
66
+ - Issue #2665: On Windows, an IDLE installation upgraded from an old version
67
+ would not start if a custom theme was defined.
68
+
69
+ - Home / Control-A toggles between left margin and end of leading white
70
+ space. issue1196903, patch by Jeff Shute.
71
+
72
+ - Improved AutoCompleteWindow logic. issue2062, patch by Tal Einat.
73
+
74
+ - Autocompletion of filenames now support alternate separators, e.g. the
75
+ '/' char on Windows. issue2061 Patch by Tal Einat.
76
+
77
+ - Configured selection highlighting colors were ignored; updating highlighting
78
+ in the config dialog would cause non-Python files to be colored as if they
79
+ were Python source; improve use of ColorDelagator. Patch 1334. Tal Einat.
80
+
81
+ - ScriptBinding event handlers weren't returning 'break'. Patch 2050, Tal Einat
82
+
83
+ - There was an error on exit if no sys.exitfunc was defined. Issue 1647.
84
+
85
+ - Could not open files in .idlerc directory if latter was hidden on Windows.
86
+ Issue 1743, Issue 1862.
87
+
88
+ - Configure Dialog: improved layout for keybinding. Patch 1457 Tal Einat.
89
+
90
+ - tabpage.py updated: tabbedPages.py now supports multiple dynamic rows
91
+ of tabs. Patch 1612746 Tal Einat.
92
+
93
+ - Add confirmation dialog before printing. Patch 1717170 Tal Einat.
94
+
95
+ - Show paste position if > 80 col. Patch 1659326 Tal Einat.
96
+
97
+ - Update cursor color without restarting. Patch 1725576 Tal Einat.
98
+
99
+ - Allow keyboard interrupt only when user code is executing in subprocess.
100
+ Patch 1225 Tal Einat (reworked from IDLE-Spoon).
101
+
102
+ - configDialog cleanup. Patch 1730217 Tal Einat.
103
+
104
+ - textView cleanup. Patch 1718043 Tal Einat.
105
+
106
+ - Clean up EditorWindow close.
107
+
108
+ - Patch 1693258: Fix for duplicate "preferences" menu-OS X. Backport of r56204.
109
+
110
+ - OSX: Avoid crash for those versions of Tcl/Tk which don't have a console
111
+
112
+ - Bug in idlelib.MultiCall: Options dialog was crashing IDLE if there was an
113
+ option in config-extensions w/o a value. Patch #1672481, Tal Einat
114
+
115
+ - Corrected some bugs in AutoComplete. Also, Page Up/Down in ACW implemented;
116
+ mouse and cursor selection in ACWindow implemented; double Tab inserts
117
+ current selection and closes ACW (similar to double-click and Return); scroll
118
+ wheel now works in ACW. Added AutoComplete instructions to IDLE Help.
119
+
120
+ - AutoCompleteWindow moved below input line, will move above if there
121
+ isn't enough space. Patch 1621265 Tal Einat
122
+
123
+ - Calltips now 'handle' tuples in the argument list (display '<tuple>' :)
124
+ Suggested solution by Christos Georgiou, Bug 791968.
125
+
126
+ - Add 'raw' support to configHandler. Patch 1650174 Tal Einat.
127
+
128
+ - Avoid hang when encountering a duplicate in a completion list. Bug 1571112.
129
+
130
+ - Patch #1362975: Rework CodeContext indentation algorithm to
131
+ avoid hard-coding pixel widths.
132
+
133
+ - Bug #813342: Start the IDLE subprocess with -Qnew if the parent
134
+ is started with that option.
135
+
136
+ - Honor the "Cancel" action in the save dialog (Debian bug #299092)
137
+
138
+ - Some syntax errors were being caught by tokenize during the tabnanny
139
+ check, resulting in obscure error messages. Do the syntax check
140
+ first. Bug 1562716, 1562719
141
+
142
+ - IDLE's version number takes a big jump to match the version number of
143
+ the Python release of which it's a part.
144
+
145
+
146
+ What's New in IDLE 1.2?
147
+ =======================
148
+ *Release date: 19-SEP-2006*
149
+
150
+ - File menu hotkeys: there were three 'p' assignments. Reassign the
151
+ 'Save Copy As' and 'Print' hotkeys to 'y' and 't'. Change the
152
+ Shell hotkey from 's' to 'l'.
153
+
154
+ - IDLE honors new quit() and exit() commands from site.py Quitter() object.
155
+ Patch 1540892, Jim Jewett
156
+
157
+ - The 'with' statement is now a Code Context block opener.
158
+ Patch 1540851, Jim Jewett
159
+
160
+ - Retrieval of previous shell command was not always preserving indentation
161
+ (since 1.2a1) Patch 1528468 Tal Einat.
162
+
163
+ - Changing tokenize (39046) to detect dedent broke tabnanny check (since 1.2a1)
164
+
165
+ - ToggleTab dialog was setting indent to 8 even if cancelled (since 1.2a1).
166
+
167
+ - When used w/o subprocess, all exceptions were preceded by an error
168
+ message claiming they were IDLE internal errors (since 1.2a1).
169
+
170
+ - Bug #1525817: Don't truncate short lines in IDLE's tool tips.
171
+
172
+ - Bug #1517990: IDLE keybindings on MacOS X now work correctly
173
+
174
+ - Bug #1517996: IDLE now longer shows the default Tk menu when a
175
+ path browser, class browser or debugger is the frontmost window on MacOS X
176
+
177
+ - EditorWindow.test() was failing. Bug 1417598
178
+
179
+ - EditorWindow failed when used stand-alone if sys.ps1 not set.
180
+ Bug 1010370 Dave Florek
181
+
182
+ - Tooltips failed on new-syle class __init__ args. Bug 1027566 Loren Guthrie
183
+
184
+ - Avoid occasional failure to detect closing paren properly.
185
+ Patch 1407280 Tal Einat
186
+
187
+ - Rebinding Tab key was inserting 'tab' instead of 'Tab'. Bug 1179168.
188
+
189
+ - Colorizer now handles #<builtin> correctly, also unicode strings and
190
+ 'as' keyword in comment directly following import command. Closes 1325071.
191
+ Patch 1479219 Tal Einat
192
+
193
+ - Patch #1162825: Support non-ASCII characters in IDLE window titles.
194
+
195
+ - Source file f.flush() after writing; trying to avoid lossage if user
196
+ kills GUI.
197
+
198
+ - Options / Keys / Advanced dialog made functional. Also, allow binding
199
+ of 'movement' keys.
200
+
201
+ - 'syntax' patch adds improved calltips and a new class attribute listbox.
202
+ MultiCall module allows binding multiple actions to an event.
203
+ Patch 906702 Noam Raphael
204
+
205
+ - Better indentation after first line of string continuation.
206
+ IDLEfork Patch 681992, Noam Raphael
207
+
208
+ - Fixed CodeContext alignment problem, following suggestion from Tal Einat.
209
+
210
+ - Increased performance in CodeContext extension Patch 936169 Noam Raphael
211
+
212
+ - Mac line endings were incorrect when pasting code from some browsers
213
+ when using X11 and the Fink distribution. Python Bug 1263656.
214
+
215
+ - <Enter> when cursor is on a previous command retrieves that command. Instead
216
+ of replacing the input line, the previous command is now appended to the
217
+ input line. Indentation is preserved, and undo is enabled.
218
+ Patch 1196917 Jeff Shute
219
+
220
+ - Clarify "tab/space" Error Dialog and "Tab Width" Dialog associated with
221
+ the Untabify command.
222
+
223
+ - Corrected "tab/space" Error Dialog to show correct menu for Untabify.
224
+ Patch 1196980 Jeff Shute
225
+
226
+ - New files are colorized by default, and colorizing is removed when
227
+ saving as non-Python files. Patch 1196895 Jeff Shute
228
+ Closes Python Bugs 775012 and 800432, partial fix IDLEfork 763524
229
+
230
+ - Improve subprocess link error notification.
231
+
232
+ - run.py: use Queue's blocking feature instead of sleeping in the main
233
+ loop. Patch # 1190163 Michiel de Hoon
234
+
235
+ - Add config-main option to make the 'history' feature non-cyclic.
236
+ Default remains cyclic. Python Patch 914546 Noam Raphael.
237
+
238
+ - Removed ability to configure tabs indent from Options dialog. This 'feature'
239
+ has never worked and no one has complained. It is still possible to set a
240
+ default tabs (v. spaces) indent 'manually' via config-main.def (or to turn on
241
+ tabs for the current EditorWindow via the Format menu) but IDLE will
242
+ encourage indentation via spaces.
243
+
244
+ - Enable setting the indentation width using the Options dialog.
245
+ Bug # 783877
246
+
247
+ - Add keybindings for del-word-left and del-word-right.
248
+
249
+ - Discourage using an indent width other than 8 when using tabs to indent
250
+ Python code.
251
+
252
+ - Restore use of EditorWindow.set_indentation_params(), was dead code since
253
+ Autoindent was merged into EditorWindow. This allows IDLE to conform to the
254
+ indentation width of a loaded file. (But it still will not switch to tabs
255
+ even if the file uses tabs.) Any change in indent width is local to that
256
+ window.
257
+
258
+ - Add Tabnanny check before Run/F5, not just when Checking module.
259
+
260
+ - If an extension can't be loaded, print warning and skip it instead of
261
+ erroring out.
262
+
263
+ - Improve error handling when .idlerc can't be created (warn and exit).
264
+
265
+ - The GUI was hanging if the shell window was closed while a raw_input()
266
+ was pending. Restored the quit() of the readline() mainloop().
267
+ http://mail.python.org/pipermail/idle-dev/2004-December/002307.html
268
+
269
+ - The remote procedure call module rpc.py can now access data attributes of
270
+ remote registered objects. Changes to these attributes are local, however.
271
+
272
+
273
+ What's New in IDLE 1.1?
274
+ =======================
275
+ *Release date: 30-NOV-2004*
276
+
277
+ - On OpenBSD, terminating IDLE with ctrl-c from the command line caused a
278
+ stuck subprocess MainThread because only the SocketThread was exiting.
279
+
280
+ - Saving a Keyset w/o making changes (by using the "Save as New Custom Key Set"
281
+ button) caused IDLE to fail on restart (no new keyset was created in
282
+ config-keys.cfg). Also true for Theme/highlights. Python Bug 1064535.
283
+
284
+ - A change to the linecache.py API caused IDLE to exit when an exception was
285
+ raised while running without the subprocess (-n switch). Python Bug 1063840.
286
+
287
+ - When paragraph reformat width was made configurable, a bug was
288
+ introduced that caused reformatting of comment blocks to ignore how
289
+ far the block was indented, effectively adding the indentation width
290
+ to the reformat width. This has been repaired, and the reformat
291
+ width is again a bound on the total width of reformatted lines.
292
+
293
+ - Improve keyboard focus binding, especially in Windows menu. Improve
294
+ window raising, especially in the Windows menu and in the debugger.
295
+ IDLEfork 763524.
296
+
297
+ - If user passes a non-existent filename on the commandline, just
298
+ open a new file, don't raise a dialog. IDLEfork 854928.
299
+
300
+ - EditorWindow.py was not finding the .chm help file on Windows. Typo
301
+ at Rev 1.54. Python Bug 990954
302
+
303
+ - checking sys.platform for substring 'win' was breaking IDLE docs on Mac
304
+ (darwin). Also, Mac Safari browser requires full file:// URIs. SF 900580.
305
+
306
+ - Redirect the warning stream to the shell during the ScriptBinding check of
307
+ user code and format the warning similarly to an exception for both that
308
+ check and for runtime warnings raised in the subprocess.
309
+
310
+ - CodeContext hint pane visibility state is now persistent across sessions.
311
+ The pane no longer appears in the shell window. Added capability to limit
312
+ extensions to shell window or editor windows. Noam Raphael addition
313
+ to Patch 936169.
314
+
315
+ - Paragraph reformat width is now a configurable parameter in the
316
+ Options GUI.
317
+
318
+ - New Extension: CodeContext. Provides block structuring hints for code
319
+ which has scrolled above an edit window. Patch 936169 Noam Raphael.
320
+
321
+ - If nulls somehow got into the strings in recent-files.lst
322
+ EditorWindow.update_recent_files_list() was failing. Python Bug 931336.
323
+
324
+ - If the normal background is changed via Configure/Highlighting, it will
325
+ update immediately, thanks to the previously mentioned patch by Nigel Rowe.
326
+
327
+ - Add a highlight theme for builtin keywords. Python Patch 805830 Nigel Rowe
328
+ This also fixed IDLEfork bug [ 693418 ] Normal text background color not
329
+ refreshed and Python bug [897872 ] Unknown color name on HP-UX
330
+
331
+ - rpc.py:SocketIO - Large modules were generating large pickles when downloaded
332
+ to the execution server. The return of the OK response from the subprocess
333
+ initialization was interfering and causing the sending socket to be not
334
+ ready. Add an IO ready test to fix this. Moved the polling IO ready test
335
+ into pollpacket().
336
+
337
+ - Fix typo in rpc.py, s/b "pickle.PicklingError" not "pickle.UnpicklingError".
338
+
339
+ - Added a Tk error dialog to run.py inform the user if the subprocess can't
340
+ connect to the user GUI process. Added a timeout to the GUI's listening
341
+ socket. Added Tk error dialogs to PyShell.py to announce a failure to bind
342
+ the port or connect to the subprocess. Clean up error handling during
343
+ connection initiation phase. This is an update of Python Patch 778323.
344
+
345
+ - Print correct exception even if source file changed since shell was
346
+ restarted. IDLEfork Patch 869012 Noam Raphael
347
+
348
+ - Keybindings with the Shift modifier now work correctly. So do bindings which
349
+ use the Space key. Limit unmodified user keybindings to the function keys.
350
+ Python Bug 775353, IDLEfork Bugs 755647, 761557
351
+
352
+ - After an exception, run.py was not setting the exception vector. Noam
353
+ Raphael suggested correcting this so pdb's postmortem pm() would work.
354
+ IDLEfork Patch 844675
355
+
356
+ - IDLE now does not fail to save the file anymore if the Tk buffer is not a
357
+ Unicode string, yet eol_convention is. Python Bugs 774680, 788378
358
+
359
+ - IDLE didn't start correctly when Python was installed in "Program Files" on
360
+ W2K and XP. Python Bugs 780451, 784183
361
+
362
+ - config-main.def documentation incorrectly referred to idle- instead of
363
+ config- filenames. SF 782759 Also added note about .idlerc location.
364
+
365
+
366
+ What's New in IDLE 1.0?
367
+ =======================
368
+ *Release date: 29-Jul-2003*
369
+
370
+ - Added a banner to the shell discussing warnings possibly raised by personal
371
+ firewall software. Added same comment to README.txt.
372
+
373
+ - Calltip error when docstring was None Python Bug 775541
374
+
375
+ - Updated extend.txt, help.txt, and config-extensions.def to correctly
376
+ reflect the current status of the configuration system. Python Bug 768469
377
+
378
+ - Fixed: Call Tip Trimming May Loop Forever. Python Patch 769142 (Daniels)
379
+
380
+ - Replaced apply(f, args, kwds) with f(*args, **kwargs) to improve performance
381
+ Python Patch 768187
382
+
383
+ - Break or continue statements outside a loop were causing IDLE crash
384
+ Python Bug 767794
385
+
386
+ - Convert Unicode strings from readline to IOBinding.encoding. Also set
387
+ sys.std{in|out|err}.encoding, for both the local and the subprocess case.
388
+ SF IDLEfork patch 682347.
389
+
390
+ - Extend AboutDialog.ViewFile() to support file encodings. Make the CREDITS
391
+ file Latin-1.
392
+
393
+ - Updated the About dialog to reflect re-integration into Python. Provide
394
+ buttons to display Python's NEWS, License, and Credits, plus additional
395
+ buttons for IDLE's README and NEWS.
396
+
397
+ - TextViewer() now has a third parameter which allows inserting text into the
398
+ viewer instead of reading from a file.
399
+
400
+ - (Created the .../Lib/idlelib directory in the Python CVS, which is a clone of
401
+ IDLEfork modified to install in the Python environment. The code in the
402
+ interrupt module has been moved to thread.interrupt_main(). )
403
+
404
+ - Printing the Shell window was failing if it was not saved first SF 748975
405
+
406
+ - When using the Search in Files dialog, if the user had a selection
407
+ highlighted in his Editor window, insert it into the dialog search field.
408
+
409
+ - The Python Shell entry was disappearing from the Windows menu.
410
+
411
+ - Update the Windows file list when a file name change occurs
412
+
413
+ - Change to File / Open Module: always pop up the dialog, using the current
414
+ selection as the default value. This is easier to use habitually.
415
+
416
+ - Avoided a problem with starting the subprocess when 'localhost' doesn't
417
+ resolve to the user's loopback interface. SF 747772
418
+
419
+ - Fixed an issue with highlighted errors never de-colorizing. SF 747677. Also
420
+ improved notification of Tabnanny Token Error.
421
+
422
+ - File / New will by default save in the directory of the Edit window from
423
+ which it was initiated. SF 748973 Guido van Rossum patch.
424
+
425
+
426
+ What's New in IDLEfork 0.9b1?
427
+ =============================
428
+ *Release date: 02-Jun-2003*
429
+
430
+ - The current working directory of the execution environment (and shell
431
+ following completion of execution) is now that of the module being run.
432
+
433
+ - Added the delete-exitfunc option to config-main.def. (This option is not
434
+ included in the Options dialog.) Setting this to True (the default) will
435
+ cause IDLE to not run sys.exitfunc/atexit when the subprocess exits.
436
+
437
+ - IDLE now preserves the line ending codes when editing a file produced on
438
+ a different platform. SF 661759, SF 538584
439
+
440
+ - Reduced default editor font size to 10 point and increased window height
441
+ to provide a better initial impression on Windows.
442
+
443
+ - Options / Fonts/Tabs / Set Base Editor Font: List box was not highlighting
444
+ the default font when first installed on Windows. SF 661676
445
+
446
+ - Added Autosave feature: when user runs code from edit window, if the file
447
+ has been modified IDLE will silently save it if Autosave is enabled. The
448
+ option is set in the Options dialog, and the default is to prompt the
449
+ user to save the file. SF 661318 Bruce Sherwood patch.
450
+
451
+ - Improved the RESTART annotation in the shell window when the user restarts
452
+ the shell while it is generating output. Also improved annotation when user
453
+ repeatedly hammers the Ctrl-F6 restart.
454
+
455
+ - Allow IDLE to run when not installed and cwd is not the IDLE directory
456
+ SF Patch 686254 "Run IDLEfork from any directory without set-up" - Raphael
457
+
458
+ - When a module is run from an EditorWindow: if its directory is not in
459
+ sys.path, prepend it. This allows the module to import other modules in
460
+ the same directory. Do the same for a script run from the command line.
461
+
462
+ - Correctly restart the subprocess if it is running user code and the user
463
+ attempts to run some other module or restarts the shell. Do the same if
464
+ the link is broken and it is possible to restart the subprocess and re-
465
+ connect to the GUI. SF RFE 661321.
466
+
467
+ - Improved exception reporting when running commands or scripts from the
468
+ command line.
469
+
470
+ - Added a -n command line switch to start IDLE without the subprocess.
471
+ Removed the Shell menu when running in that mode. Updated help messages.
472
+
473
+ - Added a comment to the shell startup header to indicate when IDLE is not
474
+ using the subprocess.
475
+
476
+ - Restore the ability to run without the subprocess. This can be important for
477
+ some platforms or configurations. (Running without the subprocess allows the
478
+ debugger to trace through parts of IDLE itself, which may or may not be
479
+ desirable, depending on your point of view. In addition, the traditional
480
+ reload/import tricks must be use if user source code is changed.) This is
481
+ helpful for developing IDLE using IDLE, because one instance can be used to
482
+ edit the code and a separate instance run to test changes. (Multiple
483
+ concurrent IDLE instances with subprocesses is a future feature)
484
+
485
+ - Improve the error message a user gets when saving a file with non-ASCII
486
+ characters and no source encoding is specified. Done by adding a dialog
487
+ 'EncodingMessage', which contains the line to add in a fixed-font entry
488
+ widget, and which has a button to add that line to the file automatically.
489
+ Also, add a configuration option 'EditorWindow/encoding', which has three
490
+ possible values: none, utf-8, and locale. None is the default: IDLE will show
491
+ this dialog when non-ASCII characters are encountered. utf-8 means that files
492
+ with non-ASCII characters are saved as utf-8-with-bom. locale means that
493
+ files are saved in the locale's encoding; the dialog is only displayed if the
494
+ source contains characters outside the locale's charset. SF 710733 - Loewis
495
+
496
+ - Improved I/O response by tweaking the wait parameter in various
497
+ calls to signal.signal().
498
+
499
+ - Implemented a threaded subprocess which allows interrupting a pass
500
+ loop in user code using the 'interrupt' extension. User code runs
501
+ in MainThread, while the RPCServer is handled by SockThread. This is
502
+ necessary because Windows doesn't support signals.
503
+
504
+ - Implemented the 'interrupt' extension module, which allows a subthread
505
+ to raise a KeyboardInterrupt in the main thread.
506
+
507
+ - Attempting to save the shell raised an error related to saving
508
+ breakpoints, which are not implemented in the shell
509
+
510
+ - Provide a correct message when 'exit' or 'quit' are entered at the
511
+ IDLE command prompt SF 695861
512
+
513
+ - Eliminate extra blank line in shell output caused by not flushing
514
+ stdout when user code ends with an unterminated print. SF 695861
515
+
516
+ - Moved responsibility for exception formatting (i.e. pruning IDLE internal
517
+ calls) out of rpc.py into the client and server.
518
+
519
+ - Exit IDLE cleanly even when doing subprocess I/O
520
+
521
+ - Handle subprocess interrupt with an RPC message.
522
+
523
+ - Restart the subprocess if it terminates itself. (VPython programs do that)
524
+
525
+ - Support subclassing of exceptions, including in the shell, by moving the
526
+ exception formatting to the subprocess.
527
+
528
+
529
+ What's New in IDLEfork 0.9 Alpha 2?
530
+ ===================================
531
+ *Release date: 27-Jan-2003*
532
+
533
+ - Updated INSTALL.txt to claify use of the python2 rpm.
534
+
535
+ - Improved formatting in IDLE Help.
536
+
537
+ - Run menu: Replace "Run Script" with "Run Module".
538
+
539
+ - Code encountering an unhandled exception under the debugger now shows
540
+ the correct traceback, with IDLE internal levels pruned out.
541
+
542
+ - If an exception occurs entirely in IDLE, don't prune the IDLE internal
543
+ modules from the traceback displayed.
544
+
545
+ - Class Browser and Path Browser now use Alt-Key-2 for vertical zoom.
546
+
547
+ - IDLE icons will now install correctly even when setup.py is run from the
548
+ build directory
549
+
550
+ - Class Browser now compatible with Python2.3 version of pyclbr.py
551
+
552
+ - Left cursor move in presence of selected text now moves from left end
553
+ of the selection.
554
+
555
+ - Add Meta keybindings to "IDLE Classic Windows" to handle reversed
556
+ Alt/Meta on some Linux distros.
557
+
558
+ - Change default: IDLE now starts with Python Shell.
559
+
560
+ - Removed the File Path from the Additional Help Sources scrolled list.
561
+
562
+ - Add capability to access Additional Help Sources on the web if the
563
+ Help File Path begins with //http or www. (Otherwise local path is
564
+ validated, as before.)
565
+
566
+ - Additional Help Sources were not being posted on the Help menu in the
567
+ order entered. Implement sorting the list by [HelpFiles] 'option'
568
+ number.
569
+
570
+ - Add Browse button to New Help Source dialog. Arrange to start in
571
+ Python/Doc if platform is Windows, otherwise start in current directory.
572
+
573
+ - Put the Additional Help Sources directly on the Help menu instead of in
574
+ an Extra Help cascade menu. Rearrange the Help menu so the Additional
575
+ Help Sources come last. Update help.txt appropriately.
576
+
577
+ - Fix Tk root pop-ups in configSectionNameDialog.py and configDialog.py
578
+
579
+ - Uniform capitalization in General tab of ConfigDialog, update the doc string.
580
+
581
+ - Fix bug in ConfigDialog where SaveAllChangedConfig() was unexpectedly
582
+ deleting Additional Help Sources from the user's config file.
583
+
584
+ - Make configHelpSourceEdit OK button the default and bind <Return>
585
+
586
+ - Fix Tk root pop-ups in configHelpSourceEdit: error dialogs not attached
587
+ to parents.
588
+
589
+ - Use os.startfile() to open both Additional Help and Python Help on the
590
+ Windows platform. The application associated with the file type will act as
591
+ the viewer. Windows help files (.chm) are now supported via the
592
+ Settings/General/Additional Help facility.
593
+
594
+ - If Python Help files are installed locally on Linux, use them instead of
595
+ accessing python.org.
596
+
597
+ - Make the methods for finding the Python help docs more robust, and make
598
+ them work in the installed configuration, also.
599
+
600
+ - On the Save Before Run dialog, make the OK button the default. One
601
+ less mouse action!
602
+
603
+ - Add a method: EditorWindow.get_geometry() for future use in implementing
604
+ window location persistence.
605
+
606
+ - Removed the "Help/Advice" menu entry. Thanks, David! We'll remember!
607
+
608
+ - Change the "Classic Windows" theme's paste key to be <ctrl-v>.
609
+
610
+ - Rearrange the Shell menu to put Stack Viewer entries adjacent.
611
+
612
+ - Add the ability to restart the subprocess interpreter from the shell window;
613
+ add an associated menu entry "Shell/Restart" with binding Control-F6. Update
614
+ IDLE help.
615
+
616
+ - Upon a restart, annotate the shell window with a "restart boundary". Add a
617
+ shell window menu "Shell/View Restart" with binding F6 to jump to the most
618
+ recent restart boundary.
619
+
620
+ - Add Shell menu to Python Shell; change "Settings" to "Options".
621
+
622
+ - Remove incorrect comment in setup.py: IDLEfork is now installed as a package.
623
+
624
+ - Add INSTALL.txt, HISTORY.txt, NEWS.txt to installed configuration.
625
+
626
+ - In installer text, fix reference to Visual Python, should be VPython.
627
+ Properly credit David Scherer.
628
+
629
+ - Modified idle, idle.py, idle.pyw to improve exception handling.
630
+
631
+
632
+ What's New in IDLEfork 0.9 Alpha 1?
633
+ ===================================
634
+ *Release date: 31-Dec-2002*
635
+
636
+ - First release of major new functionality. For further details refer to
637
+ Idle-dev and/or the Sourceforge CVS.
638
+
639
+ - Adapted to the Mac platform.
640
+
641
+ - Overhauled the IDLE startup options and revised the idle -h help message,
642
+ which provides details of command line usage.
643
+
644
+ - Multiple bug fixes and usability enhancements.
645
+
646
+ - Introduced the new RPC implementation, which includes a debugger. The output
647
+ of user code is to the shell, and the shell may be used to inspect the
648
+ environment after the run has finished. (In version 0.8.1 the shell
649
+ environment was separate from the environment of the user code.)
650
+
651
+ - Introduced the configuration GUI and a new About dialog.
652
+
653
+ - Removed David Scherer's Remote Procedure Call code and replaced with Guido
654
+ van Rossum's. GvR code has support for the IDLE debugger and uses the shell
655
+ to inspect the environment of code Run from an Edit window. Files removed:
656
+ ExecBinding.py, loader.py, protocol.py, Remote.py, spawn.py
657
+
658
+ --------------------------------------------------------------------
659
+ Refer to HISTORY.txt for additional information on earlier releases.
660
+ --------------------------------------------------------------------
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/TODO.txt ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Original IDLE todo, much of it now outdated:
2
+ ============================================
3
+ TO DO:
4
+
5
+ - improve debugger:
6
+ - manage breakpoints globally, allow bp deletion, tbreak, cbreak etc.
7
+ - real object browser
8
+ - help on how to use it (a simple help button will do wonders)
9
+ - performance? (updates of large sets of locals are slow)
10
+ - better integration of "debug module"
11
+ - debugger should be global resource (attached to flist, not to shell)
12
+ - fix the stupid bug where you need to step twice
13
+ - display class name in stack viewer entries for methods
14
+ - suppress tracing through IDLE internals (e.g. print) DONE
15
+ - add a button to suppress through a specific module or class or method
16
+ - more object inspection to stack viewer, e.g. to view all array items
17
+ - insert the initial current directory into sys.path DONE
18
+ - default directory attribute for each window instead of only for windows
19
+ that have an associated filename
20
+ - command expansion from keywords, module contents, other buffers, etc.
21
+ - "Recent documents" menu item DONE
22
+ - Filter region command
23
+ - Optional horizontal scroll bar
24
+ - more Emacsisms:
25
+ - ^K should cut to buffer
26
+ - M-[, M-] to move by paragraphs
27
+ - incremental search?
28
+ - search should indicate wrap-around in some way
29
+ - restructure state sensitive code to avoid testing flags all the time
30
+ - persistent user state (e.g. window and cursor positions, bindings)
31
+ - make backups when saving
32
+ - check file mtimes at various points
33
+ - Pluggable interface with RCS/CVS/Perforce/Clearcase
34
+ - better help?
35
+ - don't open second class browser on same module (nor second path browser)
36
+ - unify class and path browsers
37
+ - Need to define a standard way whereby one can determine one is running
38
+ inside IDLE (needed for Tk mainloop, also handy for $PYTHONSTARTUP)
39
+ - Add more utility methods for use by extensions (a la get_selection)
40
+ - Way to run command in totally separate interpreter (fork+os.system?) DONE
41
+ - Way to find definition of fully-qualified name:
42
+ In other words, select "UserDict.UserDict", hit some magic key and
43
+ it loads up UserDict.py and finds the first def or class for UserDict.
44
+ - need a way to force colorization on/off
45
+ - need a way to force auto-indent on/off
46
+
47
+ Details:
48
+
49
+ - ^O (on Unix -- open-line) should honor autoindent
50
+ - after paste, show end of pasted text
51
+ - on Windows, should turn short filename to long filename (not only in argv!)
52
+ (shouldn't this be done -- or undone -- by ntpath.normpath?)
53
+ - new autoindent after colon even indents when the colon is in a comment!
54
+ - sometimes forward slashes in pathname remain
55
+ - sometimes star in window name remains in Windows menu
56
+ - With unix bindings, ESC by itself is ignored
57
+ - Sometimes for no apparent reason a selection from the cursor to the
58
+ end of the command buffer appears, which is hard to get rid of
59
+ because it stays when you are typing!
60
+ - The Line/Col in the status bar can be wrong initially in PyShell DONE
61
+
62
+ Structural problems:
63
+
64
+ - too much knowledge in FileList about EditorWindow (for example)
65
+ - should add some primitives for accessing the selection etc.
66
+ to repeat cumbersome code over and over
67
+
68
+ ======================================================================
69
+
70
+ Jeff Bauer suggests:
71
+
72
+ - Open Module doesn't appear to handle hierarchical packages.
73
+ - Class browser should also allow hierarchical packages.
74
+ - Open and Open Module could benefit from a history, DONE
75
+ either command line style, or Microsoft recent-file
76
+ style.
77
+ - Add a Smalltalk-style inspector (i.e. Tkinspect)
78
+
79
+ The last suggestion is already a reality, but not yet
80
+ integrated into IDLE. I use a module called inspector.py,
81
+ that used to be available from python.org(?) It no longer
82
+ appears to be in the contributed section, and the source
83
+ has no author attribution.
84
+
85
+ In any case, the code is useful for visually navigating
86
+ an object's attributes, including its container hierarchy.
87
+
88
+ >>> from inspector import Tkinspect
89
+ >>> Tkinspect(None, myObject)
90
+
91
+ Tkinspect could probably be extended and refined to
92
+ integrate better into IDLE.
93
+
94
+ ======================================================================
95
+
96
+ Comparison to PTUI
97
+ ------------------
98
+
99
+ + PTUI's help is better (HTML!)
100
+
101
+ + PTUI can attach a shell to any module
102
+
103
+ + PTUI has some more I/O commands:
104
+ open multiple
105
+ append
106
+ examine (what's that?)
107
+
108
+ ======================================================================
109
+
110
+ Notes after trying to run Grail
111
+ -------------------------------
112
+
113
+ - Grail does stuff to sys.path based on sys.argv[0]; you must set
114
+ sys.argv[0] to something decent first (it is normally set to the path of
115
+ the idle script).
116
+
117
+ - Grail must be exec'ed in __main__ because that's imported by some
118
+ other parts of Grail.
119
+
120
+ - Grail uses a module called History and so does idle :-(
121
+
122
+ ======================================================================
123
+
124
+ Robin Friedrich's items:
125
+
126
+ Things I'd like to see:
127
+ - I'd like support for shift-click extending the selection. There's a
128
+ bug now that it doesn't work the first time you try it.
129
+ - Printing is needed. How hard can that be on Windows? FIRST CUT DONE
130
+ - The python-mode trick of autoindenting a line with <tab> is neat and
131
+ very handy.
132
+ - (someday) a spellchecker for docstrings and comments.
133
+ - a pagedown/up command key which moves to next class/def statement (top
134
+ level)
135
+ - split window capability
136
+ - DnD text relocation/copying
137
+
138
+ Things I don't want to see.
139
+ - line numbers... will probably slow things down way too much.
140
+ - Please use another icon for the tree browser leaf. The small snake
141
+ isn't cutting it.
142
+
143
+ ----------------------------------------------------------------------
144
+
145
+ - Customizable views (multi-window or multi-pane). (Markus Gritsch)
146
+
147
+ - Being able to double click (maybe double right click) on a callable
148
+ object in the editor which shows the source of the object, if
149
+ possible. (Gerrit Holl)
150
+
151
+ - Hooks into the guts, like in Emacs. (Mike Romberg)
152
+
153
+ - Sharing the editor with a remote tutor. (Martijn Faassen)
154
+
155
+ - Multiple views on the same file. (Tony J Ibbs)
156
+
157
+ - Store breakpoints in a global (per-project) database (GvR); Dirk
158
+ Heise adds: save some space-trimmed context and search around when
159
+ reopening a file that might have been edited by someone else.
160
+
161
+ - Capture menu events in extensions without changing the IDLE source.
162
+ (Matthias Barmeier)
163
+
164
+ - Use overlapping panels (a "notebook" in MFC terms I think) for info
165
+ that doesn't need to be accessible simultaneously (e.g. HTML source
166
+ and output). Use multi-pane windows for info that does need to be
167
+ shown together (e.g. class browser and source). (Albert Brandl)
168
+
169
+ - A project should invisibly track all symbols, for instant search,
170
+ replace and cross-ref. Projects should be allowed to span multiple
171
+ directories, hosts, etc. Project management files are placed in a
172
+ directory you specify. A global mapping between project names and
173
+ project directories should exist [not so sure --GvR]. (Tim Peters)
174
+
175
+ - Merge attr-tips and auto-expand. (Mark Hammond, Tim Peters)
176
+
177
+ - Python Shell should behave more like a "shell window" as users know
178
+ it -- i.e. you can only edit the current command, and the cursor can't
179
+ escape from the command area. (Albert Brandl)
180
+
181
+ - Set X11 class to "idle/Idle", set icon and title to something
182
+ beginning with "idle" -- for window manangers. (Randall Hopper)
183
+
184
+ - Config files editable through a preferences dialog. (me) DONE
185
+
186
+ - Config files still editable outside the preferences dialog.
187
+ (Randall Hopper) DONE
188
+
189
+ - When you're editing a command in PyShell, and there are only blank
190
+ lines below the cursor, hitting Return should ignore or delete those
191
+ blank lines rather than deciding you're not on the last line. (me)
192
+
193
+ - Run command (F5 c.s.) should be more like Pythonwin's Run -- a
194
+ dialog with options to give command line arguments, run the debugger,
195
+ etc. (me)
196
+
197
+ - Shouldn't be able to delete part of the prompt (or any text before
198
+ it) in the PyShell. (Martijn Faassen) DONE
199
+
200
+ - Emacs style auto-fill (also smart about comments and strings).
201
+ (Jeremy Hylton)
202
+
203
+ - Output of Run Script should go to a separate output window, not to
204
+ the shell window. Output of separate runs should all go to the same
205
+ window but clearly delimited. (David Scherer) REJECT FIRST, LATTER DONE
206
+
207
+ - GUI form designer to kick VB's butt. (Robert Geiger) THAT'S NOT IDLE
208
+
209
+ - Printing! Possibly via generation of PDF files which the user must
210
+ then send to the printer separately. (Dinu Gherman) FIRST CUT
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/__init__.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ """The idlelib package implements the Idle application.
2
+
3
+ Idle includes an interactive shell and editor.
4
+ Starting with Python 3.6, IDLE requires tcl/tk 8.5 or later.
5
+ Use the files named idle.* to start Idle.
6
+
7
+ The other files are private implementations. Their details are subject to
8
+ change. See PEP 434 for more. Import them at your own risk.
9
+ """
10
+ testing = False # Set True by test.test_idle.
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/autocomplete.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Complete either attribute names or file names.
2
+
3
+ Either on demand or after a user-selected delay after a key character,
4
+ pop up a list of candidates.
5
+ """
6
+ import __main__
7
+ import keyword
8
+ import os
9
+ import string
10
+ import sys
11
+
12
+ # Two types of completions; defined here for autocomplete_w import below.
13
+ ATTRS, FILES = 0, 1
14
+ from idlelib import autocomplete_w
15
+ from idlelib.config import idleConf
16
+ from idlelib.hyperparser import HyperParser
17
+
18
+ # Tuples passed to open_completions.
19
+ # EvalFunc, Complete, WantWin, Mode
20
+ FORCE = True, False, True, None # Control-Space.
21
+ TAB = False, True, True, None # Tab.
22
+ TRY_A = False, False, False, ATTRS # '.' for attributes.
23
+ TRY_F = False, False, False, FILES # '/' in quotes for file name.
24
+
25
+ # This string includes all chars that may be in an identifier.
26
+ # TODO Update this here and elsewhere.
27
+ ID_CHARS = string.ascii_letters + string.digits + "_"
28
+
29
+ SEPS = f"{os.sep}{os.altsep if os.altsep else ''}"
30
+ TRIGGERS = f".{SEPS}"
31
+
32
+ class AutoComplete:
33
+
34
+ def __init__(self, editwin=None):
35
+ self.editwin = editwin
36
+ if editwin is not None: # not in subprocess or no-gui test
37
+ self.text = editwin.text
38
+ self.autocompletewindow = None
39
+ # id of delayed call, and the index of the text insert when
40
+ # the delayed call was issued. If _delayed_completion_id is
41
+ # None, there is no delayed call.
42
+ self._delayed_completion_id = None
43
+ self._delayed_completion_index = None
44
+
45
+ @classmethod
46
+ def reload(cls):
47
+ cls.popupwait = idleConf.GetOption(
48
+ "extensions", "AutoComplete", "popupwait", type="int", default=0)
49
+
50
+ def _make_autocomplete_window(self): # Makes mocking easier.
51
+ return autocomplete_w.AutoCompleteWindow(self.text)
52
+
53
+ def _remove_autocomplete_window(self, event=None):
54
+ if self.autocompletewindow:
55
+ self.autocompletewindow.hide_window()
56
+ self.autocompletewindow = None
57
+
58
+ def force_open_completions_event(self, event):
59
+ "(^space) Open completion list, even if a function call is needed."
60
+ self.open_completions(FORCE)
61
+ return "break"
62
+
63
+ def autocomplete_event(self, event):
64
+ "(tab) Complete word or open list if multiple options."
65
+ if hasattr(event, "mc_state") and event.mc_state or\
66
+ not self.text.get("insert linestart", "insert").strip():
67
+ # A modifier was pressed along with the tab or
68
+ # there is only previous whitespace on this line, so tab.
69
+ return None
70
+ if self.autocompletewindow and self.autocompletewindow.is_active():
71
+ self.autocompletewindow.complete()
72
+ return "break"
73
+ else:
74
+ opened = self.open_completions(TAB)
75
+ return "break" if opened else None
76
+
77
+ def try_open_completions_event(self, event=None):
78
+ "(./) Open completion list after pause with no movement."
79
+ lastchar = self.text.get("insert-1c")
80
+ if lastchar in TRIGGERS:
81
+ args = TRY_A if lastchar == "." else TRY_F
82
+ self._delayed_completion_index = self.text.index("insert")
83
+ if self._delayed_completion_id is not None:
84
+ self.text.after_cancel(self._delayed_completion_id)
85
+ self._delayed_completion_id = self.text.after(
86
+ self.popupwait, self._delayed_open_completions, args)
87
+
88
+ def _delayed_open_completions(self, args):
89
+ "Call open_completions if index unchanged."
90
+ self._delayed_completion_id = None
91
+ if self.text.index("insert") == self._delayed_completion_index:
92
+ self.open_completions(args)
93
+
94
+ def open_completions(self, args):
95
+ """Find the completions and create the AutoCompleteWindow.
96
+ Return True if successful (no syntax error or so found).
97
+ If complete is True, then if there's nothing to complete and no
98
+ start of completion, won't open completions and return False.
99
+ If mode is given, will open a completion list only in this mode.
100
+ """
101
+ evalfuncs, complete, wantwin, mode = args
102
+ # Cancel another delayed call, if it exists.
103
+ if self._delayed_completion_id is not None:
104
+ self.text.after_cancel(self._delayed_completion_id)
105
+ self._delayed_completion_id = None
106
+
107
+ hp = HyperParser(self.editwin, "insert")
108
+ curline = self.text.get("insert linestart", "insert")
109
+ i = j = len(curline)
110
+ if hp.is_in_string() and (not mode or mode==FILES):
111
+ # Find the beginning of the string.
112
+ # fetch_completions will look at the file system to determine
113
+ # whether the string value constitutes an actual file name
114
+ # XXX could consider raw strings here and unescape the string
115
+ # value if it's not raw.
116
+ self._remove_autocomplete_window()
117
+ mode = FILES
118
+ # Find last separator or string start
119
+ while i and curline[i-1] not in "'\"" + SEPS:
120
+ i -= 1
121
+ comp_start = curline[i:j]
122
+ j = i
123
+ # Find string start
124
+ while i and curline[i-1] not in "'\"":
125
+ i -= 1
126
+ comp_what = curline[i:j]
127
+ elif hp.is_in_code() and (not mode or mode==ATTRS):
128
+ self._remove_autocomplete_window()
129
+ mode = ATTRS
130
+ while i and (curline[i-1] in ID_CHARS or ord(curline[i-1]) > 127):
131
+ i -= 1
132
+ comp_start = curline[i:j]
133
+ if i and curline[i-1] == '.': # Need object with attributes.
134
+ hp.set_index("insert-%dc" % (len(curline)-(i-1)))
135
+ comp_what = hp.get_expression()
136
+ if (not comp_what or
137
+ (not evalfuncs and comp_what.find('(') != -1)):
138
+ return None
139
+ else:
140
+ comp_what = ""
141
+ else:
142
+ return None
143
+
144
+ if complete and not comp_what and not comp_start:
145
+ return None
146
+ comp_lists = self.fetch_completions(comp_what, mode)
147
+ if not comp_lists[0]:
148
+ return None
149
+ self.autocompletewindow = self._make_autocomplete_window()
150
+ return not self.autocompletewindow.show_window(
151
+ comp_lists, "insert-%dc" % len(comp_start),
152
+ complete, mode, wantwin)
153
+
154
+ def fetch_completions(self, what, mode):
155
+ """Return a pair of lists of completions for something. The first list
156
+ is a sublist of the second. Both are sorted.
157
+
158
+ If there is a Python subprocess, get the comp. list there. Otherwise,
159
+ either fetch_completions() is running in the subprocess itself or it
160
+ was called in an IDLE EditorWindow before any script had been run.
161
+
162
+ The subprocess environment is that of the most recently run script. If
163
+ two unrelated modules are being edited some calltips in the current
164
+ module may be inoperative if the module was not the last to run.
165
+ """
166
+ try:
167
+ rpcclt = self.editwin.flist.pyshell.interp.rpcclt
168
+ except:
169
+ rpcclt = None
170
+ if rpcclt:
171
+ return rpcclt.remotecall("exec", "get_the_completion_list",
172
+ (what, mode), {})
173
+ else:
174
+ if mode == ATTRS:
175
+ if what == "": # Main module names.
176
+ namespace = {**__main__.__builtins__.__dict__,
177
+ **__main__.__dict__}
178
+ bigl = eval("dir()", namespace)
179
+ kwds = (s for s in keyword.kwlist
180
+ if s not in {'True', 'False', 'None'})
181
+ bigl.extend(kwds)
182
+ bigl.sort()
183
+ if "__all__" in bigl:
184
+ smalll = sorted(eval("__all__", namespace))
185
+ else:
186
+ smalll = [s for s in bigl if s[:1] != '_']
187
+ else:
188
+ try:
189
+ entity = self.get_entity(what)
190
+ bigl = dir(entity)
191
+ bigl.sort()
192
+ if "__all__" in bigl:
193
+ smalll = sorted(entity.__all__)
194
+ else:
195
+ smalll = [s for s in bigl if s[:1] != '_']
196
+ except:
197
+ return [], []
198
+
199
+ elif mode == FILES:
200
+ if what == "":
201
+ what = "."
202
+ try:
203
+ expandedpath = os.path.expanduser(what)
204
+ bigl = os.listdir(expandedpath)
205
+ bigl.sort()
206
+ smalll = [s for s in bigl if s[:1] != '.']
207
+ except OSError:
208
+ return [], []
209
+
210
+ if not smalll:
211
+ smalll = bigl
212
+ return smalll, bigl
213
+
214
+ def get_entity(self, name):
215
+ "Lookup name in a namespace spanning sys.modules and __main.dict__."
216
+ return eval(name, {**sys.modules, **__main__.__dict__})
217
+
218
+
219
+ AutoComplete.reload()
220
+
221
+ if __name__ == '__main__':
222
+ from unittest import main
223
+ main('idlelib.idle_test.test_autocomplete', verbosity=2)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/autoexpand.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''Complete the current word before the cursor with words in the editor.
2
+
3
+ Each menu selection or shortcut key selection replaces the word with a
4
+ different word with the same prefix. The search for matches begins
5
+ before the target and moves toward the top of the editor. It then starts
6
+ after the cursor and moves down. It then returns to the original word and
7
+ the cycle starts again.
8
+
9
+ Changing the current text line or leaving the cursor in a different
10
+ place before requesting the next selection causes AutoExpand to reset
11
+ its state.
12
+
13
+ There is only one instance of Autoexpand.
14
+ '''
15
+ import re
16
+ import string
17
+
18
+
19
+ class AutoExpand:
20
+ wordchars = string.ascii_letters + string.digits + "_"
21
+
22
+ def __init__(self, editwin):
23
+ self.text = editwin.text
24
+ self.bell = self.text.bell
25
+ self.state = None
26
+
27
+ def expand_word_event(self, event):
28
+ "Replace the current word with the next expansion."
29
+ curinsert = self.text.index("insert")
30
+ curline = self.text.get("insert linestart", "insert lineend")
31
+ if not self.state:
32
+ words = self.getwords()
33
+ index = 0
34
+ else:
35
+ words, index, insert, line = self.state
36
+ if insert != curinsert or line != curline:
37
+ words = self.getwords()
38
+ index = 0
39
+ if not words:
40
+ self.bell()
41
+ return "break"
42
+ word = self.getprevword()
43
+ self.text.delete("insert - %d chars" % len(word), "insert")
44
+ newword = words[index]
45
+ index = (index + 1) % len(words)
46
+ if index == 0:
47
+ self.bell() # Warn we cycled around
48
+ self.text.insert("insert", newword)
49
+ curinsert = self.text.index("insert")
50
+ curline = self.text.get("insert linestart", "insert lineend")
51
+ self.state = words, index, curinsert, curline
52
+ return "break"
53
+
54
+ def getwords(self):
55
+ "Return a list of words that match the prefix before the cursor."
56
+ word = self.getprevword()
57
+ if not word:
58
+ return []
59
+ before = self.text.get("1.0", "insert wordstart")
60
+ wbefore = re.findall(r"\b" + word + r"\w+\b", before)
61
+ del before
62
+ after = self.text.get("insert wordend", "end")
63
+ wafter = re.findall(r"\b" + word + r"\w+\b", after)
64
+ del after
65
+ if not wbefore and not wafter:
66
+ return []
67
+ words = []
68
+ dict = {}
69
+ # search backwards through words before
70
+ wbefore.reverse()
71
+ for w in wbefore:
72
+ if dict.get(w):
73
+ continue
74
+ words.append(w)
75
+ dict[w] = w
76
+ # search onwards through words after
77
+ for w in wafter:
78
+ if dict.get(w):
79
+ continue
80
+ words.append(w)
81
+ dict[w] = w
82
+ words.append(word)
83
+ return words
84
+
85
+ def getprevword(self):
86
+ "Return the word prefix before the cursor."
87
+ line = self.text.get("insert linestart", "insert")
88
+ i = len(line)
89
+ while i > 0 and line[i-1] in self.wordchars:
90
+ i = i-1
91
+ return line[i:]
92
+
93
+
94
+ if __name__ == '__main__':
95
+ from unittest import main
96
+ main('idlelib.idle_test.test_autoexpand', verbosity=2)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/calltip.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Pop up a reminder of how to call a function.
2
+
3
+ Call Tips are floating windows which display function, class, and method
4
+ parameter and docstring information when you type an opening parenthesis, and
5
+ which disappear when you type a closing parenthesis.
6
+ """
7
+ import __main__
8
+ import inspect
9
+ import re
10
+ import sys
11
+ import textwrap
12
+ import types
13
+
14
+ from idlelib import calltip_w
15
+ from idlelib.hyperparser import HyperParser
16
+
17
+
18
+ class Calltip:
19
+
20
+ def __init__(self, editwin=None):
21
+ if editwin is None: # subprocess and test
22
+ self.editwin = None
23
+ else:
24
+ self.editwin = editwin
25
+ self.text = editwin.text
26
+ self.active_calltip = None
27
+ self._calltip_window = self._make_tk_calltip_window
28
+
29
+ def close(self):
30
+ self._calltip_window = None
31
+
32
+ def _make_tk_calltip_window(self):
33
+ # See __init__ for usage
34
+ return calltip_w.CalltipWindow(self.text)
35
+
36
+ def remove_calltip_window(self, event=None):
37
+ if self.active_calltip:
38
+ self.active_calltip.hidetip()
39
+ self.active_calltip = None
40
+
41
+ def force_open_calltip_event(self, event):
42
+ "The user selected the menu entry or hotkey, open the tip."
43
+ self.open_calltip(True)
44
+ return "break"
45
+
46
+ def try_open_calltip_event(self, event):
47
+ """Happens when it would be nice to open a calltip, but not really
48
+ necessary, for example after an opening bracket, so function calls
49
+ won't be made.
50
+ """
51
+ self.open_calltip(False)
52
+
53
+ def refresh_calltip_event(self, event):
54
+ if self.active_calltip and self.active_calltip.tipwindow:
55
+ self.open_calltip(False)
56
+
57
+ def open_calltip(self, evalfuncs):
58
+ """Maybe close an existing calltip and maybe open a new calltip.
59
+
60
+ Called from (force_open|try_open|refresh)_calltip_event functions.
61
+ """
62
+ hp = HyperParser(self.editwin, "insert")
63
+ sur_paren = hp.get_surrounding_brackets('(')
64
+
65
+ # If not inside parentheses, no calltip.
66
+ if not sur_paren:
67
+ self.remove_calltip_window()
68
+ return
69
+
70
+ # If a calltip is shown for the current parentheses, do
71
+ # nothing.
72
+ if self.active_calltip:
73
+ opener_line, opener_col = map(int, sur_paren[0].split('.'))
74
+ if (
75
+ (opener_line, opener_col) ==
76
+ (self.active_calltip.parenline, self.active_calltip.parencol)
77
+ ):
78
+ return
79
+
80
+ hp.set_index(sur_paren[0])
81
+ try:
82
+ expression = hp.get_expression()
83
+ except ValueError:
84
+ expression = None
85
+ if not expression:
86
+ # No expression before the opening parenthesis, e.g.
87
+ # because it's in a string or the opener for a tuple:
88
+ # Do nothing.
89
+ return
90
+
91
+ # At this point, the current index is after an opening
92
+ # parenthesis, in a section of code, preceded by a valid
93
+ # expression. If there is a calltip shown, it's not for the
94
+ # same index and should be closed.
95
+ self.remove_calltip_window()
96
+
97
+ # Simple, fast heuristic: If the preceding expression includes
98
+ # an opening parenthesis, it likely includes a function call.
99
+ if not evalfuncs and (expression.find('(') != -1):
100
+ return
101
+
102
+ argspec = self.fetch_tip(expression)
103
+ if not argspec:
104
+ return
105
+ self.active_calltip = self._calltip_window()
106
+ self.active_calltip.showtip(argspec, sur_paren[0], sur_paren[1])
107
+
108
+ def fetch_tip(self, expression):
109
+ """Return the argument list and docstring of a function or class.
110
+
111
+ If there is a Python subprocess, get the calltip there. Otherwise,
112
+ either this fetch_tip() is running in the subprocess or it was
113
+ called in an IDLE running without the subprocess.
114
+
115
+ The subprocess environment is that of the most recently run script. If
116
+ two unrelated modules are being edited some calltips in the current
117
+ module may be inoperative if the module was not the last to run.
118
+
119
+ To find methods, fetch_tip must be fed a fully qualified name.
120
+
121
+ """
122
+ try:
123
+ rpcclt = self.editwin.flist.pyshell.interp.rpcclt
124
+ except AttributeError:
125
+ rpcclt = None
126
+ if rpcclt:
127
+ return rpcclt.remotecall("exec", "get_the_calltip",
128
+ (expression,), {})
129
+ else:
130
+ return get_argspec(get_entity(expression))
131
+
132
+
133
+ def get_entity(expression):
134
+ """Return the object corresponding to expression evaluated
135
+ in a namespace spanning sys.modules and __main.dict__.
136
+ """
137
+ if expression:
138
+ namespace = {**sys.modules, **__main__.__dict__}
139
+ try:
140
+ return eval(expression, namespace) # Only protect user code.
141
+ except BaseException:
142
+ # An uncaught exception closes idle, and eval can raise any
143
+ # exception, especially if user classes are involved.
144
+ return None
145
+
146
+ # The following are used in get_argspec and some in tests
147
+ _MAX_COLS = 85
148
+ _MAX_LINES = 5 # enough for bytes
149
+ _INDENT = ' '*4 # for wrapped signatures
150
+ _first_param = re.compile(r'(?<=\()\w*\,?\s*')
151
+ _default_callable_argspec = "See source or doc"
152
+ _invalid_method = "invalid method signature"
153
+
154
+ def get_argspec(ob):
155
+ '''Return a string describing the signature of a callable object, or ''.
156
+
157
+ For Python-coded functions and methods, the first line is introspected.
158
+ Delete 'self' parameter for classes (.__init__) and bound methods.
159
+ The next lines are the first lines of the doc string up to the first
160
+ empty line or _MAX_LINES. For builtins, this typically includes
161
+ the arguments in addition to the return value.
162
+ '''
163
+ # Determine function object fob to inspect.
164
+ try:
165
+ ob_call = ob.__call__
166
+ except BaseException: # Buggy user object could raise anything.
167
+ return '' # No popup for non-callables.
168
+ # For Get_argspecTest.test_buggy_getattr_class, CallA() & CallB().
169
+ fob = ob_call if isinstance(ob_call, types.MethodType) else ob
170
+
171
+ # Initialize argspec and wrap it to get lines.
172
+ try:
173
+ argspec = str(inspect.signature(fob))
174
+ except Exception as err:
175
+ msg = str(err)
176
+ if msg.startswith(_invalid_method):
177
+ return _invalid_method
178
+ else:
179
+ argspec = ''
180
+
181
+ if isinstance(fob, type) and argspec == '()':
182
+ # If fob has no argument, use default callable argspec.
183
+ argspec = _default_callable_argspec
184
+
185
+ lines = (textwrap.wrap(argspec, _MAX_COLS, subsequent_indent=_INDENT)
186
+ if len(argspec) > _MAX_COLS else [argspec] if argspec else [])
187
+
188
+ # Augment lines from docstring, if any, and join to get argspec.
189
+ doc = inspect.getdoc(ob)
190
+ if doc:
191
+ for line in doc.split('\n', _MAX_LINES)[:_MAX_LINES]:
192
+ line = line.strip()
193
+ if not line:
194
+ break
195
+ if len(line) > _MAX_COLS:
196
+ line = line[: _MAX_COLS - 3] + '...'
197
+ lines.append(line)
198
+ argspec = '\n'.join(lines)
199
+
200
+ return argspec or _default_callable_argspec
201
+
202
+
203
+ if __name__ == '__main__':
204
+ from unittest import main
205
+ main('idlelib.idle_test.test_calltip', verbosity=2)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/codecontext.py ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """codecontext - display the block context above the edit window
2
+
3
+ Once code has scrolled off the top of a window, it can be difficult to
4
+ determine which block you are in. This extension implements a pane at the top
5
+ of each IDLE edit window which provides block structure hints. These hints are
6
+ the lines which contain the block opening keywords, e.g. 'if', for the
7
+ enclosing block. The number of hint lines is determined by the maxlines
8
+ variable in the codecontext section of config-extensions.def. Lines which do
9
+ not open blocks are not shown in the context hints pane.
10
+
11
+ For EditorWindows, <<toggle-code-context>> is bound to CodeContext(self).
12
+ toggle_code_context_event.
13
+ """
14
+ import re
15
+ from sys import maxsize as INFINITY
16
+
17
+ from tkinter import Frame, Text, TclError
18
+ from tkinter.constants import NSEW, SUNKEN
19
+
20
+ from idlelib.config import idleConf
21
+
22
+ BLOCKOPENERS = {'class', 'def', 'if', 'elif', 'else', 'while', 'for',
23
+ 'try', 'except', 'finally', 'with', 'async'}
24
+
25
+
26
+ def get_spaces_firstword(codeline, c=re.compile(r"^(\s*)(\w*)")):
27
+ "Extract the beginning whitespace and first word from codeline."
28
+ return c.match(codeline).groups()
29
+
30
+
31
+ def get_line_info(codeline):
32
+ """Return tuple of (line indent value, codeline, block start keyword).
33
+
34
+ The indentation of empty lines (or comment lines) is INFINITY.
35
+ If the line does not start a block, the keyword value is False.
36
+ """
37
+ spaces, firstword = get_spaces_firstword(codeline)
38
+ indent = len(spaces)
39
+ if len(codeline) == indent or codeline[indent] == '#':
40
+ indent = INFINITY
41
+ opener = firstword in BLOCKOPENERS and firstword
42
+ return indent, codeline, opener
43
+
44
+
45
+ class CodeContext:
46
+ "Display block context above the edit window."
47
+ UPDATEINTERVAL = 100 # millisec
48
+
49
+ def __init__(self, editwin):
50
+ """Initialize settings for context block.
51
+
52
+ editwin is the Editor window for the context block.
53
+ self.text is the editor window text widget.
54
+
55
+ self.context displays the code context text above the editor text.
56
+ Initially None, it is toggled via <<toggle-code-context>>.
57
+ self.topvisible is the number of the top text line displayed.
58
+ self.info is a list of (line number, indent level, line text,
59
+ block keyword) tuples for the block structure above topvisible.
60
+ self.info[0] is initialized with a 'dummy' line which
61
+ starts the toplevel 'block' of the module.
62
+
63
+ self.t1 and self.t2 are two timer events on the editor text widget to
64
+ monitor for changes to the context text or editor font.
65
+ """
66
+ self.editwin = editwin
67
+ self.text = editwin.text
68
+ self._reset()
69
+
70
+ def _reset(self):
71
+ self.context = None
72
+ self.cell00 = None
73
+ self.t1 = None
74
+ self.topvisible = 1
75
+ self.info = [(0, -1, "", False)]
76
+
77
+ @classmethod
78
+ def reload(cls):
79
+ "Load class variables from config."
80
+ cls.context_depth = idleConf.GetOption("extensions", "CodeContext",
81
+ "maxlines", type="int",
82
+ default=15)
83
+
84
+ def __del__(self):
85
+ "Cancel scheduled events."
86
+ if self.t1 is not None:
87
+ try:
88
+ self.text.after_cancel(self.t1)
89
+ except TclError: # pragma: no cover
90
+ pass
91
+ self.t1 = None
92
+
93
+ def toggle_code_context_event(self, event=None):
94
+ """Toggle code context display.
95
+
96
+ If self.context doesn't exist, create it to match the size of the editor
97
+ window text (toggle on). If it does exist, destroy it (toggle off).
98
+ Return 'break' to complete the processing of the binding.
99
+ """
100
+ if self.context is None:
101
+ # Calculate the border width and horizontal padding required to
102
+ # align the context with the text in the main Text widget.
103
+ #
104
+ # All values are passed through getint(), since some
105
+ # values may be pixel objects, which can't simply be added to ints.
106
+ widgets = self.editwin.text, self.editwin.text_frame
107
+ # Calculate the required horizontal padding and border width.
108
+ padx = 0
109
+ border = 0
110
+ for widget in widgets:
111
+ info = (widget.grid_info()
112
+ if widget is self.editwin.text
113
+ else widget.pack_info())
114
+ padx += widget.tk.getint(info['padx'])
115
+ padx += widget.tk.getint(widget.cget('padx'))
116
+ border += widget.tk.getint(widget.cget('border'))
117
+ context = self.context = Text(
118
+ self.editwin.text_frame,
119
+ height=1,
120
+ width=1, # Don't request more than we get.
121
+ highlightthickness=0,
122
+ padx=padx, border=border, relief=SUNKEN, state='disabled')
123
+ self.update_font()
124
+ self.update_highlight_colors()
125
+ context.bind('<ButtonRelease-1>', self.jumptoline)
126
+ # Get the current context and initiate the recurring update event.
127
+ self.timer_event()
128
+ # Grid the context widget above the text widget.
129
+ context.grid(row=0, column=1, sticky=NSEW)
130
+
131
+ line_number_colors = idleConf.GetHighlight(idleConf.CurrentTheme(),
132
+ 'linenumber')
133
+ self.cell00 = Frame(self.editwin.text_frame,
134
+ bg=line_number_colors['background'])
135
+ self.cell00.grid(row=0, column=0, sticky=NSEW)
136
+ menu_status = 'Hide'
137
+ else:
138
+ self.context.destroy()
139
+ self.context = None
140
+ self.cell00.destroy()
141
+ self.cell00 = None
142
+ self.text.after_cancel(self.t1)
143
+ self._reset()
144
+ menu_status = 'Show'
145
+ self.editwin.update_menu_label(menu='options', index='*ode*ontext',
146
+ label=f'{menu_status} Code Context')
147
+ return "break"
148
+
149
+ def get_context(self, new_topvisible, stopline=1, stopindent=0):
150
+ """Return a list of block line tuples and the 'last' indent.
151
+
152
+ The tuple fields are (linenum, indent, text, opener).
153
+ The list represents header lines from new_topvisible back to
154
+ stopline with successively shorter indents > stopindent.
155
+ The list is returned ordered by line number.
156
+ Last indent returned is the smallest indent observed.
157
+ """
158
+ assert stopline > 0
159
+ lines = []
160
+ # The indentation level we are currently in.
161
+ lastindent = INFINITY
162
+ # For a line to be interesting, it must begin with a block opening
163
+ # keyword, and have less indentation than lastindent.
164
+ for linenum in range(new_topvisible, stopline-1, -1):
165
+ codeline = self.text.get(f'{linenum}.0', f'{linenum}.end')
166
+ indent, text, opener = get_line_info(codeline)
167
+ if indent < lastindent:
168
+ lastindent = indent
169
+ if opener in ("else", "elif"):
170
+ # Also show the if statement.
171
+ lastindent += 1
172
+ if opener and linenum < new_topvisible and indent >= stopindent:
173
+ lines.append((linenum, indent, text, opener))
174
+ if lastindent <= stopindent:
175
+ break
176
+ lines.reverse()
177
+ return lines, lastindent
178
+
179
+ def update_code_context(self):
180
+ """Update context information and lines visible in the context pane.
181
+
182
+ No update is done if the text hasn't been scrolled. If the text
183
+ was scrolled, the lines that should be shown in the context will
184
+ be retrieved and the context area will be updated with the code,
185
+ up to the number of maxlines.
186
+ """
187
+ new_topvisible = self.editwin.getlineno("@0,0")
188
+ if self.topvisible == new_topvisible: # Haven't scrolled.
189
+ return
190
+ if self.topvisible < new_topvisible: # Scroll down.
191
+ lines, lastindent = self.get_context(new_topvisible,
192
+ self.topvisible)
193
+ # Retain only context info applicable to the region
194
+ # between topvisible and new_topvisible.
195
+ while self.info[-1][1] >= lastindent:
196
+ del self.info[-1]
197
+ else: # self.topvisible > new_topvisible: # Scroll up.
198
+ stopindent = self.info[-1][1] + 1
199
+ # Retain only context info associated
200
+ # with lines above new_topvisible.
201
+ while self.info[-1][0] >= new_topvisible:
202
+ stopindent = self.info[-1][1]
203
+ del self.info[-1]
204
+ lines, lastindent = self.get_context(new_topvisible,
205
+ self.info[-1][0]+1,
206
+ stopindent)
207
+ self.info.extend(lines)
208
+ self.topvisible = new_topvisible
209
+ # Last context_depth context lines.
210
+ context_strings = [x[2] for x in self.info[-self.context_depth:]]
211
+ showfirst = 0 if context_strings[0] else 1
212
+ # Update widget.
213
+ self.context['height'] = len(context_strings) - showfirst
214
+ self.context['state'] = 'normal'
215
+ self.context.delete('1.0', 'end')
216
+ self.context.insert('end', '\n'.join(context_strings[showfirst:]))
217
+ self.context['state'] = 'disabled'
218
+
219
+ def jumptoline(self, event=None):
220
+ """ Show clicked context line at top of editor.
221
+
222
+ If a selection was made, don't jump; allow copying.
223
+ If no visible context, show the top line of the file.
224
+ """
225
+ try:
226
+ self.context.index("sel.first")
227
+ except TclError:
228
+ lines = len(self.info)
229
+ if lines == 1: # No context lines are showing.
230
+ newtop = 1
231
+ else:
232
+ # Line number clicked.
233
+ contextline = int(float(self.context.index('insert')))
234
+ # Lines not displayed due to maxlines.
235
+ offset = max(1, lines - self.context_depth) - 1
236
+ newtop = self.info[offset + contextline][0]
237
+ self.text.yview(f'{newtop}.0')
238
+ self.update_code_context()
239
+
240
+ def timer_event(self):
241
+ "Event on editor text widget triggered every UPDATEINTERVAL ms."
242
+ if self.context is not None:
243
+ self.update_code_context()
244
+ self.t1 = self.text.after(self.UPDATEINTERVAL, self.timer_event)
245
+
246
+ def update_font(self):
247
+ if self.context is not None:
248
+ font = idleConf.GetFont(self.text, 'main', 'EditorWindow')
249
+ self.context['font'] = font
250
+
251
+ def update_highlight_colors(self):
252
+ if self.context is not None:
253
+ colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'context')
254
+ self.context['background'] = colors['background']
255
+ self.context['foreground'] = colors['foreground']
256
+
257
+ if self.cell00 is not None:
258
+ line_number_colors = idleConf.GetHighlight(idleConf.CurrentTheme(),
259
+ 'linenumber')
260
+ self.cell00.config(bg=line_number_colors['background'])
261
+
262
+
263
+ CodeContext.reload()
264
+
265
+
266
+ if __name__ == "__main__":
267
+ from unittest import main
268
+ main('idlelib.idle_test.test_codecontext', verbosity=2, exit=False)
269
+
270
+ # Add htest.
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/colorizer.py ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import builtins
2
+ import keyword
3
+ import re
4
+ import time
5
+
6
+ from idlelib.config import idleConf
7
+ from idlelib.delegator import Delegator
8
+
9
+ DEBUG = False
10
+
11
+
12
+ def any(name, alternates):
13
+ "Return a named group pattern matching list of alternates."
14
+ return "(?P<%s>" % name + "|".join(alternates) + ")"
15
+
16
+
17
+ def make_pat():
18
+ kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b"
19
+ builtinlist = [str(name) for name in dir(builtins)
20
+ if not name.startswith('_') and
21
+ name not in keyword.kwlist]
22
+ builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b"
23
+ comment = any("COMMENT", [r"#[^\n]*"])
24
+ stringprefix = r"(?i:r|u|f|fr|rf|b|br|rb)?"
25
+ sqstring = stringprefix + r"'[^'\\\n]*(\\.[^'\\\n]*)*'?"
26
+ dqstring = stringprefix + r'"[^"\\\n]*(\\.[^"\\\n]*)*"?'
27
+ sq3string = stringprefix + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"
28
+ dq3string = stringprefix + r'"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?'
29
+ string = any("STRING", [sq3string, dq3string, sqstring, dqstring])
30
+ return (kw + "|" + builtin + "|" + comment + "|" + string +
31
+ "|" + any("SYNC", [r"\n"]))
32
+
33
+
34
+ prog = re.compile(make_pat(), re.S)
35
+ idprog = re.compile(r"\s+(\w+)", re.S)
36
+
37
+
38
+ def color_config(text):
39
+ """Set color options of Text widget.
40
+
41
+ If ColorDelegator is used, this should be called first.
42
+ """
43
+ # Called from htest, TextFrame, Editor, and Turtledemo.
44
+ # Not automatic because ColorDelegator does not know 'text'.
45
+ theme = idleConf.CurrentTheme()
46
+ normal_colors = idleConf.GetHighlight(theme, 'normal')
47
+ cursor_color = idleConf.GetHighlight(theme, 'cursor')['foreground']
48
+ select_colors = idleConf.GetHighlight(theme, 'hilite')
49
+ text.config(
50
+ foreground=normal_colors['foreground'],
51
+ background=normal_colors['background'],
52
+ insertbackground=cursor_color,
53
+ selectforeground=select_colors['foreground'],
54
+ selectbackground=select_colors['background'],
55
+ inactiveselectbackground=select_colors['background'], # new in 8.5
56
+ )
57
+
58
+
59
+ class ColorDelegator(Delegator):
60
+ """Delegator for syntax highlighting (text coloring).
61
+
62
+ Instance variables:
63
+ delegate: Delegator below this one in the stack, meaning the
64
+ one this one delegates to.
65
+
66
+ Used to track state:
67
+ after_id: Identifier for scheduled after event, which is a
68
+ timer for colorizing the text.
69
+ allow_colorizing: Boolean toggle for applying colorizing.
70
+ colorizing: Boolean flag when colorizing is in process.
71
+ stop_colorizing: Boolean flag to end an active colorizing
72
+ process.
73
+ """
74
+
75
+ def __init__(self):
76
+ Delegator.__init__(self)
77
+ self.init_state()
78
+ self.prog = prog
79
+ self.idprog = idprog
80
+ self.LoadTagDefs()
81
+
82
+ def init_state(self):
83
+ "Initialize variables that track colorizing state."
84
+ self.after_id = None
85
+ self.allow_colorizing = True
86
+ self.stop_colorizing = False
87
+ self.colorizing = False
88
+
89
+ def setdelegate(self, delegate):
90
+ """Set the delegate for this instance.
91
+
92
+ A delegate is an instance of a Delegator class and each
93
+ delegate points to the next delegator in the stack. This
94
+ allows multiple delegators to be chained together for a
95
+ widget. The bottom delegate for a colorizer is a Text
96
+ widget.
97
+
98
+ If there is a delegate, also start the colorizing process.
99
+ """
100
+ if self.delegate is not None:
101
+ self.unbind("<<toggle-auto-coloring>>")
102
+ Delegator.setdelegate(self, delegate)
103
+ if delegate is not None:
104
+ self.config_colors()
105
+ self.bind("<<toggle-auto-coloring>>", self.toggle_colorize_event)
106
+ self.notify_range("1.0", "end")
107
+ else:
108
+ # No delegate - stop any colorizing.
109
+ self.stop_colorizing = True
110
+ self.allow_colorizing = False
111
+
112
+ def config_colors(self):
113
+ "Configure text widget tags with colors from tagdefs."
114
+ for tag, cnf in self.tagdefs.items():
115
+ self.tag_configure(tag, **cnf)
116
+ self.tag_raise('sel')
117
+
118
+ def LoadTagDefs(self):
119
+ "Create dictionary of tag names to text colors."
120
+ theme = idleConf.CurrentTheme()
121
+ self.tagdefs = {
122
+ "COMMENT": idleConf.GetHighlight(theme, "comment"),
123
+ "KEYWORD": idleConf.GetHighlight(theme, "keyword"),
124
+ "BUILTIN": idleConf.GetHighlight(theme, "builtin"),
125
+ "STRING": idleConf.GetHighlight(theme, "string"),
126
+ "DEFINITION": idleConf.GetHighlight(theme, "definition"),
127
+ "SYNC": {'background': None, 'foreground': None},
128
+ "TODO": {'background': None, 'foreground': None},
129
+ "ERROR": idleConf.GetHighlight(theme, "error"),
130
+ # "hit" is used by ReplaceDialog to mark matches. It shouldn't be changed by Colorizer, but
131
+ # that currently isn't technically possible. This should be moved elsewhere in the future
132
+ # when fixing the "hit" tag's visibility, or when the replace dialog is replaced with a
133
+ # non-modal alternative.
134
+ "hit": idleConf.GetHighlight(theme, "hit"),
135
+ }
136
+
137
+ if DEBUG: print('tagdefs', self.tagdefs)
138
+
139
+ def insert(self, index, chars, tags=None):
140
+ "Insert chars into widget at index and mark for colorizing."
141
+ index = self.index(index)
142
+ self.delegate.insert(index, chars, tags)
143
+ self.notify_range(index, index + "+%dc" % len(chars))
144
+
145
+ def delete(self, index1, index2=None):
146
+ "Delete chars between indexes and mark for colorizing."
147
+ index1 = self.index(index1)
148
+ self.delegate.delete(index1, index2)
149
+ self.notify_range(index1)
150
+
151
+ def notify_range(self, index1, index2=None):
152
+ "Mark text changes for processing and restart colorizing, if active."
153
+ self.tag_add("TODO", index1, index2)
154
+ if self.after_id:
155
+ if DEBUG: print("colorizing already scheduled")
156
+ return
157
+ if self.colorizing:
158
+ self.stop_colorizing = True
159
+ if DEBUG: print("stop colorizing")
160
+ if self.allow_colorizing:
161
+ if DEBUG: print("schedule colorizing")
162
+ self.after_id = self.after(1, self.recolorize)
163
+ return
164
+
165
+ def close(self):
166
+ if self.after_id:
167
+ after_id = self.after_id
168
+ self.after_id = None
169
+ if DEBUG: print("cancel scheduled recolorizer")
170
+ self.after_cancel(after_id)
171
+ self.allow_colorizing = False
172
+ self.stop_colorizing = True
173
+
174
+ def toggle_colorize_event(self, event=None):
175
+ """Toggle colorizing on and off.
176
+
177
+ When toggling off, if colorizing is scheduled or is in
178
+ process, it will be cancelled and/or stopped.
179
+
180
+ When toggling on, colorizing will be scheduled.
181
+ """
182
+ if self.after_id:
183
+ after_id = self.after_id
184
+ self.after_id = None
185
+ if DEBUG: print("cancel scheduled recolorizer")
186
+ self.after_cancel(after_id)
187
+ if self.allow_colorizing and self.colorizing:
188
+ if DEBUG: print("stop colorizing")
189
+ self.stop_colorizing = True
190
+ self.allow_colorizing = not self.allow_colorizing
191
+ if self.allow_colorizing and not self.colorizing:
192
+ self.after_id = self.after(1, self.recolorize)
193
+ if DEBUG:
194
+ print("auto colorizing turned",
195
+ "on" if self.allow_colorizing else "off")
196
+ return "break"
197
+
198
+ def recolorize(self):
199
+ """Timer event (every 1ms) to colorize text.
200
+
201
+ Colorizing is only attempted when the text widget exists,
202
+ when colorizing is toggled on, and when the colorizing
203
+ process is not already running.
204
+
205
+ After colorizing is complete, some cleanup is done to
206
+ make sure that all the text has been colorized.
207
+ """
208
+ self.after_id = None
209
+ if not self.delegate:
210
+ if DEBUG: print("no delegate")
211
+ return
212
+ if not self.allow_colorizing:
213
+ if DEBUG: print("auto colorizing is off")
214
+ return
215
+ if self.colorizing:
216
+ if DEBUG: print("already colorizing")
217
+ return
218
+ try:
219
+ self.stop_colorizing = False
220
+ self.colorizing = True
221
+ if DEBUG: print("colorizing...")
222
+ t0 = time.perf_counter()
223
+ self.recolorize_main()
224
+ t1 = time.perf_counter()
225
+ if DEBUG: print("%.3f seconds" % (t1-t0))
226
+ finally:
227
+ self.colorizing = False
228
+ if self.allow_colorizing and self.tag_nextrange("TODO", "1.0"):
229
+ if DEBUG: print("reschedule colorizing")
230
+ self.after_id = self.after(1, self.recolorize)
231
+
232
+ def recolorize_main(self):
233
+ "Evaluate text and apply colorizing tags."
234
+ next = "1.0"
235
+ while True:
236
+ item = self.tag_nextrange("TODO", next)
237
+ if not item:
238
+ break
239
+ head, tail = item
240
+ self.tag_remove("SYNC", head, tail)
241
+ item = self.tag_prevrange("SYNC", head)
242
+ head = item[1] if item else "1.0"
243
+
244
+ chars = ""
245
+ next = head
246
+ lines_to_get = 1
247
+ ok = False
248
+ while not ok:
249
+ mark = next
250
+ next = self.index(mark + "+%d lines linestart" %
251
+ lines_to_get)
252
+ lines_to_get = min(lines_to_get * 2, 100)
253
+ ok = "SYNC" in self.tag_names(next + "-1c")
254
+ line = self.get(mark, next)
255
+ ##print head, "get", mark, next, "->", repr(line)
256
+ if not line:
257
+ return
258
+ for tag in self.tagdefs:
259
+ self.tag_remove(tag, mark, next)
260
+ chars = chars + line
261
+ m = self.prog.search(chars)
262
+ while m:
263
+ for key, value in m.groupdict().items():
264
+ if value:
265
+ a, b = m.span(key)
266
+ self.tag_add(key,
267
+ head + "+%dc" % a,
268
+ head + "+%dc" % b)
269
+ if value in ("def", "class"):
270
+ m1 = self.idprog.match(chars, b)
271
+ if m1:
272
+ a, b = m1.span(1)
273
+ self.tag_add("DEFINITION",
274
+ head + "+%dc" % a,
275
+ head + "+%dc" % b)
276
+ m = self.prog.search(chars, m.end())
277
+ if "SYNC" in self.tag_names(next + "-1c"):
278
+ head = next
279
+ chars = ""
280
+ else:
281
+ ok = False
282
+ if not ok:
283
+ # We're in an inconsistent state, and the call to
284
+ # update may tell us to stop. It may also change
285
+ # the correct value for "next" (since this is a
286
+ # line.col string, not a true mark). So leave a
287
+ # crumb telling the next invocation to resume here
288
+ # in case update tells us to leave.
289
+ self.tag_add("TODO", next)
290
+ self.update()
291
+ if self.stop_colorizing:
292
+ if DEBUG: print("colorizing stopped")
293
+ return
294
+
295
+ def removecolors(self):
296
+ "Remove all colorizing tags."
297
+ for tag in self.tagdefs:
298
+ self.tag_remove(tag, "1.0", "end")
299
+
300
+
301
+ def _color_delegator(parent): # htest #
302
+ from tkinter import Toplevel, Text
303
+ from idlelib.percolator import Percolator
304
+
305
+ top = Toplevel(parent)
306
+ top.title("Test ColorDelegator")
307
+ x, y = map(int, parent.geometry().split('+')[1:])
308
+ top.geometry("700x250+%d+%d" % (x + 20, y + 175))
309
+ source = (
310
+ "if True: int ('1') # keyword, builtin, string, comment\n"
311
+ "elif False: print(0)\n"
312
+ "else: float(None)\n"
313
+ "if iF + If + IF: 'keyword matching must respect case'\n"
314
+ "if'': x or'' # valid keyword-string no-space combinations\n"
315
+ "async def f(): await g()\n"
316
+ "# All valid prefixes for unicode and byte strings should be colored.\n"
317
+ "'x', '''x''', \"x\", \"\"\"x\"\"\"\n"
318
+ "r'x', u'x', R'x', U'x', f'x', F'x'\n"
319
+ "fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n"
320
+ "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'\n"
321
+ "# Invalid combinations of legal characters should be half colored.\n"
322
+ "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n"
323
+ )
324
+ text = Text(top, background="white")
325
+ text.pack(expand=1, fill="both")
326
+ text.insert("insert", source)
327
+ text.focus_set()
328
+
329
+ color_config(text)
330
+ p = Percolator(text)
331
+ d = ColorDelegator()
332
+ p.insertfilter(d)
333
+
334
+
335
+ if __name__ == "__main__":
336
+ from unittest import main
337
+ main('idlelib.idle_test.test_colorizer', verbosity=2, exit=False)
338
+
339
+ from idlelib.idle_test.htest import run
340
+ run(_color_delegator)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config-extensions.def ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # config-extensions.def
2
+ #
3
+ # The following sections are for features that are no longer extensions.
4
+ # Their options values are left here for back-compatibility.
5
+
6
+ [AutoComplete]
7
+ popupwait= 2000
8
+
9
+ [CodeContext]
10
+ maxlines= 15
11
+
12
+ [FormatParagraph]
13
+ max-width= 72
14
+
15
+ [ParenMatch]
16
+ style= expression
17
+ flash-delay= 500
18
+ bell= True
19
+
20
+ # IDLE reads several config files to determine user preferences. This
21
+ # file is the default configuration file for IDLE extensions settings.
22
+ #
23
+ # Each extension must have at least one section, named after the
24
+ # extension module. This section must contain an 'enable' item (=True to
25
+ # enable the extension, =False to disable it), it may contain
26
+ # 'enable_editor' or 'enable_shell' items, to apply it only to editor ir
27
+ # shell windows, and may also contain any other general configuration
28
+ # items for the extension. Other True/False values will also be
29
+ # recognized as boolean by the Extension Configuration dialog.
30
+ #
31
+ # Each extension must define at least one section named
32
+ # ExtensionName_bindings or ExtensionName_cfgBindings. If present,
33
+ # ExtensionName_bindings defines virtual event bindings for the
34
+ # extension that are not user re-configurable. If present,
35
+ # ExtensionName_cfgBindings defines virtual event bindings for the
36
+ # extension that may be sensibly re-configured.
37
+ #
38
+ # If there are no keybindings for a menus' virtual events, include lines
39
+ # like <<toggle-code-context>>=.
40
+ #
41
+ # Currently it is necessary to manually modify this file to change
42
+ # extension key bindings and default values. To customize, create
43
+ # ~/.idlerc/config-extensions.cfg and append the appropriate customized
44
+ # section(s). Those sections will override the defaults in this file.
45
+ #
46
+ # Note: If a keybinding is already in use when the extension is loaded,
47
+ # the extension's virtual event's keybinding will be set to ''.
48
+ #
49
+ # See config-keys.def for notes on specifying keys and extend.txt for
50
+ # information on creating IDLE extensions.
51
+
52
+ # A fake extension for testing and example purposes. When enabled and
53
+ # invoked, inserts or deletes z-text at beginning of every line.
54
+ [ZzDummy]
55
+ enable= False
56
+ enable_shell = False
57
+ enable_editor = True
58
+ z-text= Z
59
+ [ZzDummy_cfgBindings]
60
+ z-in= <Control-Shift-KeyRelease-Insert>
61
+ [ZzDummy_bindings]
62
+ z-out= <Control-Shift-KeyRelease-Delete>
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config-highlight.def ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # IDLE reads several config files to determine user preferences. This
2
+ # file is the default config file for idle highlight theme settings.
3
+
4
+ [IDLE Classic]
5
+ normal-foreground= #000000
6
+ normal-background= #ffffff
7
+ keyword-foreground= #ff7700
8
+ keyword-background= #ffffff
9
+ builtin-foreground= #900090
10
+ builtin-background= #ffffff
11
+ comment-foreground= #dd0000
12
+ comment-background= #ffffff
13
+ string-foreground= #00aa00
14
+ string-background= #ffffff
15
+ definition-foreground= #0000ff
16
+ definition-background= #ffffff
17
+ hilite-foreground= #000000
18
+ hilite-background= gray
19
+ break-foreground= black
20
+ break-background= #ffff55
21
+ hit-foreground= #ffffff
22
+ hit-background= #000000
23
+ error-foreground= #000000
24
+ error-background= #ff7777
25
+ context-foreground= #000000
26
+ context-background= lightgray
27
+ linenumber-foreground= gray
28
+ linenumber-background= #ffffff
29
+ #cursor (only foreground can be set, restart IDLE)
30
+ cursor-foreground= black
31
+ #shell window
32
+ stdout-foreground= blue
33
+ stdout-background= #ffffff
34
+ stderr-foreground= red
35
+ stderr-background= #ffffff
36
+ console-foreground= #770000
37
+ console-background= #ffffff
38
+
39
+ [IDLE New]
40
+ normal-foreground= #000000
41
+ normal-background= #ffffff
42
+ keyword-foreground= #ff7700
43
+ keyword-background= #ffffff
44
+ builtin-foreground= #900090
45
+ builtin-background= #ffffff
46
+ comment-foreground= #dd0000
47
+ comment-background= #ffffff
48
+ string-foreground= #00aa00
49
+ string-background= #ffffff
50
+ definition-foreground= #0000ff
51
+ definition-background= #ffffff
52
+ hilite-foreground= #000000
53
+ hilite-background= gray
54
+ break-foreground= black
55
+ break-background= #ffff55
56
+ hit-foreground= #ffffff
57
+ hit-background= #000000
58
+ error-foreground= #000000
59
+ error-background= #ff7777
60
+ context-foreground= #000000
61
+ context-background= lightgray
62
+ linenumber-foreground= gray
63
+ linenumber-background= #ffffff
64
+ #cursor (only foreground can be set, restart IDLE)
65
+ cursor-foreground= black
66
+ #shell window
67
+ stdout-foreground= blue
68
+ stdout-background= #ffffff
69
+ stderr-foreground= red
70
+ stderr-background= #ffffff
71
+ console-foreground= #770000
72
+ console-background= #ffffff
73
+
74
+ [IDLE Dark]
75
+ comment-foreground = #dd0000
76
+ console-foreground = #ff4d4d
77
+ error-foreground = #FFFFFF
78
+ hilite-background = #7e7e7e
79
+ string-foreground = #02ff02
80
+ stderr-background = #002240
81
+ stderr-foreground = #ffb3b3
82
+ console-background = #002240
83
+ hit-background = #fbfbfb
84
+ string-background = #002240
85
+ normal-background = #002240
86
+ hilite-foreground = #FFFFFF
87
+ keyword-foreground = #ff8000
88
+ error-background = #c86464
89
+ keyword-background = #002240
90
+ builtin-background = #002240
91
+ break-background = #808000
92
+ builtin-foreground = #ff00ff
93
+ definition-foreground = #5e5eff
94
+ stdout-foreground = #c2d1fa
95
+ definition-background = #002240
96
+ normal-foreground = #FFFFFF
97
+ cursor-foreground = #ffffff
98
+ stdout-background = #002240
99
+ hit-foreground = #002240
100
+ comment-background = #002240
101
+ break-foreground = #FFFFFF
102
+ context-foreground= #ffffff
103
+ context-background= #454545
104
+ linenumber-foreground= gray
105
+ linenumber-background= #002240
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config-keys.def ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # IDLE reads several config files to determine user preferences. This
2
+ # file is the default config file for idle key binding settings.
3
+ # Where multiple keys are specified for an action: if they are separated
4
+ # by a space (eg. action=<key1> <key2>) then the keys are alternatives, if
5
+ # there is no space (eg. action=<key1><key2>) then the keys comprise a
6
+ # single 'emacs style' multi-keystoke binding. The tk event specifier 'Key'
7
+ # is used in all cases, for consistency in auto key conflict checking in the
8
+ # configuration gui.
9
+
10
+ [IDLE Classic Windows]
11
+ copy=<Control-Key-c> <Control-Key-C>
12
+ cut=<Control-Key-x> <Control-Key-X>
13
+ paste=<Control-Key-v> <Control-Key-V>
14
+ beginning-of-line= <Key-Home>
15
+ center-insert=<Control-Key-l> <Control-Key-L>
16
+ close-all-windows=<Control-Key-q> <Control-Key-Q>
17
+ close-window=<Alt-Key-F4> <Meta-Key-F4>
18
+ do-nothing=<Control-Key-F12>
19
+ end-of-file=<Control-Key-d> <Control-Key-D>
20
+ python-docs=<Key-F1>
21
+ python-context-help=<Shift-Key-F1>
22
+ history-next=<Alt-Key-n> <Meta-Key-n> <Alt-Key-N> <Meta-Key-N>
23
+ history-previous=<Alt-Key-p> <Meta-Key-p> <Alt-Key-P> <Meta-Key-P>
24
+ interrupt-execution=<Control-Key-c> <Control-Key-C>
25
+ view-restart=<Key-F6>
26
+ restart-shell=<Control-Key-F6>
27
+ open-class-browser=<Alt-Key-c> <Meta-Key-c> <Alt-Key-C> <Meta-Key-C>
28
+ open-module=<Alt-Key-m> <Meta-Key-m> <Alt-Key-M> <Meta-Key-M>
29
+ open-new-window=<Control-Key-n> <Control-Key-N>
30
+ open-window-from-file=<Control-Key-o> <Control-Key-O>
31
+ plain-newline-and-indent=<Control-Key-j> <Control-Key-J>
32
+ print-window=<Control-Key-p> <Control-Key-P>
33
+ redo=<Control-Shift-Key-Z> <Control-Shift-Key-z>
34
+ remove-selection=<Key-Escape>
35
+ save-copy-of-window-as-file=<Alt-Shift-Key-S> <Alt-Shift-Key-s>
36
+ save-window-as-file=<Control-Shift-Key-S> <Control-Shift-Key-s>
37
+ save-window=<Control-Key-s> <Control-Key-S>
38
+ select-all=<Control-Key-a> <Control-Key-A>
39
+ toggle-auto-coloring=<Control-Key-slash>
40
+ undo=<Control-Key-z> <Control-Key-Z>
41
+ find=<Control-Key-f> <Control-Key-F>
42
+ find-again=<Control-Key-g> <Key-F3> <Control-Key-G>
43
+ find-in-files=<Alt-Key-F3> <Meta-Key-F3>
44
+ find-selection=<Control-Key-F3>
45
+ replace=<Control-Key-h> <Control-Key-H>
46
+ goto-line=<Alt-Key-g> <Meta-Key-g> <Alt-Key-G> <Meta-Key-G>
47
+ smart-backspace=<Key-BackSpace>
48
+ newline-and-indent=<Key-Return> <Key-KP_Enter>
49
+ smart-indent=<Key-Tab>
50
+ indent-region=<Control-Key-bracketright>
51
+ dedent-region=<Control-Key-bracketleft>
52
+ comment-region=<Alt-Key-3> <Meta-Key-3>
53
+ uncomment-region=<Alt-Key-4> <Meta-Key-4>
54
+ tabify-region=<Alt-Key-5> <Meta-Key-5>
55
+ untabify-region=<Alt-Key-6> <Meta-Key-6>
56
+ toggle-tabs=<Alt-Key-t> <Meta-Key-t> <Alt-Key-T> <Meta-Key-T>
57
+ change-indentwidth=<Alt-Key-u> <Meta-Key-u> <Alt-Key-U> <Meta-Key-U>
58
+ del-word-left=<Control-Key-BackSpace>
59
+ del-word-right=<Control-Key-Delete>
60
+ force-open-completions= <Control-Key-space>
61
+ expand-word= <Alt-Key-slash>
62
+ force-open-calltip= <Control-Key-backslash>
63
+ format-paragraph= <Alt-Key-q>
64
+ flash-paren= <Control-Key-0>
65
+ run-module= <Key-F5>
66
+ run-custom= <Shift-Key-F5>
67
+ check-module= <Alt-Key-x>
68
+ zoom-height= <Alt-Key-2>
69
+
70
+ [IDLE Classic Unix]
71
+ copy=<Alt-Key-w> <Meta-Key-w>
72
+ cut=<Control-Key-w>
73
+ paste=<Control-Key-y>
74
+ beginning-of-line=<Control-Key-a> <Key-Home>
75
+ center-insert=<Control-Key-l>
76
+ close-all-windows=<Control-Key-x><Control-Key-c>
77
+ close-window=<Control-Key-x><Control-Key-0>
78
+ do-nothing=<Control-Key-x>
79
+ end-of-file=<Control-Key-d>
80
+ history-next=<Alt-Key-n> <Meta-Key-n>
81
+ history-previous=<Alt-Key-p> <Meta-Key-p>
82
+ interrupt-execution=<Control-Key-c>
83
+ view-restart=<Key-F6>
84
+ restart-shell=<Control-Key-F6>
85
+ open-class-browser=<Control-Key-x><Control-Key-b>
86
+ open-module=<Control-Key-x><Control-Key-m>
87
+ open-new-window=<Control-Key-x><Control-Key-n>
88
+ open-window-from-file=<Control-Key-x><Control-Key-f>
89
+ plain-newline-and-indent=<Control-Key-j>
90
+ print-window=<Control-x><Control-Key-p>
91
+ python-docs=<Control-Key-h>
92
+ python-context-help=<Control-Shift-Key-H>
93
+ redo=<Alt-Key-z> <Meta-Key-z>
94
+ remove-selection=<Key-Escape>
95
+ save-copy-of-window-as-file=<Control-Key-x><Control-Key-y>
96
+ save-window-as-file=<Control-Key-x><Control-Key-w>
97
+ save-window=<Control-Key-x><Control-Key-s>
98
+ select-all=<Alt-Key-a> <Meta-Key-a>
99
+ toggle-auto-coloring=<Control-Key-slash>
100
+ undo=<Control-Key-z>
101
+ find=<Control-Key-u><Control-Key-u><Control-Key-s>
102
+ find-again=<Control-Key-u><Control-Key-s>
103
+ find-in-files=<Alt-Key-s> <Meta-Key-s>
104
+ find-selection=<Control-Key-s>
105
+ replace=<Control-Key-r>
106
+ goto-line=<Alt-Key-g> <Meta-Key-g>
107
+ smart-backspace=<Key-BackSpace>
108
+ newline-and-indent=<Key-Return> <Key-KP_Enter>
109
+ smart-indent=<Key-Tab>
110
+ indent-region=<Control-Key-bracketright>
111
+ dedent-region=<Control-Key-bracketleft>
112
+ comment-region=<Alt-Key-3>
113
+ uncomment-region=<Alt-Key-4>
114
+ tabify-region=<Alt-Key-5>
115
+ untabify-region=<Alt-Key-6>
116
+ toggle-tabs=<Alt-Key-t>
117
+ change-indentwidth=<Alt-Key-u>
118
+ del-word-left=<Alt-Key-BackSpace>
119
+ del-word-right=<Alt-Key-d>
120
+ force-open-completions= <Control-Key-space>
121
+ expand-word= <Alt-Key-slash>
122
+ force-open-calltip= <Control-Key-backslash>
123
+ format-paragraph= <Alt-Key-q>
124
+ flash-paren= <Control-Key-0>
125
+ run-module= <Key-F5>
126
+ run-custom= <Shift-Key-F5>
127
+ check-module= <Alt-Key-x>
128
+ zoom-height= <Alt-Key-2>
129
+
130
+ [IDLE Modern Unix]
131
+ copy = <Control-Shift-Key-C> <Control-Key-Insert>
132
+ cut = <Control-Key-x> <Shift-Key-Delete>
133
+ paste = <Control-Key-v> <Shift-Key-Insert>
134
+ beginning-of-line = <Key-Home>
135
+ center-insert = <Control-Key-l>
136
+ close-all-windows = <Control-Key-q>
137
+ close-window = <Control-Key-w> <Control-Shift-Key-W>
138
+ do-nothing = <Control-Key-F12>
139
+ end-of-file = <Control-Key-d>
140
+ history-next = <Alt-Key-n> <Meta-Key-n>
141
+ history-previous = <Alt-Key-p> <Meta-Key-p>
142
+ interrupt-execution = <Control-Key-c>
143
+ view-restart = <Key-F6>
144
+ restart-shell = <Control-Key-F6>
145
+ open-class-browser = <Control-Key-b>
146
+ open-module = <Control-Key-m>
147
+ open-new-window = <Control-Key-n>
148
+ open-window-from-file = <Control-Key-o>
149
+ plain-newline-and-indent = <Control-Key-j>
150
+ print-window = <Control-Key-p>
151
+ python-context-help = <Shift-Key-F1>
152
+ python-docs = <Key-F1>
153
+ redo = <Control-Shift-Key-Z>
154
+ remove-selection = <Key-Escape>
155
+ save-copy-of-window-as-file = <Alt-Shift-Key-S>
156
+ save-window-as-file = <Control-Shift-Key-S>
157
+ save-window = <Control-Key-s>
158
+ select-all = <Control-Key-a>
159
+ toggle-auto-coloring = <Control-Key-slash>
160
+ undo = <Control-Key-z>
161
+ find = <Control-Key-f>
162
+ find-again = <Key-F3>
163
+ find-in-files = <Control-Shift-Key-f>
164
+ find-selection = <Control-Key-h>
165
+ replace = <Control-Key-r>
166
+ goto-line = <Control-Key-g>
167
+ smart-backspace = <Key-BackSpace>
168
+ newline-and-indent = <Key-Return> <Key-KP_Enter>
169
+ smart-indent = <Key-Tab>
170
+ indent-region = <Control-Key-bracketright>
171
+ dedent-region = <Control-Key-bracketleft>
172
+ comment-region = <Control-Key-d>
173
+ uncomment-region = <Control-Shift-Key-D>
174
+ tabify-region = <Alt-Key-5>
175
+ untabify-region = <Alt-Key-6>
176
+ toggle-tabs = <Control-Key-T>
177
+ change-indentwidth = <Alt-Key-u>
178
+ del-word-left = <Control-Key-BackSpace>
179
+ del-word-right = <Control-Key-Delete>
180
+ force-open-completions= <Control-Key-space>
181
+ expand-word= <Alt-Key-slash>
182
+ force-open-calltip= <Control-Key-backslash>
183
+ format-paragraph= <Alt-Key-q>
184
+ flash-paren= <Control-Key-0>
185
+ run-module= <Key-F5>
186
+ run-custom= <Shift-Key-F5>
187
+ check-module= <Alt-Key-x>
188
+ zoom-height= <Alt-Key-2>
189
+
190
+ [IDLE Classic Mac]
191
+ copy=<Command-Key-c>
192
+ cut=<Command-Key-x>
193
+ paste=<Command-Key-v>
194
+ beginning-of-line= <Key-Home>
195
+ center-insert=<Control-Key-l>
196
+ close-all-windows=<Command-Key-q>
197
+ close-window=<Command-Key-w>
198
+ do-nothing=<Control-Key-F12>
199
+ end-of-file=<Control-Key-d>
200
+ python-docs=<Key-F1>
201
+ python-context-help=<Shift-Key-F1>
202
+ history-next=<Control-Key-n>
203
+ history-previous=<Control-Key-p>
204
+ interrupt-execution=<Control-Key-c>
205
+ view-restart=<Key-F6>
206
+ restart-shell=<Control-Key-F6>
207
+ open-class-browser=<Command-Key-b>
208
+ open-module=<Command-Key-m>
209
+ open-new-window=<Command-Key-n>
210
+ open-window-from-file=<Command-Key-o>
211
+ plain-newline-and-indent=<Control-Key-j>
212
+ print-window=<Command-Key-p>
213
+ redo=<Shift-Command-Key-Z>
214
+ remove-selection=<Key-Escape>
215
+ save-window-as-file=<Shift-Command-Key-S>
216
+ save-window=<Command-Key-s>
217
+ save-copy-of-window-as-file=<Option-Command-Key-s>
218
+ select-all=<Command-Key-a>
219
+ toggle-auto-coloring=<Control-Key-slash>
220
+ undo=<Command-Key-z>
221
+ find=<Command-Key-f>
222
+ find-again=<Command-Key-g> <Key-F3>
223
+ find-in-files=<Command-Key-F3>
224
+ find-selection=<Shift-Command-Key-F3>
225
+ replace=<Command-Key-r>
226
+ goto-line=<Command-Key-j>
227
+ smart-backspace=<Key-BackSpace>
228
+ newline-and-indent=<Key-Return> <Key-KP_Enter>
229
+ smart-indent=<Key-Tab>
230
+ indent-region=<Command-Key-bracketright>
231
+ dedent-region=<Command-Key-bracketleft>
232
+ comment-region=<Control-Key-3>
233
+ uncomment-region=<Control-Key-4>
234
+ tabify-region=<Control-Key-5>
235
+ untabify-region=<Control-Key-6>
236
+ toggle-tabs=<Control-Key-t>
237
+ change-indentwidth=<Control-Key-u>
238
+ del-word-left=<Control-Key-BackSpace>
239
+ del-word-right=<Control-Key-Delete>
240
+ force-open-completions= <Control-Key-space>
241
+ expand-word= <Option-Key-slash>
242
+ force-open-calltip= <Control-Key-backslash>
243
+ format-paragraph= <Option-Key-q>
244
+ flash-paren= <Control-Key-0>
245
+ run-module= <Key-F5>
246
+ run-custom= <Shift-Key-F5>
247
+ check-module= <Option-Key-x>
248
+ zoom-height= <Option-Key-0>
249
+
250
+ [IDLE Classic OSX]
251
+ toggle-tabs = <Control-Key-t>
252
+ interrupt-execution = <Control-Key-c>
253
+ untabify-region = <Control-Key-6>
254
+ remove-selection = <Key-Escape>
255
+ print-window = <Command-Key-p>
256
+ replace = <Command-Key-r>
257
+ goto-line = <Command-Key-j>
258
+ plain-newline-and-indent = <Control-Key-j>
259
+ history-previous = <Control-Key-p>
260
+ beginning-of-line = <Control-Key-Left>
261
+ end-of-line = <Control-Key-Right>
262
+ comment-region = <Control-Key-3>
263
+ redo = <Shift-Command-Key-Z>
264
+ close-window = <Command-Key-w>
265
+ restart-shell = <Control-Key-F6>
266
+ save-window-as-file = <Shift-Command-Key-S>
267
+ close-all-windows = <Command-Key-q>
268
+ view-restart = <Key-F6>
269
+ tabify-region = <Control-Key-5>
270
+ find-again = <Command-Key-g> <Key-F3>
271
+ find = <Command-Key-f>
272
+ toggle-auto-coloring = <Control-Key-slash>
273
+ select-all = <Command-Key-a>
274
+ smart-backspace = <Key-BackSpace>
275
+ change-indentwidth = <Control-Key-u>
276
+ do-nothing = <Control-Key-F12>
277
+ smart-indent = <Key-Tab>
278
+ center-insert = <Control-Key-l>
279
+ history-next = <Control-Key-n>
280
+ del-word-right = <Option-Key-Delete>
281
+ undo = <Command-Key-z>
282
+ save-window = <Command-Key-s>
283
+ uncomment-region = <Control-Key-4>
284
+ cut = <Command-Key-x>
285
+ find-in-files = <Command-Key-F3>
286
+ dedent-region = <Command-Key-bracketleft>
287
+ copy = <Command-Key-c>
288
+ paste = <Command-Key-v>
289
+ indent-region = <Command-Key-bracketright>
290
+ del-word-left = <Option-Key-BackSpace> <Option-Command-Key-BackSpace>
291
+ newline-and-indent = <Key-Return> <Key-KP_Enter>
292
+ end-of-file = <Control-Key-d>
293
+ open-class-browser = <Command-Key-b>
294
+ open-new-window = <Command-Key-n>
295
+ open-module = <Command-Key-m>
296
+ find-selection = <Shift-Command-Key-F3>
297
+ python-context-help = <Shift-Key-F1>
298
+ save-copy-of-window-as-file = <Option-Command-Key-s>
299
+ open-window-from-file = <Command-Key-o>
300
+ python-docs = <Key-F1>
301
+ force-open-completions= <Control-Key-space>
302
+ expand-word= <Option-Key-slash>
303
+ force-open-calltip= <Control-Key-backslash>
304
+ format-paragraph= <Option-Key-q>
305
+ flash-paren= <Control-Key-0>
306
+ run-module= <Key-F5>
307
+ run-custom= <Shift-Key-F5>
308
+ check-module= <Option-Key-x>
309
+ zoom-height= <Option-Key-0>
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config-main.def ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # IDLE reads several config files to determine user preferences. This
2
+ # file is the default config file for general idle settings.
3
+ #
4
+ # When IDLE starts, it will look in
5
+ # the following two sets of files, in order:
6
+ #
7
+ # default configuration files in idlelib
8
+ # --------------------------------------
9
+ # config-main.def default general config file
10
+ # config-extensions.def default extension config file
11
+ # config-highlight.def default highlighting config file
12
+ # config-keys.def default keybinding config file
13
+ #
14
+ # user configuration files in ~/.idlerc
15
+ # -------------------------------------
16
+ # config-main.cfg user general config file
17
+ # config-extensions.cfg user extension config file
18
+ # config-highlight.cfg user highlighting config file
19
+ # config-keys.cfg user keybinding config file
20
+ #
21
+ # On Windows, the default location of the home directory ('~' above)
22
+ # depends on the version. For Windows 10, it is C:\Users\<username>.
23
+ #
24
+ # Any options the user saves through the config dialog will be saved to
25
+ # the relevant user config file. Reverting any general or extension
26
+ # setting to the default causes that entry to be wiped from the user
27
+ # file and re-read from the default file. This rule applies to each
28
+ # item, except that the three editor font items are saved as a group.
29
+ #
30
+ # User highlighting themes and keybinding sets must have (section) names
31
+ # distinct from the default names. All items are added and saved as a
32
+ # group. They are retained unless specifically deleted within the config
33
+ # dialog. Choosing one of the default themes or keysets just applies the
34
+ # relevant settings from the default file.
35
+ #
36
+ # Additional help sources are listed in the [HelpFiles] section below
37
+ # and should be viewable by a web browser (or the Windows Help viewer in
38
+ # the case of .chm files). These sources will be listed on the Help
39
+ # menu. The pattern, and two examples, are:
40
+ #
41
+ # <sequence_number = menu item;/path/to/help/source>
42
+ # 1 = IDLE;C:/Programs/Python36/Lib/idlelib/help.html
43
+ # 2 = Pillow;https://pillow.readthedocs.io/en/latest/
44
+ #
45
+ # You can't use a semi-colon in a menu item or path. The path will be
46
+ # platform specific because of path separators, drive specs etc.
47
+ #
48
+ # The default files should not be edited except to add new sections to
49
+ # config-extensions.def for added extensions. The user files should be
50
+ # modified through the Settings dialog.
51
+
52
+ [General]
53
+ editor-on-startup= 0
54
+ autosave= 0
55
+ print-command-posix=lpr %%s
56
+ print-command-win=start /min notepad /p %%s
57
+ delete-exitfunc= 1
58
+
59
+ [EditorWindow]
60
+ width= 80
61
+ height= 40
62
+ cursor-blink= 1
63
+ font= TkFixedFont
64
+ # For TkFixedFont, the actual size and boldness are obtained from tk
65
+ # and override 10 and 0. See idlelib.config.IdleConf.GetFont
66
+ font-size= 10
67
+ font-bold= 0
68
+ encoding= none
69
+ line-numbers-default= 0
70
+
71
+ [PyShell]
72
+ auto-squeeze-min-lines= 50
73
+
74
+ [Indent]
75
+ use-spaces= 1
76
+ num-spaces= 4
77
+
78
+ [Theme]
79
+ default= 1
80
+ name= IDLE Classic
81
+ name2=
82
+ # name2 set in user config-main.cfg for themes added after 2015 Oct 1
83
+
84
+ [Keys]
85
+ default= 1
86
+ name=
87
+ name2=
88
+ # name2 set in user config-main.cfg for keys added after 2016 July 1
89
+
90
+ [History]
91
+ cyclic=1
92
+
93
+ [HelpFiles]
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/config.py ADDED
@@ -0,0 +1,911 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """idlelib.config -- Manage IDLE configuration information.
2
+
3
+ The comments at the beginning of config-main.def describe the
4
+ configuration files and the design implemented to update user
5
+ configuration information. In particular, user configuration choices
6
+ which duplicate the defaults will be removed from the user's
7
+ configuration files, and if a user file becomes empty, it will be
8
+ deleted.
9
+
10
+ The configuration database maps options to values. Conceptually, the
11
+ database keys are tuples (config-type, section, item). As implemented,
12
+ there are separate dicts for default and user values. Each has
13
+ config-type keys 'main', 'extensions', 'highlight', and 'keys'. The
14
+ value for each key is a ConfigParser instance that maps section and item
15
+ to values. For 'main' and 'extensions', user values override
16
+ default values. For 'highlight' and 'keys', user sections augment the
17
+ default sections (and must, therefore, have distinct names).
18
+
19
+ Throughout this module there is an emphasis on returning useable defaults
20
+ when a problem occurs in returning a requested configuration value back to
21
+ idle. This is to allow IDLE to continue to function in spite of errors in
22
+ the retrieval of config information. When a default is returned instead of
23
+ a requested config value, a message is printed to stderr to aid in
24
+ configuration problem notification and resolution.
25
+ """
26
+ # TODOs added Oct 2014, tjr
27
+
28
+ from configparser import ConfigParser
29
+ import os
30
+ import sys
31
+
32
+ from tkinter.font import Font
33
+ import idlelib
34
+
35
+ class InvalidConfigType(Exception): pass
36
+ class InvalidConfigSet(Exception): pass
37
+ class InvalidTheme(Exception): pass
38
+
39
+ class IdleConfParser(ConfigParser):
40
+ """
41
+ A ConfigParser specialised for idle configuration file handling
42
+ """
43
+ def __init__(self, cfgFile, cfgDefaults=None):
44
+ """
45
+ cfgFile - string, fully specified configuration file name
46
+ """
47
+ self.file = cfgFile # This is currently '' when testing.
48
+ ConfigParser.__init__(self, defaults=cfgDefaults, strict=False)
49
+
50
+ def Get(self, section, option, type=None, default=None, raw=False):
51
+ """
52
+ Get an option value for given section/option or return default.
53
+ If type is specified, return as type.
54
+ """
55
+ # TODO Use default as fallback, at least if not None
56
+ # Should also print Warning(file, section, option).
57
+ # Currently may raise ValueError
58
+ if not self.has_option(section, option):
59
+ return default
60
+ if type == 'bool':
61
+ return self.getboolean(section, option)
62
+ elif type == 'int':
63
+ return self.getint(section, option)
64
+ else:
65
+ return self.get(section, option, raw=raw)
66
+
67
+ def GetOptionList(self, section):
68
+ "Return a list of options for given section, else []."
69
+ if self.has_section(section):
70
+ return self.options(section)
71
+ else: #return a default value
72
+ return []
73
+
74
+ def Load(self):
75
+ "Load the configuration file from disk."
76
+ if self.file:
77
+ self.read(self.file)
78
+
79
+ class IdleUserConfParser(IdleConfParser):
80
+ """
81
+ IdleConfigParser specialised for user configuration handling.
82
+ """
83
+
84
+ def SetOption(self, section, option, value):
85
+ """Return True if option is added or changed to value, else False.
86
+
87
+ Add section if required. False means option already had value.
88
+ """
89
+ if self.has_option(section, option):
90
+ if self.get(section, option) == value:
91
+ return False
92
+ else:
93
+ self.set(section, option, value)
94
+ return True
95
+ else:
96
+ if not self.has_section(section):
97
+ self.add_section(section)
98
+ self.set(section, option, value)
99
+ return True
100
+
101
+ def RemoveOption(self, section, option):
102
+ """Return True if option is removed from section, else False.
103
+
104
+ False if either section does not exist or did not have option.
105
+ """
106
+ if self.has_section(section):
107
+ return self.remove_option(section, option)
108
+ return False
109
+
110
+ def AddSection(self, section):
111
+ "If section doesn't exist, add it."
112
+ if not self.has_section(section):
113
+ self.add_section(section)
114
+
115
+ def RemoveEmptySections(self):
116
+ "Remove any sections that have no options."
117
+ for section in self.sections():
118
+ if not self.GetOptionList(section):
119
+ self.remove_section(section)
120
+
121
+ def IsEmpty(self):
122
+ "Return True if no sections after removing empty sections."
123
+ self.RemoveEmptySections()
124
+ return not self.sections()
125
+
126
+ def Save(self):
127
+ """Update user configuration file.
128
+
129
+ If self not empty after removing empty sections, write the file
130
+ to disk. Otherwise, remove the file from disk if it exists.
131
+ """
132
+ fname = self.file
133
+ if fname and fname[0] != '#':
134
+ if not self.IsEmpty():
135
+ try:
136
+ cfgFile = open(fname, 'w')
137
+ except OSError:
138
+ os.unlink(fname)
139
+ cfgFile = open(fname, 'w')
140
+ with cfgFile:
141
+ self.write(cfgFile)
142
+ elif os.path.exists(self.file):
143
+ os.remove(self.file)
144
+
145
+ class IdleConf:
146
+ """Hold config parsers for all idle config files in singleton instance.
147
+
148
+ Default config files, self.defaultCfg --
149
+ for config_type in self.config_types:
150
+ (idle install dir)/config-{config-type}.def
151
+
152
+ User config files, self.userCfg --
153
+ for config_type in self.config_types:
154
+ (user home dir)/.idlerc/config-{config-type}.cfg
155
+ """
156
+ def __init__(self, _utest=False):
157
+ self.config_types = ('main', 'highlight', 'keys', 'extensions')
158
+ self.defaultCfg = {}
159
+ self.userCfg = {}
160
+ self.cfg = {} # TODO use to select userCfg vs defaultCfg
161
+ # self.blink_off_time = <first editor text>['insertofftime']
162
+ # See https:/bugs.python.org/issue4630, msg356516.
163
+
164
+ if not _utest:
165
+ self.CreateConfigHandlers()
166
+ self.LoadCfgFiles()
167
+
168
+ def CreateConfigHandlers(self):
169
+ "Populate default and user config parser dictionaries."
170
+ idledir = os.path.dirname(__file__)
171
+ self.userdir = userdir = '' if idlelib.testing else self.GetUserCfgDir()
172
+ for cfg_type in self.config_types:
173
+ self.defaultCfg[cfg_type] = IdleConfParser(
174
+ os.path.join(idledir, f'config-{cfg_type}.def'))
175
+ self.userCfg[cfg_type] = IdleUserConfParser(
176
+ os.path.join(userdir or '#', f'config-{cfg_type}.cfg'))
177
+
178
+ def GetUserCfgDir(self):
179
+ """Return a filesystem directory for storing user config files.
180
+
181
+ Creates it if required.
182
+ """
183
+ cfgDir = '.idlerc'
184
+ userDir = os.path.expanduser('~')
185
+ if userDir != '~': # expanduser() found user home dir
186
+ if not os.path.exists(userDir):
187
+ if not idlelib.testing:
188
+ warn = ('\n Warning: os.path.expanduser("~") points to\n ' +
189
+ userDir + ',\n but the path does not exist.')
190
+ try:
191
+ print(warn, file=sys.stderr)
192
+ except OSError:
193
+ pass
194
+ userDir = '~'
195
+ if userDir == "~": # still no path to home!
196
+ # traditionally IDLE has defaulted to os.getcwd(), is this adequate?
197
+ userDir = os.getcwd()
198
+ userDir = os.path.join(userDir, cfgDir)
199
+ if not os.path.exists(userDir):
200
+ try:
201
+ os.mkdir(userDir)
202
+ except OSError:
203
+ if not idlelib.testing:
204
+ warn = ('\n Warning: unable to create user config directory\n' +
205
+ userDir + '\n Check path and permissions.\n Exiting!\n')
206
+ try:
207
+ print(warn, file=sys.stderr)
208
+ except OSError:
209
+ pass
210
+ raise SystemExit
211
+ # TODO continue without userDIr instead of exit
212
+ return userDir
213
+
214
+ def GetOption(self, configType, section, option, default=None, type=None,
215
+ warn_on_default=True, raw=False):
216
+ """Return a value for configType section option, or default.
217
+
218
+ If type is not None, return a value of that type. Also pass raw
219
+ to the config parser. First try to return a valid value
220
+ (including type) from a user configuration. If that fails, try
221
+ the default configuration. If that fails, return default, with a
222
+ default of None.
223
+
224
+ Warn if either user or default configurations have an invalid value.
225
+ Warn if default is returned and warn_on_default is True.
226
+ """
227
+ try:
228
+ if self.userCfg[configType].has_option(section, option):
229
+ return self.userCfg[configType].Get(section, option,
230
+ type=type, raw=raw)
231
+ except ValueError:
232
+ warning = ('\n Warning: config.py - IdleConf.GetOption -\n'
233
+ ' invalid %r value for configuration option %r\n'
234
+ ' from section %r: %r' %
235
+ (type, option, section,
236
+ self.userCfg[configType].Get(section, option, raw=raw)))
237
+ _warn(warning, configType, section, option)
238
+ try:
239
+ if self.defaultCfg[configType].has_option(section,option):
240
+ return self.defaultCfg[configType].Get(
241
+ section, option, type=type, raw=raw)
242
+ except ValueError:
243
+ pass
244
+ #returning default, print warning
245
+ if warn_on_default:
246
+ warning = ('\n Warning: config.py - IdleConf.GetOption -\n'
247
+ ' problem retrieving configuration option %r\n'
248
+ ' from section %r.\n'
249
+ ' returning default value: %r' %
250
+ (option, section, default))
251
+ _warn(warning, configType, section, option)
252
+ return default
253
+
254
+ def SetOption(self, configType, section, option, value):
255
+ """Set section option to value in user config file."""
256
+ self.userCfg[configType].SetOption(section, option, value)
257
+
258
+ def GetSectionList(self, configSet, configType):
259
+ """Return sections for configSet configType configuration.
260
+
261
+ configSet must be either 'user' or 'default'
262
+ configType must be in self.config_types.
263
+ """
264
+ if not (configType in self.config_types):
265
+ raise InvalidConfigType('Invalid configType specified')
266
+ if configSet == 'user':
267
+ cfgParser = self.userCfg[configType]
268
+ elif configSet == 'default':
269
+ cfgParser=self.defaultCfg[configType]
270
+ else:
271
+ raise InvalidConfigSet('Invalid configSet specified')
272
+ return cfgParser.sections()
273
+
274
+ def GetHighlight(self, theme, element):
275
+ """Return dict of theme element highlight colors.
276
+
277
+ The keys are 'foreground' and 'background'. The values are
278
+ tkinter color strings for configuring backgrounds and tags.
279
+ """
280
+ cfg = ('default' if self.defaultCfg['highlight'].has_section(theme)
281
+ else 'user')
282
+ theme_dict = self.GetThemeDict(cfg, theme)
283
+ fore = theme_dict[element + '-foreground']
284
+ if element == 'cursor':
285
+ element = 'normal'
286
+ back = theme_dict[element + '-background']
287
+ return {"foreground": fore, "background": back}
288
+
289
+ def GetThemeDict(self, type, themeName):
290
+ """Return {option:value} dict for elements in themeName.
291
+
292
+ type - string, 'default' or 'user' theme type
293
+ themeName - string, theme name
294
+ Values are loaded over ultimate fallback defaults to guarantee
295
+ that all theme elements are present in a newly created theme.
296
+ """
297
+ if type == 'user':
298
+ cfgParser = self.userCfg['highlight']
299
+ elif type == 'default':
300
+ cfgParser = self.defaultCfg['highlight']
301
+ else:
302
+ raise InvalidTheme('Invalid theme type specified')
303
+ # Provide foreground and background colors for each theme
304
+ # element (other than cursor) even though some values are not
305
+ # yet used by idle, to allow for their use in the future.
306
+ # Default values are generally black and white.
307
+ # TODO copy theme from a class attribute.
308
+ theme ={'normal-foreground':'#000000',
309
+ 'normal-background':'#ffffff',
310
+ 'keyword-foreground':'#000000',
311
+ 'keyword-background':'#ffffff',
312
+ 'builtin-foreground':'#000000',
313
+ 'builtin-background':'#ffffff',
314
+ 'comment-foreground':'#000000',
315
+ 'comment-background':'#ffffff',
316
+ 'string-foreground':'#000000',
317
+ 'string-background':'#ffffff',
318
+ 'definition-foreground':'#000000',
319
+ 'definition-background':'#ffffff',
320
+ 'hilite-foreground':'#000000',
321
+ 'hilite-background':'gray',
322
+ 'break-foreground':'#ffffff',
323
+ 'break-background':'#000000',
324
+ 'hit-foreground':'#ffffff',
325
+ 'hit-background':'#000000',
326
+ 'error-foreground':'#ffffff',
327
+ 'error-background':'#000000',
328
+ 'context-foreground':'#000000',
329
+ 'context-background':'#ffffff',
330
+ 'linenumber-foreground':'#000000',
331
+ 'linenumber-background':'#ffffff',
332
+ #cursor (only foreground can be set)
333
+ 'cursor-foreground':'#000000',
334
+ #shell window
335
+ 'stdout-foreground':'#000000',
336
+ 'stdout-background':'#ffffff',
337
+ 'stderr-foreground':'#000000',
338
+ 'stderr-background':'#ffffff',
339
+ 'console-foreground':'#000000',
340
+ 'console-background':'#ffffff',
341
+ }
342
+ for element in theme:
343
+ if not (cfgParser.has_option(themeName, element) or
344
+ # Skip warning for new elements.
345
+ element.startswith(('context-', 'linenumber-'))):
346
+ # Print warning that will return a default color
347
+ warning = ('\n Warning: config.IdleConf.GetThemeDict'
348
+ ' -\n problem retrieving theme element %r'
349
+ '\n from theme %r.\n'
350
+ ' returning default color: %r' %
351
+ (element, themeName, theme[element]))
352
+ _warn(warning, 'highlight', themeName, element)
353
+ theme[element] = cfgParser.Get(
354
+ themeName, element, default=theme[element])
355
+ return theme
356
+
357
+ def CurrentTheme(self):
358
+ "Return the name of the currently active text color theme."
359
+ return self.current_colors_and_keys('Theme')
360
+
361
+ def CurrentKeys(self):
362
+ """Return the name of the currently active key set."""
363
+ return self.current_colors_and_keys('Keys')
364
+
365
+ def current_colors_and_keys(self, section):
366
+ """Return the currently active name for Theme or Keys section.
367
+
368
+ idlelib.config-main.def ('default') includes these sections
369
+
370
+ [Theme]
371
+ default= 1
372
+ name= IDLE Classic
373
+ name2=
374
+
375
+ [Keys]
376
+ default= 1
377
+ name=
378
+ name2=
379
+
380
+ Item 'name2', is used for built-in ('default') themes and keys
381
+ added after 2015 Oct 1 and 2016 July 1. This kludge is needed
382
+ because setting 'name' to a builtin not defined in older IDLEs
383
+ to display multiple error messages or quit.
384
+ See https://bugs.python.org/issue25313.
385
+ When default = True, 'name2' takes precedence over 'name',
386
+ while older IDLEs will just use name. When default = False,
387
+ 'name2' may still be set, but it is ignored.
388
+ """
389
+ cfgname = 'highlight' if section == 'Theme' else 'keys'
390
+ default = self.GetOption('main', section, 'default',
391
+ type='bool', default=True)
392
+ name = ''
393
+ if default:
394
+ name = self.GetOption('main', section, 'name2', default='')
395
+ if not name:
396
+ name = self.GetOption('main', section, 'name', default='')
397
+ if name:
398
+ source = self.defaultCfg if default else self.userCfg
399
+ if source[cfgname].has_section(name):
400
+ return name
401
+ return "IDLE Classic" if section == 'Theme' else self.default_keys()
402
+
403
+ @staticmethod
404
+ def default_keys():
405
+ if sys.platform[:3] == 'win':
406
+ return 'IDLE Classic Windows'
407
+ elif sys.platform == 'darwin':
408
+ return 'IDLE Classic OSX'
409
+ else:
410
+ return 'IDLE Modern Unix'
411
+
412
+ def GetExtensions(self, active_only=True,
413
+ editor_only=False, shell_only=False):
414
+ """Return extensions in default and user config-extensions files.
415
+
416
+ If active_only True, only return active (enabled) extensions
417
+ and optionally only editor or shell extensions.
418
+ If active_only False, return all extensions.
419
+ """
420
+ extns = self.RemoveKeyBindNames(
421
+ self.GetSectionList('default', 'extensions'))
422
+ userExtns = self.RemoveKeyBindNames(
423
+ self.GetSectionList('user', 'extensions'))
424
+ for extn in userExtns:
425
+ if extn not in extns: #user has added own extension
426
+ extns.append(extn)
427
+ for extn in ('AutoComplete','CodeContext',
428
+ 'FormatParagraph','ParenMatch'):
429
+ extns.remove(extn)
430
+ # specific exclusions because we are storing config for mainlined old
431
+ # extensions in config-extensions.def for backward compatibility
432
+ if active_only:
433
+ activeExtns = []
434
+ for extn in extns:
435
+ if self.GetOption('extensions', extn, 'enable', default=True,
436
+ type='bool'):
437
+ #the extension is enabled
438
+ if editor_only or shell_only: # TODO both True contradict
439
+ if editor_only:
440
+ option = "enable_editor"
441
+ else:
442
+ option = "enable_shell"
443
+ if self.GetOption('extensions', extn,option,
444
+ default=True, type='bool',
445
+ warn_on_default=False):
446
+ activeExtns.append(extn)
447
+ else:
448
+ activeExtns.append(extn)
449
+ return activeExtns
450
+ else:
451
+ return extns
452
+
453
+ def RemoveKeyBindNames(self, extnNameList):
454
+ "Return extnNameList with keybinding section names removed."
455
+ return [n for n in extnNameList if not n.endswith(('_bindings', '_cfgBindings'))]
456
+
457
+ def GetExtnNameForEvent(self, virtualEvent):
458
+ """Return the name of the extension binding virtualEvent, or None.
459
+
460
+ virtualEvent - string, name of the virtual event to test for,
461
+ without the enclosing '<< >>'
462
+ """
463
+ extName = None
464
+ vEvent = '<<' + virtualEvent + '>>'
465
+ for extn in self.GetExtensions(active_only=0):
466
+ for event in self.GetExtensionKeys(extn):
467
+ if event == vEvent:
468
+ extName = extn # TODO return here?
469
+ return extName
470
+
471
+ def GetExtensionKeys(self, extensionName):
472
+ """Return dict: {configurable extensionName event : active keybinding}.
473
+
474
+ Events come from default config extension_cfgBindings section.
475
+ Keybindings come from GetCurrentKeySet() active key dict,
476
+ where previously used bindings are disabled.
477
+ """
478
+ keysName = extensionName + '_cfgBindings'
479
+ activeKeys = self.GetCurrentKeySet()
480
+ extKeys = {}
481
+ if self.defaultCfg['extensions'].has_section(keysName):
482
+ eventNames = self.defaultCfg['extensions'].GetOptionList(keysName)
483
+ for eventName in eventNames:
484
+ event = '<<' + eventName + '>>'
485
+ binding = activeKeys[event]
486
+ extKeys[event] = binding
487
+ return extKeys
488
+
489
+ def __GetRawExtensionKeys(self,extensionName):
490
+ """Return dict {configurable extensionName event : keybinding list}.
491
+
492
+ Events come from default config extension_cfgBindings section.
493
+ Keybindings list come from the splitting of GetOption, which
494
+ tries user config before default config.
495
+ """
496
+ keysName = extensionName+'_cfgBindings'
497
+ extKeys = {}
498
+ if self.defaultCfg['extensions'].has_section(keysName):
499
+ eventNames = self.defaultCfg['extensions'].GetOptionList(keysName)
500
+ for eventName in eventNames:
501
+ binding = self.GetOption(
502
+ 'extensions', keysName, eventName, default='').split()
503
+ event = '<<' + eventName + '>>'
504
+ extKeys[event] = binding
505
+ return extKeys
506
+
507
+ def GetExtensionBindings(self, extensionName):
508
+ """Return dict {extensionName event : active or defined keybinding}.
509
+
510
+ Augment self.GetExtensionKeys(extensionName) with mapping of non-
511
+ configurable events (from default config) to GetOption splits,
512
+ as in self.__GetRawExtensionKeys.
513
+ """
514
+ bindsName = extensionName + '_bindings'
515
+ extBinds = self.GetExtensionKeys(extensionName)
516
+ #add the non-configurable bindings
517
+ if self.defaultCfg['extensions'].has_section(bindsName):
518
+ eventNames = self.defaultCfg['extensions'].GetOptionList(bindsName)
519
+ for eventName in eventNames:
520
+ binding = self.GetOption(
521
+ 'extensions', bindsName, eventName, default='').split()
522
+ event = '<<' + eventName + '>>'
523
+ extBinds[event] = binding
524
+
525
+ return extBinds
526
+
527
+ def GetKeyBinding(self, keySetName, eventStr):
528
+ """Return the keybinding list for keySetName eventStr.
529
+
530
+ keySetName - name of key binding set (config-keys section).
531
+ eventStr - virtual event, including brackets, as in '<<event>>'.
532
+ """
533
+ eventName = eventStr[2:-2] #trim off the angle brackets
534
+ binding = self.GetOption('keys', keySetName, eventName, default='',
535
+ warn_on_default=False).split()
536
+ return binding
537
+
538
+ def GetCurrentKeySet(self):
539
+ "Return CurrentKeys with 'darwin' modifications."
540
+ result = self.GetKeySet(self.CurrentKeys())
541
+
542
+ if sys.platform == "darwin":
543
+ # macOS (OS X) Tk variants do not support the "Alt"
544
+ # keyboard modifier. Replace it with "Option".
545
+ # TODO (Ned?): the "Option" modifier does not work properly
546
+ # for Cocoa Tk and XQuartz Tk so we should not use it
547
+ # in the default 'OSX' keyset.
548
+ for k, v in result.items():
549
+ v2 = [ x.replace('<Alt-', '<Option-') for x in v ]
550
+ if v != v2:
551
+ result[k] = v2
552
+
553
+ return result
554
+
555
+ def GetKeySet(self, keySetName):
556
+ """Return event-key dict for keySetName core plus active extensions.
557
+
558
+ If a binding defined in an extension is already in use, the
559
+ extension binding is disabled by being set to ''
560
+ """
561
+ keySet = self.GetCoreKeys(keySetName)
562
+ activeExtns = self.GetExtensions(active_only=1)
563
+ for extn in activeExtns:
564
+ extKeys = self.__GetRawExtensionKeys(extn)
565
+ if extKeys: #the extension defines keybindings
566
+ for event in extKeys:
567
+ if extKeys[event] in keySet.values():
568
+ #the binding is already in use
569
+ extKeys[event] = '' #disable this binding
570
+ keySet[event] = extKeys[event] #add binding
571
+ return keySet
572
+
573
+ def IsCoreBinding(self, virtualEvent):
574
+ """Return True if the virtual event is one of the core idle key events.
575
+
576
+ virtualEvent - string, name of the virtual event to test for,
577
+ without the enclosing '<< >>'
578
+ """
579
+ return ('<<'+virtualEvent+'>>') in self.GetCoreKeys()
580
+
581
+ # TODO make keyBindins a file or class attribute used for test above
582
+ # and copied in function below.
583
+
584
+ former_extension_events = { # Those with user-configurable keys.
585
+ '<<force-open-completions>>', '<<expand-word>>',
586
+ '<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>',
587
+ '<<run-module>>', '<<check-module>>', '<<zoom-height>>',
588
+ '<<run-custom>>',
589
+ }
590
+
591
+ def GetCoreKeys(self, keySetName=None):
592
+ """Return dict of core virtual-key keybindings for keySetName.
593
+
594
+ The default keySetName None corresponds to the keyBindings base
595
+ dict. If keySetName is not None, bindings from the config
596
+ file(s) are loaded _over_ these defaults, so if there is a
597
+ problem getting any core binding there will be an 'ultimate last
598
+ resort fallback' to the CUA-ish bindings defined here.
599
+ """
600
+ keyBindings={
601
+ '<<copy>>': ['<Control-c>', '<Control-C>'],
602
+ '<<cut>>': ['<Control-x>', '<Control-X>'],
603
+ '<<paste>>': ['<Control-v>', '<Control-V>'],
604
+ '<<beginning-of-line>>': ['<Control-a>', '<Home>'],
605
+ '<<center-insert>>': ['<Control-l>'],
606
+ '<<close-all-windows>>': ['<Control-q>'],
607
+ '<<close-window>>': ['<Alt-F4>'],
608
+ '<<do-nothing>>': ['<Control-x>'],
609
+ '<<end-of-file>>': ['<Control-d>'],
610
+ '<<python-docs>>': ['<F1>'],
611
+ '<<python-context-help>>': ['<Shift-F1>'],
612
+ '<<history-next>>': ['<Alt-n>'],
613
+ '<<history-previous>>': ['<Alt-p>'],
614
+ '<<interrupt-execution>>': ['<Control-c>'],
615
+ '<<view-restart>>': ['<F6>'],
616
+ '<<restart-shell>>': ['<Control-F6>'],
617
+ '<<open-class-browser>>': ['<Alt-c>'],
618
+ '<<open-module>>': ['<Alt-m>'],
619
+ '<<open-new-window>>': ['<Control-n>'],
620
+ '<<open-window-from-file>>': ['<Control-o>'],
621
+ '<<plain-newline-and-indent>>': ['<Control-j>'],
622
+ '<<print-window>>': ['<Control-p>'],
623
+ '<<redo>>': ['<Control-y>'],
624
+ '<<remove-selection>>': ['<Escape>'],
625
+ '<<save-copy-of-window-as-file>>': ['<Alt-Shift-S>'],
626
+ '<<save-window-as-file>>': ['<Alt-s>'],
627
+ '<<save-window>>': ['<Control-s>'],
628
+ '<<select-all>>': ['<Alt-a>'],
629
+ '<<toggle-auto-coloring>>': ['<Control-slash>'],
630
+ '<<undo>>': ['<Control-z>'],
631
+ '<<find-again>>': ['<Control-g>', '<F3>'],
632
+ '<<find-in-files>>': ['<Alt-F3>'],
633
+ '<<find-selection>>': ['<Control-F3>'],
634
+ '<<find>>': ['<Control-f>'],
635
+ '<<replace>>': ['<Control-h>'],
636
+ '<<goto-line>>': ['<Alt-g>'],
637
+ '<<smart-backspace>>': ['<Key-BackSpace>'],
638
+ '<<newline-and-indent>>': ['<Key-Return>', '<Key-KP_Enter>'],
639
+ '<<smart-indent>>': ['<Key-Tab>'],
640
+ '<<indent-region>>': ['<Control-Key-bracketright>'],
641
+ '<<dedent-region>>': ['<Control-Key-bracketleft>'],
642
+ '<<comment-region>>': ['<Alt-Key-3>'],
643
+ '<<uncomment-region>>': ['<Alt-Key-4>'],
644
+ '<<tabify-region>>': ['<Alt-Key-5>'],
645
+ '<<untabify-region>>': ['<Alt-Key-6>'],
646
+ '<<toggle-tabs>>': ['<Alt-Key-t>'],
647
+ '<<change-indentwidth>>': ['<Alt-Key-u>'],
648
+ '<<del-word-left>>': ['<Control-Key-BackSpace>'],
649
+ '<<del-word-right>>': ['<Control-Key-Delete>'],
650
+ '<<force-open-completions>>': ['<Control-Key-space>'],
651
+ '<<expand-word>>': ['<Alt-Key-slash>'],
652
+ '<<force-open-calltip>>': ['<Control-Key-backslash>'],
653
+ '<<flash-paren>>': ['<Control-Key-0>'],
654
+ '<<format-paragraph>>': ['<Alt-Key-q>'],
655
+ '<<run-module>>': ['<Key-F5>'],
656
+ '<<run-custom>>': ['<Shift-Key-F5>'],
657
+ '<<check-module>>': ['<Alt-Key-x>'],
658
+ '<<zoom-height>>': ['<Alt-Key-2>'],
659
+ }
660
+
661
+ if keySetName:
662
+ if not (self.userCfg['keys'].has_section(keySetName) or
663
+ self.defaultCfg['keys'].has_section(keySetName)):
664
+ warning = (
665
+ '\n Warning: config.py - IdleConf.GetCoreKeys -\n'
666
+ ' key set %r is not defined, using default bindings.' %
667
+ (keySetName,)
668
+ )
669
+ _warn(warning, 'keys', keySetName)
670
+ else:
671
+ for event in keyBindings:
672
+ binding = self.GetKeyBinding(keySetName, event)
673
+ if binding:
674
+ keyBindings[event] = binding
675
+ # Otherwise return default in keyBindings.
676
+ elif event not in self.former_extension_events:
677
+ warning = (
678
+ '\n Warning: config.py - IdleConf.GetCoreKeys -\n'
679
+ ' problem retrieving key binding for event %r\n'
680
+ ' from key set %r.\n'
681
+ ' returning default value: %r' %
682
+ (event, keySetName, keyBindings[event])
683
+ )
684
+ _warn(warning, 'keys', keySetName, event)
685
+ return keyBindings
686
+
687
+ def GetExtraHelpSourceList(self, configSet):
688
+ """Return list of extra help sources from a given configSet.
689
+
690
+ Valid configSets are 'user' or 'default'. Return a list of tuples of
691
+ the form (menu_item , path_to_help_file , option), or return the empty
692
+ list. 'option' is the sequence number of the help resource. 'option'
693
+ values determine the position of the menu items on the Help menu,
694
+ therefore the returned list must be sorted by 'option'.
695
+
696
+ """
697
+ helpSources = []
698
+ if configSet == 'user':
699
+ cfgParser = self.userCfg['main']
700
+ elif configSet == 'default':
701
+ cfgParser = self.defaultCfg['main']
702
+ else:
703
+ raise InvalidConfigSet('Invalid configSet specified')
704
+ options=cfgParser.GetOptionList('HelpFiles')
705
+ for option in options:
706
+ value=cfgParser.Get('HelpFiles', option, default=';')
707
+ if value.find(';') == -1: #malformed config entry with no ';'
708
+ menuItem = '' #make these empty
709
+ helpPath = '' #so value won't be added to list
710
+ else: #config entry contains ';' as expected
711
+ value=value.split(';')
712
+ menuItem=value[0].strip()
713
+ helpPath=value[1].strip()
714
+ if menuItem and helpPath: #neither are empty strings
715
+ helpSources.append( (menuItem,helpPath,option) )
716
+ helpSources.sort(key=lambda x: x[2])
717
+ return helpSources
718
+
719
+ def GetAllExtraHelpSourcesList(self):
720
+ """Return a list of the details of all additional help sources.
721
+
722
+ Tuples in the list are those of GetExtraHelpSourceList.
723
+ """
724
+ allHelpSources = (self.GetExtraHelpSourceList('default') +
725
+ self.GetExtraHelpSourceList('user') )
726
+ return allHelpSources
727
+
728
+ def GetFont(self, root, configType, section):
729
+ """Retrieve a font from configuration (font, font-size, font-bold)
730
+ Intercept the special value 'TkFixedFont' and substitute
731
+ the actual font, factoring in some tweaks if needed for
732
+ appearance sakes.
733
+
734
+ The 'root' parameter can normally be any valid Tkinter widget.
735
+
736
+ Return a tuple (family, size, weight) suitable for passing
737
+ to tkinter.Font
738
+ """
739
+ family = self.GetOption(configType, section, 'font', default='courier')
740
+ size = self.GetOption(configType, section, 'font-size', type='int',
741
+ default='10')
742
+ bold = self.GetOption(configType, section, 'font-bold', default=0,
743
+ type='bool')
744
+ if (family == 'TkFixedFont'):
745
+ f = Font(name='TkFixedFont', exists=True, root=root)
746
+ actualFont = Font.actual(f)
747
+ family = actualFont['family']
748
+ size = actualFont['size']
749
+ if size <= 0:
750
+ size = 10 # if font in pixels, ignore actual size
751
+ bold = actualFont['weight'] == 'bold'
752
+ return (family, size, 'bold' if bold else 'normal')
753
+
754
+ def LoadCfgFiles(self):
755
+ "Load all configuration files."
756
+ for key in self.defaultCfg:
757
+ self.defaultCfg[key].Load()
758
+ self.userCfg[key].Load() #same keys
759
+
760
+ def SaveUserCfgFiles(self):
761
+ "Write all loaded user configuration files to disk."
762
+ for key in self.userCfg:
763
+ self.userCfg[key].Save()
764
+
765
+
766
+ idleConf = IdleConf()
767
+
768
+ _warned = set()
769
+ def _warn(msg, *key):
770
+ key = (msg,) + key
771
+ if key not in _warned:
772
+ try:
773
+ print(msg, file=sys.stderr)
774
+ except OSError:
775
+ pass
776
+ _warned.add(key)
777
+
778
+
779
+ class ConfigChanges(dict):
780
+ """Manage a user's proposed configuration option changes.
781
+
782
+ Names used across multiple methods:
783
+ page -- one of the 4 top-level dicts representing a
784
+ .idlerc/config-x.cfg file.
785
+ config_type -- name of a page.
786
+ section -- a section within a page/file.
787
+ option -- name of an option within a section.
788
+ value -- value for the option.
789
+
790
+ Methods
791
+ add_option: Add option and value to changes.
792
+ save_option: Save option and value to config parser.
793
+ save_all: Save all the changes to the config parser and file.
794
+ delete_section: If section exists,
795
+ delete from changes, userCfg, and file.
796
+ clear: Clear all changes by clearing each page.
797
+ """
798
+ def __init__(self):
799
+ "Create a page for each configuration file"
800
+ self.pages = [] # List of unhashable dicts.
801
+ for config_type in idleConf.config_types:
802
+ self[config_type] = {}
803
+ self.pages.append(self[config_type])
804
+
805
+ def add_option(self, config_type, section, item, value):
806
+ "Add item/value pair for config_type and section."
807
+ page = self[config_type]
808
+ value = str(value) # Make sure we use a string.
809
+ if section not in page:
810
+ page[section] = {}
811
+ page[section][item] = value
812
+
813
+ @staticmethod
814
+ def save_option(config_type, section, item, value):
815
+ """Return True if the configuration value was added or changed.
816
+
817
+ Helper for save_all.
818
+ """
819
+ if idleConf.defaultCfg[config_type].has_option(section, item):
820
+ if idleConf.defaultCfg[config_type].Get(section, item) == value:
821
+ # The setting equals a default setting, remove it from user cfg.
822
+ return idleConf.userCfg[config_type].RemoveOption(section, item)
823
+ # If we got here, set the option.
824
+ return idleConf.userCfg[config_type].SetOption(section, item, value)
825
+
826
+ def save_all(self):
827
+ """Save configuration changes to the user config file.
828
+
829
+ Clear self in preparation for additional changes.
830
+ Return changed for testing.
831
+ """
832
+ idleConf.userCfg['main'].Save()
833
+
834
+ changed = False
835
+ for config_type in self:
836
+ cfg_type_changed = False
837
+ page = self[config_type]
838
+ for section in page:
839
+ if section == 'HelpFiles': # Remove it for replacement.
840
+ idleConf.userCfg['main'].remove_section('HelpFiles')
841
+ cfg_type_changed = True
842
+ for item, value in page[section].items():
843
+ if self.save_option(config_type, section, item, value):
844
+ cfg_type_changed = True
845
+ if cfg_type_changed:
846
+ idleConf.userCfg[config_type].Save()
847
+ changed = True
848
+ for config_type in ['keys', 'highlight']:
849
+ # Save these even if unchanged!
850
+ idleConf.userCfg[config_type].Save()
851
+ self.clear()
852
+ # ConfigDialog caller must add the following call
853
+ # self.save_all_changed_extensions() # Uses a different mechanism.
854
+ return changed
855
+
856
+ def delete_section(self, config_type, section):
857
+ """Delete a section from self, userCfg, and file.
858
+
859
+ Used to delete custom themes and keysets.
860
+ """
861
+ if section in self[config_type]:
862
+ del self[config_type][section]
863
+ configpage = idleConf.userCfg[config_type]
864
+ configpage.remove_section(section)
865
+ configpage.Save()
866
+
867
+ def clear(self):
868
+ """Clear all 4 pages.
869
+
870
+ Called in save_all after saving to idleConf.
871
+ XXX Mark window *title* when there are changes; unmark here.
872
+ """
873
+ for page in self.pages:
874
+ page.clear()
875
+
876
+
877
+ # TODO Revise test output, write expanded unittest
878
+ def _dump(): # htest # (not really, but ignore in coverage)
879
+ from zlib import crc32
880
+ line, crc = 0, 0
881
+
882
+ def sprint(obj):
883
+ global line, crc
884
+ txt = str(obj)
885
+ line += 1
886
+ crc = crc32(txt.encode(encoding='utf-8'), crc)
887
+ print(txt)
888
+ #print('***', line, crc, '***') # Uncomment for diagnosis.
889
+
890
+ def dumpCfg(cfg):
891
+ print('\n', cfg, '\n') # Cfg has variable '0xnnnnnnnn' address.
892
+ for key in sorted(cfg.keys()):
893
+ sections = cfg[key].sections()
894
+ sprint(key)
895
+ sprint(sections)
896
+ for section in sections:
897
+ options = cfg[key].options(section)
898
+ sprint(section)
899
+ sprint(options)
900
+ for option in options:
901
+ sprint(option + ' = ' + cfg[key].Get(section, option))
902
+
903
+ dumpCfg(idleConf.defaultCfg)
904
+ dumpCfg(idleConf.userCfg)
905
+ print('\nlines = ', line, ', crc = ', crc, sep='')
906
+
907
+ if __name__ == '__main__':
908
+ from unittest import main
909
+ main('idlelib.idle_test.test_config', verbosity=2, exit=False)
910
+
911
+ # Run revised _dump() as htest?
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/configdialog.py ADDED
The diff for this file is too large to render. See raw diff
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/debugger.py ADDED
@@ -0,0 +1,550 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import bdb
2
+ import os
3
+
4
+ from tkinter import *
5
+ from tkinter.ttk import Frame, Scrollbar
6
+
7
+ from idlelib import macosx
8
+ from idlelib.scrolledlist import ScrolledList
9
+ from idlelib.window import ListedToplevel
10
+
11
+
12
+ class Idb(bdb.Bdb):
13
+
14
+ def __init__(self, gui):
15
+ self.gui = gui # An instance of Debugger or proxy of remote.
16
+ bdb.Bdb.__init__(self)
17
+
18
+ def user_line(self, frame):
19
+ if self.in_rpc_code(frame):
20
+ self.set_step()
21
+ return
22
+ message = self.__frame2message(frame)
23
+ try:
24
+ self.gui.interaction(message, frame)
25
+ except TclError: # When closing debugger window with [x] in 3.x
26
+ pass
27
+
28
+ def user_exception(self, frame, info):
29
+ if self.in_rpc_code(frame):
30
+ self.set_step()
31
+ return
32
+ message = self.__frame2message(frame)
33
+ self.gui.interaction(message, frame, info)
34
+
35
+ def in_rpc_code(self, frame):
36
+ if frame.f_code.co_filename.count('rpc.py'):
37
+ return True
38
+ else:
39
+ prev_frame = frame.f_back
40
+ prev_name = prev_frame.f_code.co_filename
41
+ if 'idlelib' in prev_name and 'debugger' in prev_name:
42
+ # catch both idlelib/debugger.py and idlelib/debugger_r.py
43
+ # on both Posix and Windows
44
+ return False
45
+ return self.in_rpc_code(prev_frame)
46
+
47
+ def __frame2message(self, frame):
48
+ code = frame.f_code
49
+ filename = code.co_filename
50
+ lineno = frame.f_lineno
51
+ basename = os.path.basename(filename)
52
+ message = "%s:%s" % (basename, lineno)
53
+ if code.co_name != "?":
54
+ message = "%s: %s()" % (message, code.co_name)
55
+ return message
56
+
57
+
58
+ class Debugger:
59
+
60
+ vstack = vsource = vlocals = vglobals = None
61
+
62
+ def __init__(self, pyshell, idb=None):
63
+ if idb is None:
64
+ idb = Idb(self)
65
+ self.pyshell = pyshell
66
+ self.idb = idb # If passed, a proxy of remote instance.
67
+ self.frame = None
68
+ self.make_gui()
69
+ self.interacting = 0
70
+ self.nesting_level = 0
71
+
72
+ def run(self, *args):
73
+ # Deal with the scenario where we've already got a program running
74
+ # in the debugger and we want to start another. If that is the case,
75
+ # our second 'run' was invoked from an event dispatched not from
76
+ # the main event loop, but from the nested event loop in 'interaction'
77
+ # below. So our stack looks something like this:
78
+ # outer main event loop
79
+ # run()
80
+ # <running program with traces>
81
+ # callback to debugger's interaction()
82
+ # nested event loop
83
+ # run() for second command
84
+ #
85
+ # This kind of nesting of event loops causes all kinds of problems
86
+ # (see e.g. issue #24455) especially when dealing with running as a
87
+ # subprocess, where there's all kinds of extra stuff happening in
88
+ # there - insert a traceback.print_stack() to check it out.
89
+ #
90
+ # By this point, we've already called restart_subprocess() in
91
+ # ScriptBinding. However, we also need to unwind the stack back to
92
+ # that outer event loop. To accomplish this, we:
93
+ # - return immediately from the nested run()
94
+ # - abort_loop ensures the nested event loop will terminate
95
+ # - the debugger's interaction routine completes normally
96
+ # - the restart_subprocess() will have taken care of stopping
97
+ # the running program, which will also let the outer run complete
98
+ #
99
+ # That leaves us back at the outer main event loop, at which point our
100
+ # after event can fire, and we'll come back to this routine with a
101
+ # clean stack.
102
+ if self.nesting_level > 0:
103
+ self.abort_loop()
104
+ self.root.after(100, lambda: self.run(*args))
105
+ return
106
+ try:
107
+ self.interacting = 1
108
+ return self.idb.run(*args)
109
+ finally:
110
+ self.interacting = 0
111
+
112
+ def close(self, event=None):
113
+ try:
114
+ self.quit()
115
+ except Exception:
116
+ pass
117
+ if self.interacting:
118
+ self.top.bell()
119
+ return
120
+ if self.stackviewer:
121
+ self.stackviewer.close(); self.stackviewer = None
122
+ # Clean up pyshell if user clicked debugger control close widget.
123
+ # (Causes a harmless extra cycle through close_debugger() if user
124
+ # toggled debugger from pyshell Debug menu)
125
+ self.pyshell.close_debugger()
126
+ # Now close the debugger control window....
127
+ self.top.destroy()
128
+
129
+ def make_gui(self):
130
+ pyshell = self.pyshell
131
+ self.flist = pyshell.flist
132
+ self.root = root = pyshell.root
133
+ self.top = top = ListedToplevel(root)
134
+ self.top.wm_title("Debug Control")
135
+ self.top.wm_iconname("Debug")
136
+ top.wm_protocol("WM_DELETE_WINDOW", self.close)
137
+ self.top.bind("<Escape>", self.close)
138
+ #
139
+ self.bframe = bframe = Frame(top)
140
+ self.bframe.pack(anchor="w")
141
+ self.buttons = bl = []
142
+ #
143
+ self.bcont = b = Button(bframe, text="Go", command=self.cont)
144
+ bl.append(b)
145
+ self.bstep = b = Button(bframe, text="Step", command=self.step)
146
+ bl.append(b)
147
+ self.bnext = b = Button(bframe, text="Over", command=self.next)
148
+ bl.append(b)
149
+ self.bret = b = Button(bframe, text="Out", command=self.ret)
150
+ bl.append(b)
151
+ self.bret = b = Button(bframe, text="Quit", command=self.quit)
152
+ bl.append(b)
153
+ #
154
+ for b in bl:
155
+ b.configure(state="disabled")
156
+ b.pack(side="left")
157
+ #
158
+ self.cframe = cframe = Frame(bframe)
159
+ self.cframe.pack(side="left")
160
+ #
161
+ if not self.vstack:
162
+ self.__class__.vstack = BooleanVar(top)
163
+ self.vstack.set(1)
164
+ self.bstack = Checkbutton(cframe,
165
+ text="Stack", command=self.show_stack, variable=self.vstack)
166
+ self.bstack.grid(row=0, column=0)
167
+ if not self.vsource:
168
+ self.__class__.vsource = BooleanVar(top)
169
+ self.bsource = Checkbutton(cframe,
170
+ text="Source", command=self.show_source, variable=self.vsource)
171
+ self.bsource.grid(row=0, column=1)
172
+ if not self.vlocals:
173
+ self.__class__.vlocals = BooleanVar(top)
174
+ self.vlocals.set(1)
175
+ self.blocals = Checkbutton(cframe,
176
+ text="Locals", command=self.show_locals, variable=self.vlocals)
177
+ self.blocals.grid(row=1, column=0)
178
+ if not self.vglobals:
179
+ self.__class__.vglobals = BooleanVar(top)
180
+ self.bglobals = Checkbutton(cframe,
181
+ text="Globals", command=self.show_globals, variable=self.vglobals)
182
+ self.bglobals.grid(row=1, column=1)
183
+ #
184
+ self.status = Label(top, anchor="w")
185
+ self.status.pack(anchor="w")
186
+ self.error = Label(top, anchor="w")
187
+ self.error.pack(anchor="w", fill="x")
188
+ self.errorbg = self.error.cget("background")
189
+ #
190
+ self.fstack = Frame(top, height=1)
191
+ self.fstack.pack(expand=1, fill="both")
192
+ self.flocals = Frame(top)
193
+ self.flocals.pack(expand=1, fill="both")
194
+ self.fglobals = Frame(top, height=1)
195
+ self.fglobals.pack(expand=1, fill="both")
196
+ #
197
+ if self.vstack.get():
198
+ self.show_stack()
199
+ if self.vlocals.get():
200
+ self.show_locals()
201
+ if self.vglobals.get():
202
+ self.show_globals()
203
+
204
+ def interaction(self, message, frame, info=None):
205
+ self.frame = frame
206
+ self.status.configure(text=message)
207
+ #
208
+ if info:
209
+ type, value, tb = info
210
+ try:
211
+ m1 = type.__name__
212
+ except AttributeError:
213
+ m1 = "%s" % str(type)
214
+ if value is not None:
215
+ try:
216
+ m1 = "%s: %s" % (m1, str(value))
217
+ except:
218
+ pass
219
+ bg = "yellow"
220
+ else:
221
+ m1 = ""
222
+ tb = None
223
+ bg = self.errorbg
224
+ self.error.configure(text=m1, background=bg)
225
+ #
226
+ sv = self.stackviewer
227
+ if sv:
228
+ stack, i = self.idb.get_stack(self.frame, tb)
229
+ sv.load_stack(stack, i)
230
+ #
231
+ self.show_variables(1)
232
+ #
233
+ if self.vsource.get():
234
+ self.sync_source_line()
235
+ #
236
+ for b in self.buttons:
237
+ b.configure(state="normal")
238
+ #
239
+ self.top.wakeup()
240
+ # Nested main loop: Tkinter's main loop is not reentrant, so use
241
+ # Tcl's vwait facility, which reenters the event loop until an
242
+ # event handler sets the variable we're waiting on
243
+ self.nesting_level += 1
244
+ self.root.tk.call('vwait', '::idledebugwait')
245
+ self.nesting_level -= 1
246
+ #
247
+ for b in self.buttons:
248
+ b.configure(state="disabled")
249
+ self.status.configure(text="")
250
+ self.error.configure(text="", background=self.errorbg)
251
+ self.frame = None
252
+
253
+ def sync_source_line(self):
254
+ frame = self.frame
255
+ if not frame:
256
+ return
257
+ filename, lineno = self.__frame2fileline(frame)
258
+ if filename[:1] + filename[-1:] != "<>" and os.path.exists(filename):
259
+ self.flist.gotofileline(filename, lineno)
260
+
261
+ def __frame2fileline(self, frame):
262
+ code = frame.f_code
263
+ filename = code.co_filename
264
+ lineno = frame.f_lineno
265
+ return filename, lineno
266
+
267
+ def cont(self):
268
+ self.idb.set_continue()
269
+ self.abort_loop()
270
+
271
+ def step(self):
272
+ self.idb.set_step()
273
+ self.abort_loop()
274
+
275
+ def next(self):
276
+ self.idb.set_next(self.frame)
277
+ self.abort_loop()
278
+
279
+ def ret(self):
280
+ self.idb.set_return(self.frame)
281
+ self.abort_loop()
282
+
283
+ def quit(self):
284
+ self.idb.set_quit()
285
+ self.abort_loop()
286
+
287
+ def abort_loop(self):
288
+ self.root.tk.call('set', '::idledebugwait', '1')
289
+
290
+ stackviewer = None
291
+
292
+ def show_stack(self):
293
+ if not self.stackviewer and self.vstack.get():
294
+ self.stackviewer = sv = StackViewer(self.fstack, self.flist, self)
295
+ if self.frame:
296
+ stack, i = self.idb.get_stack(self.frame, None)
297
+ sv.load_stack(stack, i)
298
+ else:
299
+ sv = self.stackviewer
300
+ if sv and not self.vstack.get():
301
+ self.stackviewer = None
302
+ sv.close()
303
+ self.fstack['height'] = 1
304
+
305
+ def show_source(self):
306
+ if self.vsource.get():
307
+ self.sync_source_line()
308
+
309
+ def show_frame(self, stackitem):
310
+ self.frame = stackitem[0] # lineno is stackitem[1]
311
+ self.show_variables()
312
+
313
+ localsviewer = None
314
+ globalsviewer = None
315
+
316
+ def show_locals(self):
317
+ lv = self.localsviewer
318
+ if self.vlocals.get():
319
+ if not lv:
320
+ self.localsviewer = NamespaceViewer(self.flocals, "Locals")
321
+ else:
322
+ if lv:
323
+ self.localsviewer = None
324
+ lv.close()
325
+ self.flocals['height'] = 1
326
+ self.show_variables()
327
+
328
+ def show_globals(self):
329
+ gv = self.globalsviewer
330
+ if self.vglobals.get():
331
+ if not gv:
332
+ self.globalsviewer = NamespaceViewer(self.fglobals, "Globals")
333
+ else:
334
+ if gv:
335
+ self.globalsviewer = None
336
+ gv.close()
337
+ self.fglobals['height'] = 1
338
+ self.show_variables()
339
+
340
+ def show_variables(self, force=0):
341
+ lv = self.localsviewer
342
+ gv = self.globalsviewer
343
+ frame = self.frame
344
+ if not frame:
345
+ ldict = gdict = None
346
+ else:
347
+ ldict = frame.f_locals
348
+ gdict = frame.f_globals
349
+ if lv and gv and ldict is gdict:
350
+ ldict = None
351
+ if lv:
352
+ lv.load_dict(ldict, force, self.pyshell.interp.rpcclt)
353
+ if gv:
354
+ gv.load_dict(gdict, force, self.pyshell.interp.rpcclt)
355
+
356
+ def set_breakpoint_here(self, filename, lineno):
357
+ self.idb.set_break(filename, lineno)
358
+
359
+ def clear_breakpoint_here(self, filename, lineno):
360
+ self.idb.clear_break(filename, lineno)
361
+
362
+ def clear_file_breaks(self, filename):
363
+ self.idb.clear_all_file_breaks(filename)
364
+
365
+ def load_breakpoints(self):
366
+ "Load PyShellEditorWindow breakpoints into subprocess debugger"
367
+ for editwin in self.pyshell.flist.inversedict:
368
+ filename = editwin.io.filename
369
+ try:
370
+ for lineno in editwin.breakpoints:
371
+ self.set_breakpoint_here(filename, lineno)
372
+ except AttributeError:
373
+ continue
374
+
375
+ class StackViewer(ScrolledList):
376
+
377
+ def __init__(self, master, flist, gui):
378
+ if macosx.isAquaTk():
379
+ # At least on with the stock AquaTk version on OSX 10.4 you'll
380
+ # get a shaking GUI that eventually kills IDLE if the width
381
+ # argument is specified.
382
+ ScrolledList.__init__(self, master)
383
+ else:
384
+ ScrolledList.__init__(self, master, width=80)
385
+ self.flist = flist
386
+ self.gui = gui
387
+ self.stack = []
388
+
389
+ def load_stack(self, stack, index=None):
390
+ self.stack = stack
391
+ self.clear()
392
+ for i in range(len(stack)):
393
+ frame, lineno = stack[i]
394
+ try:
395
+ modname = frame.f_globals["__name__"]
396
+ except:
397
+ modname = "?"
398
+ code = frame.f_code
399
+ filename = code.co_filename
400
+ funcname = code.co_name
401
+ import linecache
402
+ sourceline = linecache.getline(filename, lineno)
403
+ sourceline = sourceline.strip()
404
+ if funcname in ("?", "", None):
405
+ item = "%s, line %d: %s" % (modname, lineno, sourceline)
406
+ else:
407
+ item = "%s.%s(), line %d: %s" % (modname, funcname,
408
+ lineno, sourceline)
409
+ if i == index:
410
+ item = "> " + item
411
+ self.append(item)
412
+ if index is not None:
413
+ self.select(index)
414
+
415
+ def popup_event(self, event):
416
+ "override base method"
417
+ if self.stack:
418
+ return ScrolledList.popup_event(self, event)
419
+
420
+ def fill_menu(self):
421
+ "override base method"
422
+ menu = self.menu
423
+ menu.add_command(label="Go to source line",
424
+ command=self.goto_source_line)
425
+ menu.add_command(label="Show stack frame",
426
+ command=self.show_stack_frame)
427
+
428
+ def on_select(self, index):
429
+ "override base method"
430
+ if 0 <= index < len(self.stack):
431
+ self.gui.show_frame(self.stack[index])
432
+
433
+ def on_double(self, index):
434
+ "override base method"
435
+ self.show_source(index)
436
+
437
+ def goto_source_line(self):
438
+ index = self.listbox.index("active")
439
+ self.show_source(index)
440
+
441
+ def show_stack_frame(self):
442
+ index = self.listbox.index("active")
443
+ if 0 <= index < len(self.stack):
444
+ self.gui.show_frame(self.stack[index])
445
+
446
+ def show_source(self, index):
447
+ if not (0 <= index < len(self.stack)):
448
+ return
449
+ frame, lineno = self.stack[index]
450
+ code = frame.f_code
451
+ filename = code.co_filename
452
+ if os.path.isfile(filename):
453
+ edit = self.flist.open(filename)
454
+ if edit:
455
+ edit.gotoline(lineno)
456
+
457
+
458
+ class NamespaceViewer:
459
+
460
+ def __init__(self, master, title, dict=None):
461
+ width = 0
462
+ height = 40
463
+ if dict:
464
+ height = 20*len(dict) # XXX 20 == observed height of Entry widget
465
+ self.master = master
466
+ self.title = title
467
+ import reprlib
468
+ self.repr = reprlib.Repr()
469
+ self.repr.maxstring = 60
470
+ self.repr.maxother = 60
471
+ self.frame = frame = Frame(master)
472
+ self.frame.pack(expand=1, fill="both")
473
+ self.label = Label(frame, text=title, borderwidth=2, relief="groove")
474
+ self.label.pack(fill="x")
475
+ self.vbar = vbar = Scrollbar(frame, name="vbar")
476
+ vbar.pack(side="right", fill="y")
477
+ self.canvas = canvas = Canvas(frame,
478
+ height=min(300, max(40, height)),
479
+ scrollregion=(0, 0, width, height))
480
+ canvas.pack(side="left", fill="both", expand=1)
481
+ vbar["command"] = canvas.yview
482
+ canvas["yscrollcommand"] = vbar.set
483
+ self.subframe = subframe = Frame(canvas)
484
+ self.sfid = canvas.create_window(0, 0, window=subframe, anchor="nw")
485
+ self.load_dict(dict)
486
+
487
+ dict = -1
488
+
489
+ def load_dict(self, dict, force=0, rpc_client=None):
490
+ if dict is self.dict and not force:
491
+ return
492
+ subframe = self.subframe
493
+ frame = self.frame
494
+ for c in list(subframe.children.values()):
495
+ c.destroy()
496
+ self.dict = None
497
+ if not dict:
498
+ l = Label(subframe, text="None")
499
+ l.grid(row=0, column=0)
500
+ else:
501
+ #names = sorted(dict)
502
+ ###
503
+ # Because of (temporary) limitations on the dict_keys type (not yet
504
+ # public or pickleable), have the subprocess to send a list of
505
+ # keys, not a dict_keys object. sorted() will take a dict_keys
506
+ # (no subprocess) or a list.
507
+ #
508
+ # There is also an obscure bug in sorted(dict) where the
509
+ # interpreter gets into a loop requesting non-existing dict[0],
510
+ # dict[1], dict[2], etc from the debugger_r.DictProxy.
511
+ ###
512
+ keys_list = dict.keys()
513
+ names = sorted(keys_list)
514
+ ###
515
+ row = 0
516
+ for name in names:
517
+ value = dict[name]
518
+ svalue = self.repr.repr(value) # repr(value)
519
+ # Strip extra quotes caused by calling repr on the (already)
520
+ # repr'd value sent across the RPC interface:
521
+ if rpc_client:
522
+ svalue = svalue[1:-1]
523
+ l = Label(subframe, text=name)
524
+ l.grid(row=row, column=0, sticky="nw")
525
+ l = Entry(subframe, width=0, borderwidth=0)
526
+ l.insert(0, svalue)
527
+ l.grid(row=row, column=1, sticky="nw")
528
+ row = row+1
529
+ self.dict = dict
530
+ # XXX Could we use a <Configure> callback for the following?
531
+ subframe.update_idletasks() # Alas!
532
+ width = subframe.winfo_reqwidth()
533
+ height = subframe.winfo_reqheight()
534
+ canvas = self.canvas
535
+ self.canvas["scrollregion"] = (0, 0, width, height)
536
+ if height > 300:
537
+ canvas["height"] = 300
538
+ frame.pack(expand=1)
539
+ else:
540
+ canvas["height"] = height
541
+ frame.pack(expand=0)
542
+
543
+ def close(self):
544
+ self.frame.destroy()
545
+
546
+ if __name__ == "__main__":
547
+ from unittest import main
548
+ main('idlelib.idle_test.test_debugger', verbosity=2, exit=False)
549
+
550
+ # TODO: htest?
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/debugger_r.py ADDED
@@ -0,0 +1,393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Support for remote Python debugging.
2
+
3
+ Some ASCII art to describe the structure:
4
+
5
+ IN PYTHON SUBPROCESS # IN IDLE PROCESS
6
+ #
7
+ # oid='gui_adapter'
8
+ +----------+ # +------------+ +-----+
9
+ | GUIProxy |--remote#call-->| GUIAdapter |--calls-->| GUI |
10
+ +-----+--calls-->+----------+ # +------------+ +-----+
11
+ | Idb | # /
12
+ +-----+<-calls--+------------+ # +----------+<--calls-/
13
+ | IdbAdapter |<--remote#call--| IdbProxy |
14
+ +------------+ # +----------+
15
+ oid='idb_adapter' #
16
+
17
+ The purpose of the Proxy and Adapter classes is to translate certain
18
+ arguments and return values that cannot be transported through the RPC
19
+ barrier, in particular frame and traceback objects.
20
+
21
+ """
22
+ import reprlib
23
+ import types
24
+ from idlelib import debugger
25
+
26
+ debugging = 0
27
+
28
+ idb_adap_oid = "idb_adapter"
29
+ gui_adap_oid = "gui_adapter"
30
+
31
+ #=======================================
32
+ #
33
+ # In the PYTHON subprocess:
34
+
35
+ frametable = {}
36
+ dicttable = {}
37
+ codetable = {}
38
+ tracebacktable = {}
39
+
40
+ def wrap_frame(frame):
41
+ fid = id(frame)
42
+ frametable[fid] = frame
43
+ return fid
44
+
45
+ def wrap_info(info):
46
+ "replace info[2], a traceback instance, by its ID"
47
+ if info is None:
48
+ return None
49
+ else:
50
+ traceback = info[2]
51
+ assert isinstance(traceback, types.TracebackType)
52
+ traceback_id = id(traceback)
53
+ tracebacktable[traceback_id] = traceback
54
+ modified_info = (info[0], info[1], traceback_id)
55
+ return modified_info
56
+
57
+ class GUIProxy:
58
+
59
+ def __init__(self, conn, gui_adap_oid):
60
+ self.conn = conn
61
+ self.oid = gui_adap_oid
62
+
63
+ def interaction(self, message, frame, info=None):
64
+ # calls rpc.SocketIO.remotecall() via run.MyHandler instance
65
+ # pass frame and traceback object IDs instead of the objects themselves
66
+ self.conn.remotecall(self.oid, "interaction",
67
+ (message, wrap_frame(frame), wrap_info(info)),
68
+ {})
69
+
70
+ class IdbAdapter:
71
+
72
+ def __init__(self, idb):
73
+ self.idb = idb
74
+
75
+ #----------called by an IdbProxy----------
76
+
77
+ def set_step(self):
78
+ self.idb.set_step()
79
+
80
+ def set_quit(self):
81
+ self.idb.set_quit()
82
+
83
+ def set_continue(self):
84
+ self.idb.set_continue()
85
+
86
+ def set_next(self, fid):
87
+ frame = frametable[fid]
88
+ self.idb.set_next(frame)
89
+
90
+ def set_return(self, fid):
91
+ frame = frametable[fid]
92
+ self.idb.set_return(frame)
93
+
94
+ def get_stack(self, fid, tbid):
95
+ frame = frametable[fid]
96
+ if tbid is None:
97
+ tb = None
98
+ else:
99
+ tb = tracebacktable[tbid]
100
+ stack, i = self.idb.get_stack(frame, tb)
101
+ stack = [(wrap_frame(frame2), k) for frame2, k in stack]
102
+ return stack, i
103
+
104
+ def run(self, cmd):
105
+ import __main__
106
+ self.idb.run(cmd, __main__.__dict__)
107
+
108
+ def set_break(self, filename, lineno):
109
+ msg = self.idb.set_break(filename, lineno)
110
+ return msg
111
+
112
+ def clear_break(self, filename, lineno):
113
+ msg = self.idb.clear_break(filename, lineno)
114
+ return msg
115
+
116
+ def clear_all_file_breaks(self, filename):
117
+ msg = self.idb.clear_all_file_breaks(filename)
118
+ return msg
119
+
120
+ #----------called by a FrameProxy----------
121
+
122
+ def frame_attr(self, fid, name):
123
+ frame = frametable[fid]
124
+ return getattr(frame, name)
125
+
126
+ def frame_globals(self, fid):
127
+ frame = frametable[fid]
128
+ dict = frame.f_globals
129
+ did = id(dict)
130
+ dicttable[did] = dict
131
+ return did
132
+
133
+ def frame_locals(self, fid):
134
+ frame = frametable[fid]
135
+ dict = frame.f_locals
136
+ did = id(dict)
137
+ dicttable[did] = dict
138
+ return did
139
+
140
+ def frame_code(self, fid):
141
+ frame = frametable[fid]
142
+ code = frame.f_code
143
+ cid = id(code)
144
+ codetable[cid] = code
145
+ return cid
146
+
147
+ #----------called by a CodeProxy----------
148
+
149
+ def code_name(self, cid):
150
+ code = codetable[cid]
151
+ return code.co_name
152
+
153
+ def code_filename(self, cid):
154
+ code = codetable[cid]
155
+ return code.co_filename
156
+
157
+ #----------called by a DictProxy----------
158
+
159
+ def dict_keys(self, did):
160
+ raise NotImplementedError("dict_keys not public or pickleable")
161
+ ## dict = dicttable[did]
162
+ ## return dict.keys()
163
+
164
+ ### Needed until dict_keys is type is finished and pickealable.
165
+ ### Will probably need to extend rpc.py:SocketIO._proxify at that time.
166
+ def dict_keys_list(self, did):
167
+ dict = dicttable[did]
168
+ return list(dict.keys())
169
+
170
+ def dict_item(self, did, key):
171
+ dict = dicttable[did]
172
+ value = dict[key]
173
+ value = reprlib.repr(value) ### can't pickle module 'builtins'
174
+ return value
175
+
176
+ #----------end class IdbAdapter----------
177
+
178
+
179
+ def start_debugger(rpchandler, gui_adap_oid):
180
+ """Start the debugger and its RPC link in the Python subprocess
181
+
182
+ Start the subprocess side of the split debugger and set up that side of the
183
+ RPC link by instantiating the GUIProxy, Idb debugger, and IdbAdapter
184
+ objects and linking them together. Register the IdbAdapter with the
185
+ RPCServer to handle RPC requests from the split debugger GUI via the
186
+ IdbProxy.
187
+
188
+ """
189
+ gui_proxy = GUIProxy(rpchandler, gui_adap_oid)
190
+ idb = debugger.Idb(gui_proxy)
191
+ idb_adap = IdbAdapter(idb)
192
+ rpchandler.register(idb_adap_oid, idb_adap)
193
+ return idb_adap_oid
194
+
195
+
196
+ #=======================================
197
+ #
198
+ # In the IDLE process:
199
+
200
+
201
+ class FrameProxy:
202
+
203
+ def __init__(self, conn, fid):
204
+ self._conn = conn
205
+ self._fid = fid
206
+ self._oid = "idb_adapter"
207
+ self._dictcache = {}
208
+
209
+ def __getattr__(self, name):
210
+ if name[:1] == "_":
211
+ raise AttributeError(name)
212
+ if name == "f_code":
213
+ return self._get_f_code()
214
+ if name == "f_globals":
215
+ return self._get_f_globals()
216
+ if name == "f_locals":
217
+ return self._get_f_locals()
218
+ return self._conn.remotecall(self._oid, "frame_attr",
219
+ (self._fid, name), {})
220
+
221
+ def _get_f_code(self):
222
+ cid = self._conn.remotecall(self._oid, "frame_code", (self._fid,), {})
223
+ return CodeProxy(self._conn, self._oid, cid)
224
+
225
+ def _get_f_globals(self):
226
+ did = self._conn.remotecall(self._oid, "frame_globals",
227
+ (self._fid,), {})
228
+ return self._get_dict_proxy(did)
229
+
230
+ def _get_f_locals(self):
231
+ did = self._conn.remotecall(self._oid, "frame_locals",
232
+ (self._fid,), {})
233
+ return self._get_dict_proxy(did)
234
+
235
+ def _get_dict_proxy(self, did):
236
+ if did in self._dictcache:
237
+ return self._dictcache[did]
238
+ dp = DictProxy(self._conn, self._oid, did)
239
+ self._dictcache[did] = dp
240
+ return dp
241
+
242
+
243
+ class CodeProxy:
244
+
245
+ def __init__(self, conn, oid, cid):
246
+ self._conn = conn
247
+ self._oid = oid
248
+ self._cid = cid
249
+
250
+ def __getattr__(self, name):
251
+ if name == "co_name":
252
+ return self._conn.remotecall(self._oid, "code_name",
253
+ (self._cid,), {})
254
+ if name == "co_filename":
255
+ return self._conn.remotecall(self._oid, "code_filename",
256
+ (self._cid,), {})
257
+
258
+
259
+ class DictProxy:
260
+
261
+ def __init__(self, conn, oid, did):
262
+ self._conn = conn
263
+ self._oid = oid
264
+ self._did = did
265
+
266
+ ## def keys(self):
267
+ ## return self._conn.remotecall(self._oid, "dict_keys", (self._did,), {})
268
+
269
+ # 'temporary' until dict_keys is a pickleable built-in type
270
+ def keys(self):
271
+ return self._conn.remotecall(self._oid,
272
+ "dict_keys_list", (self._did,), {})
273
+
274
+ def __getitem__(self, key):
275
+ return self._conn.remotecall(self._oid, "dict_item",
276
+ (self._did, key), {})
277
+
278
+ def __getattr__(self, name):
279
+ ##print("*** Failed DictProxy.__getattr__:", name)
280
+ raise AttributeError(name)
281
+
282
+
283
+ class GUIAdapter:
284
+
285
+ def __init__(self, conn, gui):
286
+ self.conn = conn
287
+ self.gui = gui
288
+
289
+ def interaction(self, message, fid, modified_info):
290
+ ##print("*** Interaction: (%s, %s, %s)" % (message, fid, modified_info))
291
+ frame = FrameProxy(self.conn, fid)
292
+ self.gui.interaction(message, frame, modified_info)
293
+
294
+
295
+ class IdbProxy:
296
+
297
+ def __init__(self, conn, shell, oid):
298
+ self.oid = oid
299
+ self.conn = conn
300
+ self.shell = shell
301
+
302
+ def call(self, methodname, /, *args, **kwargs):
303
+ ##print("*** IdbProxy.call %s %s %s" % (methodname, args, kwargs))
304
+ value = self.conn.remotecall(self.oid, methodname, args, kwargs)
305
+ ##print("*** IdbProxy.call %s returns %r" % (methodname, value))
306
+ return value
307
+
308
+ def run(self, cmd, locals):
309
+ # Ignores locals on purpose!
310
+ seq = self.conn.asyncqueue(self.oid, "run", (cmd,), {})
311
+ self.shell.interp.active_seq = seq
312
+
313
+ def get_stack(self, frame, tbid):
314
+ # passing frame and traceback IDs, not the objects themselves
315
+ stack, i = self.call("get_stack", frame._fid, tbid)
316
+ stack = [(FrameProxy(self.conn, fid), k) for fid, k in stack]
317
+ return stack, i
318
+
319
+ def set_continue(self):
320
+ self.call("set_continue")
321
+
322
+ def set_step(self):
323
+ self.call("set_step")
324
+
325
+ def set_next(self, frame):
326
+ self.call("set_next", frame._fid)
327
+
328
+ def set_return(self, frame):
329
+ self.call("set_return", frame._fid)
330
+
331
+ def set_quit(self):
332
+ self.call("set_quit")
333
+
334
+ def set_break(self, filename, lineno):
335
+ msg = self.call("set_break", filename, lineno)
336
+ return msg
337
+
338
+ def clear_break(self, filename, lineno):
339
+ msg = self.call("clear_break", filename, lineno)
340
+ return msg
341
+
342
+ def clear_all_file_breaks(self, filename):
343
+ msg = self.call("clear_all_file_breaks", filename)
344
+ return msg
345
+
346
+ def start_remote_debugger(rpcclt, pyshell):
347
+ """Start the subprocess debugger, initialize the debugger GUI and RPC link
348
+
349
+ Request the RPCServer start the Python subprocess debugger and link. Set
350
+ up the Idle side of the split debugger by instantiating the IdbProxy,
351
+ debugger GUI, and debugger GUIAdapter objects and linking them together.
352
+
353
+ Register the GUIAdapter with the RPCClient to handle debugger GUI
354
+ interaction requests coming from the subprocess debugger via the GUIProxy.
355
+
356
+ The IdbAdapter will pass execution and environment requests coming from the
357
+ Idle debugger GUI to the subprocess debugger via the IdbProxy.
358
+
359
+ """
360
+ global idb_adap_oid
361
+
362
+ idb_adap_oid = rpcclt.remotecall("exec", "start_the_debugger",\
363
+ (gui_adap_oid,), {})
364
+ idb_proxy = IdbProxy(rpcclt, pyshell, idb_adap_oid)
365
+ gui = debugger.Debugger(pyshell, idb_proxy)
366
+ gui_adap = GUIAdapter(rpcclt, gui)
367
+ rpcclt.register(gui_adap_oid, gui_adap)
368
+ return gui
369
+
370
+ def close_remote_debugger(rpcclt):
371
+ """Shut down subprocess debugger and Idle side of debugger RPC link
372
+
373
+ Request that the RPCServer shut down the subprocess debugger and link.
374
+ Unregister the GUIAdapter, which will cause a GC on the Idle process
375
+ debugger and RPC link objects. (The second reference to the debugger GUI
376
+ is deleted in pyshell.close_remote_debugger().)
377
+
378
+ """
379
+ close_subprocess_debugger(rpcclt)
380
+ rpcclt.unregister(gui_adap_oid)
381
+
382
+ def close_subprocess_debugger(rpcclt):
383
+ rpcclt.remotecall("exec", "stop_the_debugger", (idb_adap_oid,), {})
384
+
385
+ def restart_subprocess_debugger(rpcclt):
386
+ idb_adap_oid_ret = rpcclt.remotecall("exec", "start_the_debugger",\
387
+ (gui_adap_oid,), {})
388
+ assert idb_adap_oid_ret == idb_adap_oid, 'Idb restarted with different oid'
389
+
390
+
391
+ if __name__ == "__main__":
392
+ from unittest import main
393
+ main('idlelib.idle_test.test_debugger_r', verbosity=2, exit=False)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/debugobj.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # XXX TO DO:
2
+ # - popup menu
3
+ # - support partial or total redisplay
4
+ # - more doc strings
5
+ # - tooltips
6
+
7
+ # object browser
8
+
9
+ # XXX TO DO:
10
+ # - for classes/modules, add "open source" to object browser
11
+ from reprlib import Repr
12
+
13
+ from idlelib.tree import TreeItem, TreeNode, ScrolledCanvas
14
+
15
+ myrepr = Repr()
16
+ myrepr.maxstring = 100
17
+ myrepr.maxother = 100
18
+
19
+ class ObjectTreeItem(TreeItem):
20
+ def __init__(self, labeltext, object, setfunction=None):
21
+ self.labeltext = labeltext
22
+ self.object = object
23
+ self.setfunction = setfunction
24
+ def GetLabelText(self):
25
+ return self.labeltext
26
+ def GetText(self):
27
+ return myrepr.repr(self.object)
28
+ def GetIconName(self):
29
+ if not self.IsExpandable():
30
+ return "python"
31
+ def IsEditable(self):
32
+ return self.setfunction is not None
33
+ def SetText(self, text):
34
+ try:
35
+ value = eval(text)
36
+ self.setfunction(value)
37
+ except:
38
+ pass
39
+ else:
40
+ self.object = value
41
+ def IsExpandable(self):
42
+ return not not dir(self.object)
43
+ def GetSubList(self):
44
+ keys = dir(self.object)
45
+ sublist = []
46
+ for key in keys:
47
+ try:
48
+ value = getattr(self.object, key)
49
+ except AttributeError:
50
+ continue
51
+ item = make_objecttreeitem(
52
+ str(key) + " =",
53
+ value,
54
+ lambda value, key=key, object=self.object:
55
+ setattr(object, key, value))
56
+ sublist.append(item)
57
+ return sublist
58
+
59
+ class ClassTreeItem(ObjectTreeItem):
60
+ def IsExpandable(self):
61
+ return True
62
+ def GetSubList(self):
63
+ sublist = ObjectTreeItem.GetSubList(self)
64
+ if len(self.object.__bases__) == 1:
65
+ item = make_objecttreeitem("__bases__[0] =",
66
+ self.object.__bases__[0])
67
+ else:
68
+ item = make_objecttreeitem("__bases__ =", self.object.__bases__)
69
+ sublist.insert(0, item)
70
+ return sublist
71
+
72
+ class AtomicObjectTreeItem(ObjectTreeItem):
73
+ def IsExpandable(self):
74
+ return False
75
+
76
+ class SequenceTreeItem(ObjectTreeItem):
77
+ def IsExpandable(self):
78
+ return len(self.object) > 0
79
+ def keys(self):
80
+ return range(len(self.object))
81
+ def GetSubList(self):
82
+ sublist = []
83
+ for key in self.keys():
84
+ try:
85
+ value = self.object[key]
86
+ except KeyError:
87
+ continue
88
+ def setfunction(value, key=key, object=self.object):
89
+ object[key] = value
90
+ item = make_objecttreeitem("%r:" % (key,), value, setfunction)
91
+ sublist.append(item)
92
+ return sublist
93
+
94
+ class DictTreeItem(SequenceTreeItem):
95
+ def keys(self):
96
+ keys = list(self.object.keys())
97
+ try:
98
+ keys.sort()
99
+ except:
100
+ pass
101
+ return keys
102
+
103
+ dispatch = {
104
+ int: AtomicObjectTreeItem,
105
+ float: AtomicObjectTreeItem,
106
+ str: AtomicObjectTreeItem,
107
+ tuple: SequenceTreeItem,
108
+ list: SequenceTreeItem,
109
+ dict: DictTreeItem,
110
+ type: ClassTreeItem,
111
+ }
112
+
113
+ def make_objecttreeitem(labeltext, object, setfunction=None):
114
+ t = type(object)
115
+ if t in dispatch:
116
+ c = dispatch[t]
117
+ else:
118
+ c = ObjectTreeItem
119
+ return c(labeltext, object, setfunction)
120
+
121
+
122
+ def _object_browser(parent): # htest #
123
+ import sys
124
+ from tkinter import Toplevel
125
+ top = Toplevel(parent)
126
+ top.title("Test debug object browser")
127
+ x, y = map(int, parent.geometry().split('+')[1:])
128
+ top.geometry("+%d+%d" % (x + 100, y + 175))
129
+ top.configure(bd=0, bg="yellow")
130
+ top.focus_set()
131
+ sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1)
132
+ sc.frame.pack(expand=1, fill="both")
133
+ item = make_objecttreeitem("sys", sys)
134
+ node = TreeNode(sc.canvas, None, item)
135
+ node.update()
136
+
137
+ if __name__ == '__main__':
138
+ from unittest import main
139
+ main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False)
140
+
141
+ from idlelib.idle_test.htest import run
142
+ run(_object_browser)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/debugobj_r.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from idlelib import rpc
2
+
3
+ def remote_object_tree_item(item):
4
+ wrapper = WrappedObjectTreeItem(item)
5
+ oid = id(wrapper)
6
+ rpc.objecttable[oid] = wrapper
7
+ return oid
8
+
9
+ class WrappedObjectTreeItem:
10
+ # Lives in PYTHON subprocess
11
+
12
+ def __init__(self, item):
13
+ self.__item = item
14
+
15
+ def __getattr__(self, name):
16
+ value = getattr(self.__item, name)
17
+ return value
18
+
19
+ def _GetSubList(self):
20
+ sub_list = self.__item._GetSubList()
21
+ return list(map(remote_object_tree_item, sub_list))
22
+
23
+ class StubObjectTreeItem:
24
+ # Lives in IDLE process
25
+
26
+ def __init__(self, sockio, oid):
27
+ self.sockio = sockio
28
+ self.oid = oid
29
+
30
+ def __getattr__(self, name):
31
+ value = rpc.MethodProxy(self.sockio, self.oid, name)
32
+ return value
33
+
34
+ def _GetSubList(self):
35
+ sub_list = self.sockio.remotecall(self.oid, "_GetSubList", (), {})
36
+ return [StubObjectTreeItem(self.sockio, oid) for oid in sub_list]
37
+
38
+
39
+ if __name__ == '__main__':
40
+ from unittest import main
41
+ main('idlelib.idle_test.test_debugobj_r', verbosity=2)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/delegator.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class Delegator:
2
+
3
+ def __init__(self, delegate=None):
4
+ self.delegate = delegate
5
+ self.__cache = set()
6
+ # Cache is used to only remove added attributes
7
+ # when changing the delegate.
8
+
9
+ def __getattr__(self, name):
10
+ attr = getattr(self.delegate, name) # May raise AttributeError
11
+ setattr(self, name, attr)
12
+ self.__cache.add(name)
13
+ return attr
14
+
15
+ def resetcache(self):
16
+ "Removes added attributes while leaving original attributes."
17
+ # Function is really about resetting delegator dict
18
+ # to original state. Cache is just a means
19
+ for key in self.__cache:
20
+ try:
21
+ delattr(self, key)
22
+ except AttributeError:
23
+ pass
24
+ self.__cache.clear()
25
+
26
+ def setdelegate(self, delegate):
27
+ "Reset attributes and change delegate."
28
+ self.resetcache()
29
+ self.delegate = delegate
30
+
31
+ if __name__ == '__main__':
32
+ from unittest import main
33
+ main('idlelib.idle_test.test_delegator', verbosity=2)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/editor.py ADDED
@@ -0,0 +1,1672 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib.abc
2
+ import importlib.util
3
+ import os
4
+ import platform
5
+ import re
6
+ import string
7
+ import sys
8
+ import tokenize
9
+ import traceback
10
+ import webbrowser
11
+
12
+ from tkinter import *
13
+ from tkinter.font import Font
14
+ from tkinter.ttk import Scrollbar
15
+ from tkinter import simpledialog
16
+ from tkinter import messagebox
17
+
18
+ from idlelib.config import idleConf
19
+ from idlelib import configdialog
20
+ from idlelib import grep
21
+ from idlelib import help
22
+ from idlelib import help_about
23
+ from idlelib import macosx
24
+ from idlelib.multicall import MultiCallCreator
25
+ from idlelib import pyparse
26
+ from idlelib import query
27
+ from idlelib import replace
28
+ from idlelib import search
29
+ from idlelib.tree import wheel_event
30
+ from idlelib import window
31
+
32
+ # The default tab setting for a Text widget, in average-width characters.
33
+ TK_TABWIDTH_DEFAULT = 8
34
+ _py_version = ' (%s)' % platform.python_version()
35
+ darwin = sys.platform == 'darwin'
36
+
37
+ def _sphinx_version():
38
+ "Format sys.version_info to produce the Sphinx version string used to install the chm docs"
39
+ major, minor, micro, level, serial = sys.version_info
40
+ release = '%s%s' % (major, minor)
41
+ release += '%s' % (micro,)
42
+ if level == 'candidate':
43
+ release += 'rc%s' % (serial,)
44
+ elif level != 'final':
45
+ release += '%s%s' % (level[0], serial)
46
+ return release
47
+
48
+
49
+ class EditorWindow:
50
+ from idlelib.percolator import Percolator
51
+ from idlelib.colorizer import ColorDelegator, color_config
52
+ from idlelib.undo import UndoDelegator
53
+ from idlelib.iomenu import IOBinding, encoding
54
+ from idlelib import mainmenu
55
+ from idlelib.statusbar import MultiStatusBar
56
+ from idlelib.autocomplete import AutoComplete
57
+ from idlelib.autoexpand import AutoExpand
58
+ from idlelib.calltip import Calltip
59
+ from idlelib.codecontext import CodeContext
60
+ from idlelib.sidebar import LineNumbers
61
+ from idlelib.format import FormatParagraph, FormatRegion, Indents, Rstrip
62
+ from idlelib.parenmatch import ParenMatch
63
+ from idlelib.squeezer import Squeezer
64
+ from idlelib.zoomheight import ZoomHeight
65
+
66
+ filesystemencoding = sys.getfilesystemencoding() # for file names
67
+ help_url = None
68
+
69
+ allow_code_context = True
70
+ allow_line_numbers = True
71
+
72
+ def __init__(self, flist=None, filename=None, key=None, root=None):
73
+ # Delay import: runscript imports pyshell imports EditorWindow.
74
+ from idlelib.runscript import ScriptBinding
75
+
76
+ if EditorWindow.help_url is None:
77
+ dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html')
78
+ if sys.platform.count('linux'):
79
+ # look for html docs in a couple of standard places
80
+ pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3]
81
+ if os.path.isdir('/var/www/html/python/'): # "python2" rpm
82
+ dochome = '/var/www/html/python/index.html'
83
+ else:
84
+ basepath = '/usr/share/doc/' # standard location
85
+ dochome = os.path.join(basepath, pyver,
86
+ 'Doc', 'index.html')
87
+ elif sys.platform[:3] == 'win':
88
+ chmfile = os.path.join(sys.base_prefix, 'Doc',
89
+ 'Python%s.chm' % _sphinx_version())
90
+ if os.path.isfile(chmfile):
91
+ dochome = chmfile
92
+ elif sys.platform == 'darwin':
93
+ # documentation may be stored inside a python framework
94
+ dochome = os.path.join(sys.base_prefix,
95
+ 'Resources/English.lproj/Documentation/index.html')
96
+ dochome = os.path.normpath(dochome)
97
+ if os.path.isfile(dochome):
98
+ EditorWindow.help_url = dochome
99
+ if sys.platform == 'darwin':
100
+ # Safari requires real file:-URLs
101
+ EditorWindow.help_url = 'file://' + EditorWindow.help_url
102
+ else:
103
+ EditorWindow.help_url = ("https://docs.python.org/%d.%d/"
104
+ % sys.version_info[:2])
105
+ self.flist = flist
106
+ root = root or flist.root
107
+ self.root = root
108
+ self.menubar = Menu(root)
109
+ self.top = top = window.ListedToplevel(root, menu=self.menubar)
110
+ if flist:
111
+ self.tkinter_vars = flist.vars
112
+ #self.top.instance_dict makes flist.inversedict available to
113
+ #configdialog.py so it can access all EditorWindow instances
114
+ self.top.instance_dict = flist.inversedict
115
+ else:
116
+ self.tkinter_vars = {} # keys: Tkinter event names
117
+ # values: Tkinter variable instances
118
+ self.top.instance_dict = {}
119
+ self.recent_files_path = idleConf.userdir and os.path.join(
120
+ idleConf.userdir, 'recent-files.lst')
121
+
122
+ self.prompt_last_line = '' # Override in PyShell
123
+ self.text_frame = text_frame = Frame(top)
124
+ self.vbar = vbar = Scrollbar(text_frame, name='vbar')
125
+ width = idleConf.GetOption('main', 'EditorWindow', 'width', type='int')
126
+ text_options = {
127
+ 'name': 'text',
128
+ 'padx': 5,
129
+ 'wrap': 'none',
130
+ 'highlightthickness': 0,
131
+ 'width': width,
132
+ 'tabstyle': 'wordprocessor', # new in 8.5
133
+ 'height': idleConf.GetOption(
134
+ 'main', 'EditorWindow', 'height', type='int'),
135
+ }
136
+ self.text = text = MultiCallCreator(Text)(text_frame, **text_options)
137
+ self.top.focused_widget = self.text
138
+
139
+ self.createmenubar()
140
+ self.apply_bindings()
141
+
142
+ self.top.protocol("WM_DELETE_WINDOW", self.close)
143
+ self.top.bind("<<close-window>>", self.close_event)
144
+ if macosx.isAquaTk():
145
+ # Command-W on editor windows doesn't work without this.
146
+ text.bind('<<close-window>>', self.close_event)
147
+ # Some OS X systems have only one mouse button, so use
148
+ # control-click for popup context menus there. For two
149
+ # buttons, AquaTk defines <2> as the right button, not <3>.
150
+ text.bind("<Control-Button-1>",self.right_menu_event)
151
+ text.bind("<2>", self.right_menu_event)
152
+ else:
153
+ # Elsewhere, use right-click for popup menus.
154
+ text.bind("<3>",self.right_menu_event)
155
+
156
+ text.bind('<MouseWheel>', wheel_event)
157
+ text.bind('<Button-4>', wheel_event)
158
+ text.bind('<Button-5>', wheel_event)
159
+ text.bind('<Configure>', self.handle_winconfig)
160
+ text.bind("<<cut>>", self.cut)
161
+ text.bind("<<copy>>", self.copy)
162
+ text.bind("<<paste>>", self.paste)
163
+ text.bind("<<center-insert>>", self.center_insert_event)
164
+ text.bind("<<help>>", self.help_dialog)
165
+ text.bind("<<python-docs>>", self.python_docs)
166
+ text.bind("<<about-idle>>", self.about_dialog)
167
+ text.bind("<<open-config-dialog>>", self.config_dialog)
168
+ text.bind("<<open-module>>", self.open_module_event)
169
+ text.bind("<<do-nothing>>", lambda event: "break")
170
+ text.bind("<<select-all>>", self.select_all)
171
+ text.bind("<<remove-selection>>", self.remove_selection)
172
+ text.bind("<<find>>", self.find_event)
173
+ text.bind("<<find-again>>", self.find_again_event)
174
+ text.bind("<<find-in-files>>", self.find_in_files_event)
175
+ text.bind("<<find-selection>>", self.find_selection_event)
176
+ text.bind("<<replace>>", self.replace_event)
177
+ text.bind("<<goto-line>>", self.goto_line_event)
178
+ text.bind("<<smart-backspace>>",self.smart_backspace_event)
179
+ text.bind("<<newline-and-indent>>",self.newline_and_indent_event)
180
+ text.bind("<<smart-indent>>",self.smart_indent_event)
181
+ self.fregion = fregion = self.FormatRegion(self)
182
+ # self.fregion used in smart_indent_event to access indent_region.
183
+ text.bind("<<indent-region>>", fregion.indent_region_event)
184
+ text.bind("<<dedent-region>>", fregion.dedent_region_event)
185
+ text.bind("<<comment-region>>", fregion.comment_region_event)
186
+ text.bind("<<uncomment-region>>", fregion.uncomment_region_event)
187
+ text.bind("<<tabify-region>>", fregion.tabify_region_event)
188
+ text.bind("<<untabify-region>>", fregion.untabify_region_event)
189
+ indents = self.Indents(self)
190
+ text.bind("<<toggle-tabs>>", indents.toggle_tabs_event)
191
+ text.bind("<<change-indentwidth>>", indents.change_indentwidth_event)
192
+ text.bind("<Left>", self.move_at_edge_if_selection(0))
193
+ text.bind("<Right>", self.move_at_edge_if_selection(1))
194
+ text.bind("<<del-word-left>>", self.del_word_left)
195
+ text.bind("<<del-word-right>>", self.del_word_right)
196
+ text.bind("<<beginning-of-line>>", self.home_callback)
197
+
198
+ if flist:
199
+ flist.inversedict[self] = key
200
+ if key:
201
+ flist.dict[key] = self
202
+ text.bind("<<open-new-window>>", self.new_callback)
203
+ text.bind("<<close-all-windows>>", self.flist.close_all_callback)
204
+ text.bind("<<open-class-browser>>", self.open_module_browser)
205
+ text.bind("<<open-path-browser>>", self.open_path_browser)
206
+ text.bind("<<open-turtle-demo>>", self.open_turtle_demo)
207
+
208
+ self.set_status_bar()
209
+ text_frame.pack(side=LEFT, fill=BOTH, expand=1)
210
+ text_frame.rowconfigure(1, weight=1)
211
+ text_frame.columnconfigure(1, weight=1)
212
+ vbar['command'] = self.handle_yview
213
+ vbar.grid(row=1, column=2, sticky=NSEW)
214
+ text['yscrollcommand'] = vbar.set
215
+ text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow')
216
+ text.grid(row=1, column=1, sticky=NSEW)
217
+ text.focus_set()
218
+ self.set_width()
219
+
220
+ # usetabs true -> literal tab characters are used by indent and
221
+ # dedent cmds, possibly mixed with spaces if
222
+ # indentwidth is not a multiple of tabwidth,
223
+ # which will cause Tabnanny to nag!
224
+ # false -> tab characters are converted to spaces by indent
225
+ # and dedent cmds, and ditto TAB keystrokes
226
+ # Although use-spaces=0 can be configured manually in config-main.def,
227
+ # configuration of tabs v. spaces is not supported in the configuration
228
+ # dialog. IDLE promotes the preferred Python indentation: use spaces!
229
+ usespaces = idleConf.GetOption('main', 'Indent',
230
+ 'use-spaces', type='bool')
231
+ self.usetabs = not usespaces
232
+
233
+ # tabwidth is the display width of a literal tab character.
234
+ # CAUTION: telling Tk to use anything other than its default
235
+ # tab setting causes it to use an entirely different tabbing algorithm,
236
+ # treating tab stops as fixed distances from the left margin.
237
+ # Nobody expects this, so for now tabwidth should never be changed.
238
+ self.tabwidth = 8 # must remain 8 until Tk is fixed.
239
+
240
+ # indentwidth is the number of screen characters per indent level.
241
+ # The recommended Python indentation is four spaces.
242
+ self.indentwidth = self.tabwidth
243
+ self.set_notabs_indentwidth()
244
+
245
+ # Store the current value of the insertofftime now so we can restore
246
+ # it if needed.
247
+ if not hasattr(idleConf, 'blink_off_time'):
248
+ idleConf.blink_off_time = self.text['insertofftime']
249
+ self.update_cursor_blink()
250
+
251
+ # When searching backwards for a reliable place to begin parsing,
252
+ # first start num_context_lines[0] lines back, then
253
+ # num_context_lines[1] lines back if that didn't work, and so on.
254
+ # The last value should be huge (larger than the # of lines in a
255
+ # conceivable file).
256
+ # Making the initial values larger slows things down more often.
257
+ self.num_context_lines = 50, 500, 5000000
258
+ self.per = per = self.Percolator(text)
259
+ self.undo = undo = self.UndoDelegator()
260
+ per.insertfilter(undo)
261
+ text.undo_block_start = undo.undo_block_start
262
+ text.undo_block_stop = undo.undo_block_stop
263
+ undo.set_saved_change_hook(self.saved_change_hook)
264
+ # IOBinding implements file I/O and printing functionality
265
+ self.io = io = self.IOBinding(self)
266
+ io.set_filename_change_hook(self.filename_change_hook)
267
+ self.good_load = False
268
+ self.set_indentation_params(False)
269
+ self.color = None # initialized below in self.ResetColorizer
270
+ self.code_context = None # optionally initialized later below
271
+ self.line_numbers = None # optionally initialized later below
272
+ if filename:
273
+ if os.path.exists(filename) and not os.path.isdir(filename):
274
+ if io.loadfile(filename):
275
+ self.good_load = True
276
+ is_py_src = self.ispythonsource(filename)
277
+ self.set_indentation_params(is_py_src)
278
+ else:
279
+ io.set_filename(filename)
280
+ self.good_load = True
281
+
282
+ self.ResetColorizer()
283
+ self.saved_change_hook()
284
+ self.update_recent_files_list()
285
+ self.load_extensions()
286
+ menu = self.menudict.get('window')
287
+ if menu:
288
+ end = menu.index("end")
289
+ if end is None:
290
+ end = -1
291
+ if end >= 0:
292
+ menu.add_separator()
293
+ end = end + 1
294
+ self.wmenu_end = end
295
+ window.register_callback(self.postwindowsmenu)
296
+
297
+ # Some abstractions so IDLE extensions are cross-IDE
298
+ self.askinteger = simpledialog.askinteger
299
+ self.askyesno = messagebox.askyesno
300
+ self.showerror = messagebox.showerror
301
+
302
+ # Add pseudoevents for former extension fixed keys.
303
+ # (This probably needs to be done once in the process.)
304
+ text.event_add('<<autocomplete>>', '<Key-Tab>')
305
+ text.event_add('<<try-open-completions>>', '<KeyRelease-period>',
306
+ '<KeyRelease-slash>', '<KeyRelease-backslash>')
307
+ text.event_add('<<try-open-calltip>>', '<KeyRelease-parenleft>')
308
+ text.event_add('<<refresh-calltip>>', '<KeyRelease-parenright>')
309
+ text.event_add('<<paren-closed>>', '<KeyRelease-parenright>',
310
+ '<KeyRelease-bracketright>', '<KeyRelease-braceright>')
311
+
312
+ # Former extension bindings depends on frame.text being packed
313
+ # (called from self.ResetColorizer()).
314
+ autocomplete = self.AutoComplete(self)
315
+ text.bind("<<autocomplete>>", autocomplete.autocomplete_event)
316
+ text.bind("<<try-open-completions>>",
317
+ autocomplete.try_open_completions_event)
318
+ text.bind("<<force-open-completions>>",
319
+ autocomplete.force_open_completions_event)
320
+ text.bind("<<expand-word>>", self.AutoExpand(self).expand_word_event)
321
+ text.bind("<<format-paragraph>>",
322
+ self.FormatParagraph(self).format_paragraph_event)
323
+ parenmatch = self.ParenMatch(self)
324
+ text.bind("<<flash-paren>>", parenmatch.flash_paren_event)
325
+ text.bind("<<paren-closed>>", parenmatch.paren_closed_event)
326
+ scriptbinding = ScriptBinding(self)
327
+ text.bind("<<check-module>>", scriptbinding.check_module_event)
328
+ text.bind("<<run-module>>", scriptbinding.run_module_event)
329
+ text.bind("<<run-custom>>", scriptbinding.run_custom_event)
330
+ text.bind("<<do-rstrip>>", self.Rstrip(self).do_rstrip)
331
+ self.ctip = ctip = self.Calltip(self)
332
+ text.bind("<<try-open-calltip>>", ctip.try_open_calltip_event)
333
+ #refresh-calltip must come after paren-closed to work right
334
+ text.bind("<<refresh-calltip>>", ctip.refresh_calltip_event)
335
+ text.bind("<<force-open-calltip>>", ctip.force_open_calltip_event)
336
+ text.bind("<<zoom-height>>", self.ZoomHeight(self).zoom_height_event)
337
+ if self.allow_code_context:
338
+ self.code_context = self.CodeContext(self)
339
+ text.bind("<<toggle-code-context>>",
340
+ self.code_context.toggle_code_context_event)
341
+ else:
342
+ self.update_menu_state('options', '*ode*ontext', 'disabled')
343
+ if self.allow_line_numbers:
344
+ self.line_numbers = self.LineNumbers(self)
345
+ if idleConf.GetOption('main', 'EditorWindow',
346
+ 'line-numbers-default', type='bool'):
347
+ self.toggle_line_numbers_event()
348
+ text.bind("<<toggle-line-numbers>>", self.toggle_line_numbers_event)
349
+ else:
350
+ self.update_menu_state('options', '*ine*umbers', 'disabled')
351
+
352
+ def handle_winconfig(self, event=None):
353
+ self.set_width()
354
+
355
+ def set_width(self):
356
+ text = self.text
357
+ inner_padding = sum(map(text.tk.getint, [text.cget('border'),
358
+ text.cget('padx')]))
359
+ pixel_width = text.winfo_width() - 2 * inner_padding
360
+
361
+ # Divide the width of the Text widget by the font width,
362
+ # which is taken to be the width of '0' (zero).
363
+ # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21
364
+ zero_char_width = \
365
+ Font(text, font=text.cget('font')).measure('0')
366
+ self.width = pixel_width // zero_char_width
367
+
368
+ def new_callback(self, event):
369
+ dirname, basename = self.io.defaultfilename()
370
+ self.flist.new(dirname)
371
+ return "break"
372
+
373
+ def home_callback(self, event):
374
+ if (event.state & 4) != 0 and event.keysym == "Home":
375
+ # state&4==Control. If <Control-Home>, use the Tk binding.
376
+ return None
377
+ if self.text.index("iomark") and \
378
+ self.text.compare("iomark", "<=", "insert lineend") and \
379
+ self.text.compare("insert linestart", "<=", "iomark"):
380
+ # In Shell on input line, go to just after prompt
381
+ insertpt = int(self.text.index("iomark").split(".")[1])
382
+ else:
383
+ line = self.text.get("insert linestart", "insert lineend")
384
+ for insertpt in range(len(line)):
385
+ if line[insertpt] not in (' ','\t'):
386
+ break
387
+ else:
388
+ insertpt=len(line)
389
+ lineat = int(self.text.index("insert").split('.')[1])
390
+ if insertpt == lineat:
391
+ insertpt = 0
392
+ dest = "insert linestart+"+str(insertpt)+"c"
393
+ if (event.state&1) == 0:
394
+ # shift was not pressed
395
+ self.text.tag_remove("sel", "1.0", "end")
396
+ else:
397
+ if not self.text.index("sel.first"):
398
+ # there was no previous selection
399
+ self.text.mark_set("my_anchor", "insert")
400
+ else:
401
+ if self.text.compare(self.text.index("sel.first"), "<",
402
+ self.text.index("insert")):
403
+ self.text.mark_set("my_anchor", "sel.first") # extend back
404
+ else:
405
+ self.text.mark_set("my_anchor", "sel.last") # extend forward
406
+ first = self.text.index(dest)
407
+ last = self.text.index("my_anchor")
408
+ if self.text.compare(first,">",last):
409
+ first,last = last,first
410
+ self.text.tag_remove("sel", "1.0", "end")
411
+ self.text.tag_add("sel", first, last)
412
+ self.text.mark_set("insert", dest)
413
+ self.text.see("insert")
414
+ return "break"
415
+
416
+ def set_status_bar(self):
417
+ self.status_bar = self.MultiStatusBar(self.top)
418
+ sep = Frame(self.top, height=1, borderwidth=1, background='grey75')
419
+ if sys.platform == "darwin":
420
+ # Insert some padding to avoid obscuring some of the statusbar
421
+ # by the resize widget.
422
+ self.status_bar.set_label('_padding1', ' ', side=RIGHT)
423
+ self.status_bar.set_label('column', 'Col: ?', side=RIGHT)
424
+ self.status_bar.set_label('line', 'Ln: ?', side=RIGHT)
425
+ self.status_bar.pack(side=BOTTOM, fill=X)
426
+ sep.pack(side=BOTTOM, fill=X)
427
+ self.text.bind("<<set-line-and-column>>", self.set_line_and_column)
428
+ self.text.event_add("<<set-line-and-column>>",
429
+ "<KeyRelease>", "<ButtonRelease>")
430
+ self.text.after_idle(self.set_line_and_column)
431
+
432
+ def set_line_and_column(self, event=None):
433
+ line, column = self.text.index(INSERT).split('.')
434
+ self.status_bar.set_label('column', 'Col: %s' % column)
435
+ self.status_bar.set_label('line', 'Ln: %s' % line)
436
+
437
+ menu_specs = [
438
+ ("file", "_File"),
439
+ ("edit", "_Edit"),
440
+ ("format", "F_ormat"),
441
+ ("run", "_Run"),
442
+ ("options", "_Options"),
443
+ ("window", "_Window"),
444
+ ("help", "_Help"),
445
+ ]
446
+
447
+
448
+ def createmenubar(self):
449
+ mbar = self.menubar
450
+ self.menudict = menudict = {}
451
+ for name, label in self.menu_specs:
452
+ underline, label = prepstr(label)
453
+ postcommand = getattr(self, f'{name}_menu_postcommand', None)
454
+ menudict[name] = menu = Menu(mbar, name=name, tearoff=0,
455
+ postcommand=postcommand)
456
+ mbar.add_cascade(label=label, menu=menu, underline=underline)
457
+ if macosx.isCarbonTk():
458
+ # Insert the application menu
459
+ menudict['application'] = menu = Menu(mbar, name='apple',
460
+ tearoff=0)
461
+ mbar.add_cascade(label='IDLE', menu=menu)
462
+ self.fill_menus()
463
+ self.recent_files_menu = Menu(self.menubar, tearoff=0)
464
+ self.menudict['file'].insert_cascade(3, label='Recent Files',
465
+ underline=0,
466
+ menu=self.recent_files_menu)
467
+ self.base_helpmenu_length = self.menudict['help'].index(END)
468
+ self.reset_help_menu_entries()
469
+
470
+ def postwindowsmenu(self):
471
+ # Only called when Window menu exists
472
+ menu = self.menudict['window']
473
+ end = menu.index("end")
474
+ if end is None:
475
+ end = -1
476
+ if end > self.wmenu_end:
477
+ menu.delete(self.wmenu_end+1, end)
478
+ window.add_windows_to_menu(menu)
479
+
480
+ def update_menu_label(self, menu, index, label):
481
+ "Update label for menu item at index."
482
+ menuitem = self.menudict[menu]
483
+ menuitem.entryconfig(index, label=label)
484
+
485
+ def update_menu_state(self, menu, index, state):
486
+ "Update state for menu item at index."
487
+ menuitem = self.menudict[menu]
488
+ menuitem.entryconfig(index, state=state)
489
+
490
+ def handle_yview(self, event, *args):
491
+ "Handle scrollbar."
492
+ if event == 'moveto':
493
+ fraction = float(args[0])
494
+ lines = (round(self.getlineno('end') * fraction) -
495
+ self.getlineno('@0,0'))
496
+ event = 'scroll'
497
+ args = (lines, 'units')
498
+ self.text.yview(event, *args)
499
+ return 'break'
500
+
501
+ rmenu = None
502
+
503
+ def right_menu_event(self, event):
504
+ text = self.text
505
+ newdex = text.index(f'@{event.x},{event.y}')
506
+ try:
507
+ in_selection = (text.compare('sel.first', '<=', newdex) and
508
+ text.compare(newdex, '<=', 'sel.last'))
509
+ except TclError:
510
+ in_selection = False
511
+ if not in_selection:
512
+ text.tag_remove("sel", "1.0", "end")
513
+ text.mark_set("insert", newdex)
514
+ if not self.rmenu:
515
+ self.make_rmenu()
516
+ rmenu = self.rmenu
517
+ self.event = event
518
+ iswin = sys.platform[:3] == 'win'
519
+ if iswin:
520
+ text.config(cursor="arrow")
521
+
522
+ for item in self.rmenu_specs:
523
+ try:
524
+ label, eventname, verify_state = item
525
+ except ValueError: # see issue1207589
526
+ continue
527
+
528
+ if verify_state is None:
529
+ continue
530
+ state = getattr(self, verify_state)()
531
+ rmenu.entryconfigure(label, state=state)
532
+
533
+ rmenu.tk_popup(event.x_root, event.y_root)
534
+ if iswin:
535
+ self.text.config(cursor="ibeam")
536
+ return "break"
537
+
538
+ rmenu_specs = [
539
+ # ("Label", "<<virtual-event>>", "statefuncname"), ...
540
+ ("Close", "<<close-window>>", None), # Example
541
+ ]
542
+
543
+ def make_rmenu(self):
544
+ rmenu = Menu(self.text, tearoff=0)
545
+ for item in self.rmenu_specs:
546
+ label, eventname = item[0], item[1]
547
+ if label is not None:
548
+ def command(text=self.text, eventname=eventname):
549
+ text.event_generate(eventname)
550
+ rmenu.add_command(label=label, command=command)
551
+ else:
552
+ rmenu.add_separator()
553
+ self.rmenu = rmenu
554
+
555
+ def rmenu_check_cut(self):
556
+ return self.rmenu_check_copy()
557
+
558
+ def rmenu_check_copy(self):
559
+ try:
560
+ indx = self.text.index('sel.first')
561
+ except TclError:
562
+ return 'disabled'
563
+ else:
564
+ return 'normal' if indx else 'disabled'
565
+
566
+ def rmenu_check_paste(self):
567
+ try:
568
+ self.text.tk.call('tk::GetSelection', self.text, 'CLIPBOARD')
569
+ except TclError:
570
+ return 'disabled'
571
+ else:
572
+ return 'normal'
573
+
574
+ def about_dialog(self, event=None):
575
+ "Handle Help 'About IDLE' event."
576
+ # Synchronize with macosx.overrideRootMenu.about_dialog.
577
+ help_about.AboutDialog(self.top)
578
+ return "break"
579
+
580
+ def config_dialog(self, event=None):
581
+ "Handle Options 'Configure IDLE' event."
582
+ # Synchronize with macosx.overrideRootMenu.config_dialog.
583
+ configdialog.ConfigDialog(self.top,'Settings')
584
+ return "break"
585
+
586
+ def help_dialog(self, event=None):
587
+ "Handle Help 'IDLE Help' event."
588
+ # Synchronize with macosx.overrideRootMenu.help_dialog.
589
+ if self.root:
590
+ parent = self.root
591
+ else:
592
+ parent = self.top
593
+ help.show_idlehelp(parent)
594
+ return "break"
595
+
596
+ def python_docs(self, event=None):
597
+ if sys.platform[:3] == 'win':
598
+ try:
599
+ os.startfile(self.help_url)
600
+ except OSError as why:
601
+ messagebox.showerror(title='Document Start Failure',
602
+ message=str(why), parent=self.text)
603
+ else:
604
+ webbrowser.open(self.help_url)
605
+ return "break"
606
+
607
+ def cut(self,event):
608
+ self.text.event_generate("<<Cut>>")
609
+ return "break"
610
+
611
+ def copy(self,event):
612
+ if not self.text.tag_ranges("sel"):
613
+ # There is no selection, so do nothing and maybe interrupt.
614
+ return None
615
+ self.text.event_generate("<<Copy>>")
616
+ return "break"
617
+
618
+ def paste(self,event):
619
+ self.text.event_generate("<<Paste>>")
620
+ self.text.see("insert")
621
+ return "break"
622
+
623
+ def select_all(self, event=None):
624
+ self.text.tag_add("sel", "1.0", "end-1c")
625
+ self.text.mark_set("insert", "1.0")
626
+ self.text.see("insert")
627
+ return "break"
628
+
629
+ def remove_selection(self, event=None):
630
+ self.text.tag_remove("sel", "1.0", "end")
631
+ self.text.see("insert")
632
+ return "break"
633
+
634
+ def move_at_edge_if_selection(self, edge_index):
635
+ """Cursor move begins at start or end of selection
636
+
637
+ When a left/right cursor key is pressed create and return to Tkinter a
638
+ function which causes a cursor move from the associated edge of the
639
+ selection.
640
+
641
+ """
642
+ self_text_index = self.text.index
643
+ self_text_mark_set = self.text.mark_set
644
+ edges_table = ("sel.first+1c", "sel.last-1c")
645
+ def move_at_edge(event):
646
+ if (event.state & 5) == 0: # no shift(==1) or control(==4) pressed
647
+ try:
648
+ self_text_index("sel.first")
649
+ self_text_mark_set("insert", edges_table[edge_index])
650
+ except TclError:
651
+ pass
652
+ return move_at_edge
653
+
654
+ def del_word_left(self, event):
655
+ self.text.event_generate('<Meta-Delete>')
656
+ return "break"
657
+
658
+ def del_word_right(self, event):
659
+ self.text.event_generate('<Meta-d>')
660
+ return "break"
661
+
662
+ def find_event(self, event):
663
+ search.find(self.text)
664
+ return "break"
665
+
666
+ def find_again_event(self, event):
667
+ search.find_again(self.text)
668
+ return "break"
669
+
670
+ def find_selection_event(self, event):
671
+ search.find_selection(self.text)
672
+ return "break"
673
+
674
+ def find_in_files_event(self, event):
675
+ grep.grep(self.text, self.io, self.flist)
676
+ return "break"
677
+
678
+ def replace_event(self, event):
679
+ replace.replace(self.text)
680
+ return "break"
681
+
682
+ def goto_line_event(self, event):
683
+ text = self.text
684
+ lineno = query.Goto(
685
+ text, "Go To Line",
686
+ "Enter a positive integer\n"
687
+ "('big' = end of file):"
688
+ ).result
689
+ if lineno is not None:
690
+ text.tag_remove("sel", "1.0", "end")
691
+ text.mark_set("insert", f'{lineno}.0')
692
+ text.see("insert")
693
+ self.set_line_and_column()
694
+ return "break"
695
+
696
+ def open_module(self):
697
+ """Get module name from user and open it.
698
+
699
+ Return module path or None for calls by open_module_browser
700
+ when latter is not invoked in named editor window.
701
+ """
702
+ # XXX This, open_module_browser, and open_path_browser
703
+ # would fit better in iomenu.IOBinding.
704
+ try:
705
+ name = self.text.get("sel.first", "sel.last").strip()
706
+ except TclError:
707
+ name = ''
708
+ file_path = query.ModuleName(
709
+ self.text, "Open Module",
710
+ "Enter the name of a Python module\n"
711
+ "to search on sys.path and open:",
712
+ name).result
713
+ if file_path is not None:
714
+ if self.flist:
715
+ self.flist.open(file_path)
716
+ else:
717
+ self.io.loadfile(file_path)
718
+ return file_path
719
+
720
+ def open_module_event(self, event):
721
+ self.open_module()
722
+ return "break"
723
+
724
+ def open_module_browser(self, event=None):
725
+ filename = self.io.filename
726
+ if not (self.__class__.__name__ == 'PyShellEditorWindow'
727
+ and filename):
728
+ filename = self.open_module()
729
+ if filename is None:
730
+ return "break"
731
+ from idlelib import browser
732
+ browser.ModuleBrowser(self.root, filename)
733
+ return "break"
734
+
735
+ def open_path_browser(self, event=None):
736
+ from idlelib import pathbrowser
737
+ pathbrowser.PathBrowser(self.root)
738
+ return "break"
739
+
740
+ def open_turtle_demo(self, event = None):
741
+ import subprocess
742
+
743
+ cmd = [sys.executable,
744
+ '-c',
745
+ 'from turtledemo.__main__ import main; main()']
746
+ subprocess.Popen(cmd, shell=False)
747
+ return "break"
748
+
749
+ def gotoline(self, lineno):
750
+ if lineno is not None and lineno > 0:
751
+ self.text.mark_set("insert", "%d.0" % lineno)
752
+ self.text.tag_remove("sel", "1.0", "end")
753
+ self.text.tag_add("sel", "insert", "insert +1l")
754
+ self.center()
755
+
756
+ def ispythonsource(self, filename):
757
+ if not filename or os.path.isdir(filename):
758
+ return True
759
+ base, ext = os.path.splitext(os.path.basename(filename))
760
+ if os.path.normcase(ext) in (".py", ".pyw"):
761
+ return True
762
+ line = self.text.get('1.0', '1.0 lineend')
763
+ return line.startswith('#!') and 'python' in line
764
+
765
+ def close_hook(self):
766
+ if self.flist:
767
+ self.flist.unregister_maybe_terminate(self)
768
+ self.flist = None
769
+
770
+ def set_close_hook(self, close_hook):
771
+ self.close_hook = close_hook
772
+
773
+ def filename_change_hook(self):
774
+ if self.flist:
775
+ self.flist.filename_changed_edit(self)
776
+ self.saved_change_hook()
777
+ self.top.update_windowlist_registry(self)
778
+ self.ResetColorizer()
779
+
780
+ def _addcolorizer(self):
781
+ if self.color:
782
+ return
783
+ if self.ispythonsource(self.io.filename):
784
+ self.color = self.ColorDelegator()
785
+ # can add more colorizers here...
786
+ if self.color:
787
+ self.per.removefilter(self.undo)
788
+ self.per.insertfilter(self.color)
789
+ self.per.insertfilter(self.undo)
790
+
791
+ def _rmcolorizer(self):
792
+ if not self.color:
793
+ return
794
+ self.color.removecolors()
795
+ self.per.removefilter(self.color)
796
+ self.color = None
797
+
798
+ def ResetColorizer(self):
799
+ "Update the color theme"
800
+ # Called from self.filename_change_hook and from configdialog.py
801
+ self._rmcolorizer()
802
+ self._addcolorizer()
803
+ EditorWindow.color_config(self.text)
804
+
805
+ if self.code_context is not None:
806
+ self.code_context.update_highlight_colors()
807
+
808
+ if self.line_numbers is not None:
809
+ self.line_numbers.update_colors()
810
+
811
+ IDENTCHARS = string.ascii_letters + string.digits + "_"
812
+
813
+ def colorize_syntax_error(self, text, pos):
814
+ text.tag_add("ERROR", pos)
815
+ char = text.get(pos)
816
+ if char and char in self.IDENTCHARS:
817
+ text.tag_add("ERROR", pos + " wordstart", pos)
818
+ if '\n' == text.get(pos): # error at line end
819
+ text.mark_set("insert", pos)
820
+ else:
821
+ text.mark_set("insert", pos + "+1c")
822
+ text.see(pos)
823
+
824
+ def update_cursor_blink(self):
825
+ "Update the cursor blink configuration."
826
+ cursorblink = idleConf.GetOption(
827
+ 'main', 'EditorWindow', 'cursor-blink', type='bool')
828
+ if not cursorblink:
829
+ self.text['insertofftime'] = 0
830
+ else:
831
+ # Restore the original value
832
+ self.text['insertofftime'] = idleConf.blink_off_time
833
+
834
+ def ResetFont(self):
835
+ "Update the text widgets' font if it is changed"
836
+ # Called from configdialog.py
837
+
838
+ # Update the code context widget first, since its height affects
839
+ # the height of the text widget. This avoids double re-rendering.
840
+ if self.code_context is not None:
841
+ self.code_context.update_font()
842
+ # Next, update the line numbers widget, since its width affects
843
+ # the width of the text widget.
844
+ if self.line_numbers is not None:
845
+ self.line_numbers.update_font()
846
+ # Finally, update the main text widget.
847
+ new_font = idleConf.GetFont(self.root, 'main', 'EditorWindow')
848
+ self.text['font'] = new_font
849
+ self.set_width()
850
+
851
+ def RemoveKeybindings(self):
852
+ "Remove the keybindings before they are changed."
853
+ # Called from configdialog.py
854
+ self.mainmenu.default_keydefs = keydefs = idleConf.GetCurrentKeySet()
855
+ for event, keylist in keydefs.items():
856
+ self.text.event_delete(event, *keylist)
857
+ for extensionName in self.get_standard_extension_names():
858
+ xkeydefs = idleConf.GetExtensionBindings(extensionName)
859
+ if xkeydefs:
860
+ for event, keylist in xkeydefs.items():
861
+ self.text.event_delete(event, *keylist)
862
+
863
+ def ApplyKeybindings(self):
864
+ "Update the keybindings after they are changed"
865
+ # Called from configdialog.py
866
+ self.mainmenu.default_keydefs = keydefs = idleConf.GetCurrentKeySet()
867
+ self.apply_bindings()
868
+ for extensionName in self.get_standard_extension_names():
869
+ xkeydefs = idleConf.GetExtensionBindings(extensionName)
870
+ if xkeydefs:
871
+ self.apply_bindings(xkeydefs)
872
+ #update menu accelerators
873
+ menuEventDict = {}
874
+ for menu in self.mainmenu.menudefs:
875
+ menuEventDict[menu[0]] = {}
876
+ for item in menu[1]:
877
+ if item:
878
+ menuEventDict[menu[0]][prepstr(item[0])[1]] = item[1]
879
+ for menubarItem in self.menudict:
880
+ menu = self.menudict[menubarItem]
881
+ end = menu.index(END)
882
+ if end is None:
883
+ # Skip empty menus
884
+ continue
885
+ end += 1
886
+ for index in range(0, end):
887
+ if menu.type(index) == 'command':
888
+ accel = menu.entrycget(index, 'accelerator')
889
+ if accel:
890
+ itemName = menu.entrycget(index, 'label')
891
+ event = ''
892
+ if menubarItem in menuEventDict:
893
+ if itemName in menuEventDict[menubarItem]:
894
+ event = menuEventDict[menubarItem][itemName]
895
+ if event:
896
+ accel = get_accelerator(keydefs, event)
897
+ menu.entryconfig(index, accelerator=accel)
898
+
899
+ def set_notabs_indentwidth(self):
900
+ "Update the indentwidth if changed and not using tabs in this window"
901
+ # Called from configdialog.py
902
+ if not self.usetabs:
903
+ self.indentwidth = idleConf.GetOption('main', 'Indent','num-spaces',
904
+ type='int')
905
+
906
+ def reset_help_menu_entries(self):
907
+ "Update the additional help entries on the Help menu"
908
+ help_list = idleConf.GetAllExtraHelpSourcesList()
909
+ helpmenu = self.menudict['help']
910
+ # first delete the extra help entries, if any
911
+ helpmenu_length = helpmenu.index(END)
912
+ if helpmenu_length > self.base_helpmenu_length:
913
+ helpmenu.delete((self.base_helpmenu_length + 1), helpmenu_length)
914
+ # then rebuild them
915
+ if help_list:
916
+ helpmenu.add_separator()
917
+ for entry in help_list:
918
+ cmd = self.__extra_help_callback(entry[1])
919
+ helpmenu.add_command(label=entry[0], command=cmd)
920
+ # and update the menu dictionary
921
+ self.menudict['help'] = helpmenu
922
+
923
+ def __extra_help_callback(self, helpfile):
924
+ "Create a callback with the helpfile value frozen at definition time"
925
+ def display_extra_help(helpfile=helpfile):
926
+ if not helpfile.startswith(('www', 'http')):
927
+ helpfile = os.path.normpath(helpfile)
928
+ if sys.platform[:3] == 'win':
929
+ try:
930
+ os.startfile(helpfile)
931
+ except OSError as why:
932
+ messagebox.showerror(title='Document Start Failure',
933
+ message=str(why), parent=self.text)
934
+ else:
935
+ webbrowser.open(helpfile)
936
+ return display_extra_help
937
+
938
+ def update_recent_files_list(self, new_file=None):
939
+ "Load and update the recent files list and menus"
940
+ # TODO: move to iomenu.
941
+ rf_list = []
942
+ file_path = self.recent_files_path
943
+ if file_path and os.path.exists(file_path):
944
+ with open(file_path, 'r',
945
+ encoding='utf_8', errors='replace') as rf_list_file:
946
+ rf_list = rf_list_file.readlines()
947
+ if new_file:
948
+ new_file = os.path.abspath(new_file) + '\n'
949
+ if new_file in rf_list:
950
+ rf_list.remove(new_file) # move to top
951
+ rf_list.insert(0, new_file)
952
+ # clean and save the recent files list
953
+ bad_paths = []
954
+ for path in rf_list:
955
+ if '\0' in path or not os.path.exists(path[0:-1]):
956
+ bad_paths.append(path)
957
+ rf_list = [path for path in rf_list if path not in bad_paths]
958
+ ulchars = "1234567890ABCDEFGHIJK"
959
+ rf_list = rf_list[0:len(ulchars)]
960
+ if file_path:
961
+ try:
962
+ with open(file_path, 'w',
963
+ encoding='utf_8', errors='replace') as rf_file:
964
+ rf_file.writelines(rf_list)
965
+ except OSError as err:
966
+ if not getattr(self.root, "recentfiles_message", False):
967
+ self.root.recentfiles_message = True
968
+ messagebox.showwarning(title='IDLE Warning',
969
+ message="Cannot save Recent Files list to disk.\n"
970
+ f" {err}\n"
971
+ "Select OK to continue.",
972
+ parent=self.text)
973
+ # for each edit window instance, construct the recent files menu
974
+ for instance in self.top.instance_dict:
975
+ menu = instance.recent_files_menu
976
+ menu.delete(0, END) # clear, and rebuild:
977
+ for i, file_name in enumerate(rf_list):
978
+ file_name = file_name.rstrip() # zap \n
979
+ callback = instance.__recent_file_callback(file_name)
980
+ menu.add_command(label=ulchars[i] + " " + file_name,
981
+ command=callback,
982
+ underline=0)
983
+
984
+ def __recent_file_callback(self, file_name):
985
+ def open_recent_file(fn_closure=file_name):
986
+ self.io.open(editFile=fn_closure)
987
+ return open_recent_file
988
+
989
+ def saved_change_hook(self):
990
+ short = self.short_title()
991
+ long = self.long_title()
992
+ if short and long:
993
+ title = short + " - " + long + _py_version
994
+ elif short:
995
+ title = short
996
+ elif long:
997
+ title = long
998
+ else:
999
+ title = "untitled"
1000
+ icon = short or long or title
1001
+ if not self.get_saved():
1002
+ title = "*%s*" % title
1003
+ icon = "*%s" % icon
1004
+ self.top.wm_title(title)
1005
+ self.top.wm_iconname(icon)
1006
+
1007
+ def get_saved(self):
1008
+ return self.undo.get_saved()
1009
+
1010
+ def set_saved(self, flag):
1011
+ self.undo.set_saved(flag)
1012
+
1013
+ def reset_undo(self):
1014
+ self.undo.reset_undo()
1015
+
1016
+ def short_title(self):
1017
+ filename = self.io.filename
1018
+ return os.path.basename(filename) if filename else "untitled"
1019
+
1020
+ def long_title(self):
1021
+ return self.io.filename or ""
1022
+
1023
+ def center_insert_event(self, event):
1024
+ self.center()
1025
+ return "break"
1026
+
1027
+ def center(self, mark="insert"):
1028
+ text = self.text
1029
+ top, bot = self.getwindowlines()
1030
+ lineno = self.getlineno(mark)
1031
+ height = bot - top
1032
+ newtop = max(1, lineno - height//2)
1033
+ text.yview(float(newtop))
1034
+
1035
+ def getwindowlines(self):
1036
+ text = self.text
1037
+ top = self.getlineno("@0,0")
1038
+ bot = self.getlineno("@0,65535")
1039
+ if top == bot and text.winfo_height() == 1:
1040
+ # Geometry manager hasn't run yet
1041
+ height = int(text['height'])
1042
+ bot = top + height - 1
1043
+ return top, bot
1044
+
1045
+ def getlineno(self, mark="insert"):
1046
+ text = self.text
1047
+ return int(float(text.index(mark)))
1048
+
1049
+ def get_geometry(self):
1050
+ "Return (width, height, x, y)"
1051
+ geom = self.top.wm_geometry()
1052
+ m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom)
1053
+ return list(map(int, m.groups()))
1054
+
1055
+ def close_event(self, event):
1056
+ self.close()
1057
+ return "break"
1058
+
1059
+ def maybesave(self):
1060
+ if self.io:
1061
+ if not self.get_saved():
1062
+ if self.top.state()!='normal':
1063
+ self.top.deiconify()
1064
+ self.top.lower()
1065
+ self.top.lift()
1066
+ return self.io.maybesave()
1067
+
1068
+ def close(self):
1069
+ try:
1070
+ reply = self.maybesave()
1071
+ if str(reply) != "cancel":
1072
+ self._close()
1073
+ return reply
1074
+ except AttributeError: # bpo-35379: close called twice
1075
+ pass
1076
+
1077
+ def _close(self):
1078
+ if self.io.filename:
1079
+ self.update_recent_files_list(new_file=self.io.filename)
1080
+ window.unregister_callback(self.postwindowsmenu)
1081
+ self.unload_extensions()
1082
+ self.io.close()
1083
+ self.io = None
1084
+ self.undo = None
1085
+ if self.color:
1086
+ self.color.close()
1087
+ self.color = None
1088
+ self.text = None
1089
+ self.tkinter_vars = None
1090
+ self.per.close()
1091
+ self.per = None
1092
+ self.top.destroy()
1093
+ if self.close_hook:
1094
+ # unless override: unregister from flist, terminate if last window
1095
+ self.close_hook()
1096
+
1097
+ def load_extensions(self):
1098
+ self.extensions = {}
1099
+ self.load_standard_extensions()
1100
+
1101
+ def unload_extensions(self):
1102
+ for ins in list(self.extensions.values()):
1103
+ if hasattr(ins, "close"):
1104
+ ins.close()
1105
+ self.extensions = {}
1106
+
1107
+ def load_standard_extensions(self):
1108
+ for name in self.get_standard_extension_names():
1109
+ try:
1110
+ self.load_extension(name)
1111
+ except:
1112
+ print("Failed to load extension", repr(name))
1113
+ traceback.print_exc()
1114
+
1115
+ def get_standard_extension_names(self):
1116
+ return idleConf.GetExtensions(editor_only=True)
1117
+
1118
+ extfiles = { # Map built-in config-extension section names to file names.
1119
+ 'ZzDummy': 'zzdummy',
1120
+ }
1121
+
1122
+ def load_extension(self, name):
1123
+ fname = self.extfiles.get(name, name)
1124
+ try:
1125
+ try:
1126
+ mod = importlib.import_module('.' + fname, package=__package__)
1127
+ except (ImportError, TypeError):
1128
+ mod = importlib.import_module(fname)
1129
+ except ImportError:
1130
+ print("\nFailed to import extension: ", name)
1131
+ raise
1132
+ cls = getattr(mod, name)
1133
+ keydefs = idleConf.GetExtensionBindings(name)
1134
+ if hasattr(cls, "menudefs"):
1135
+ self.fill_menus(cls.menudefs, keydefs)
1136
+ ins = cls(self)
1137
+ self.extensions[name] = ins
1138
+ if keydefs:
1139
+ self.apply_bindings(keydefs)
1140
+ for vevent in keydefs:
1141
+ methodname = vevent.replace("-", "_")
1142
+ while methodname[:1] == '<':
1143
+ methodname = methodname[1:]
1144
+ while methodname[-1:] == '>':
1145
+ methodname = methodname[:-1]
1146
+ methodname = methodname + "_event"
1147
+ if hasattr(ins, methodname):
1148
+ self.text.bind(vevent, getattr(ins, methodname))
1149
+
1150
+ def apply_bindings(self, keydefs=None):
1151
+ if keydefs is None:
1152
+ keydefs = self.mainmenu.default_keydefs
1153
+ text = self.text
1154
+ text.keydefs = keydefs
1155
+ for event, keylist in keydefs.items():
1156
+ if keylist:
1157
+ text.event_add(event, *keylist)
1158
+
1159
+ def fill_menus(self, menudefs=None, keydefs=None):
1160
+ """Add appropriate entries to the menus and submenus
1161
+
1162
+ Menus that are absent or None in self.menudict are ignored.
1163
+ """
1164
+ if menudefs is None:
1165
+ menudefs = self.mainmenu.menudefs
1166
+ if keydefs is None:
1167
+ keydefs = self.mainmenu.default_keydefs
1168
+ menudict = self.menudict
1169
+ text = self.text
1170
+ for mname, entrylist in menudefs:
1171
+ menu = menudict.get(mname)
1172
+ if not menu:
1173
+ continue
1174
+ for entry in entrylist:
1175
+ if not entry:
1176
+ menu.add_separator()
1177
+ else:
1178
+ label, eventname = entry
1179
+ checkbutton = (label[:1] == '!')
1180
+ if checkbutton:
1181
+ label = label[1:]
1182
+ underline, label = prepstr(label)
1183
+ accelerator = get_accelerator(keydefs, eventname)
1184
+ def command(text=text, eventname=eventname):
1185
+ text.event_generate(eventname)
1186
+ if checkbutton:
1187
+ var = self.get_var_obj(eventname, BooleanVar)
1188
+ menu.add_checkbutton(label=label, underline=underline,
1189
+ command=command, accelerator=accelerator,
1190
+ variable=var)
1191
+ else:
1192
+ menu.add_command(label=label, underline=underline,
1193
+ command=command,
1194
+ accelerator=accelerator)
1195
+
1196
+ def getvar(self, name):
1197
+ var = self.get_var_obj(name)
1198
+ if var:
1199
+ value = var.get()
1200
+ return value
1201
+ else:
1202
+ raise NameError(name)
1203
+
1204
+ def setvar(self, name, value, vartype=None):
1205
+ var = self.get_var_obj(name, vartype)
1206
+ if var:
1207
+ var.set(value)
1208
+ else:
1209
+ raise NameError(name)
1210
+
1211
+ def get_var_obj(self, name, vartype=None):
1212
+ var = self.tkinter_vars.get(name)
1213
+ if not var and vartype:
1214
+ # create a Tkinter variable object with self.text as master:
1215
+ self.tkinter_vars[name] = var = vartype(self.text)
1216
+ return var
1217
+
1218
+ # Tk implementations of "virtual text methods" -- each platform
1219
+ # reusing IDLE's support code needs to define these for its GUI's
1220
+ # flavor of widget.
1221
+
1222
+ # Is character at text_index in a Python string? Return 0 for
1223
+ # "guaranteed no", true for anything else. This info is expensive
1224
+ # to compute ab initio, but is probably already known by the
1225
+ # platform's colorizer.
1226
+
1227
+ def is_char_in_string(self, text_index):
1228
+ if self.color:
1229
+ # Return true iff colorizer hasn't (re)gotten this far
1230
+ # yet, or the character is tagged as being in a string
1231
+ return self.text.tag_prevrange("TODO", text_index) or \
1232
+ "STRING" in self.text.tag_names(text_index)
1233
+ else:
1234
+ # The colorizer is missing: assume the worst
1235
+ return 1
1236
+
1237
+ # If a selection is defined in the text widget, return (start,
1238
+ # end) as Tkinter text indices, otherwise return (None, None)
1239
+ def get_selection_indices(self):
1240
+ try:
1241
+ first = self.text.index("sel.first")
1242
+ last = self.text.index("sel.last")
1243
+ return first, last
1244
+ except TclError:
1245
+ return None, None
1246
+
1247
+ # Return the text widget's current view of what a tab stop means
1248
+ # (equivalent width in spaces).
1249
+
1250
+ def get_tk_tabwidth(self):
1251
+ current = self.text['tabs'] or TK_TABWIDTH_DEFAULT
1252
+ return int(current)
1253
+
1254
+ # Set the text widget's current view of what a tab stop means.
1255
+
1256
+ def set_tk_tabwidth(self, newtabwidth):
1257
+ text = self.text
1258
+ if self.get_tk_tabwidth() != newtabwidth:
1259
+ # Set text widget tab width
1260
+ pixels = text.tk.call("font", "measure", text["font"],
1261
+ "-displayof", text.master,
1262
+ "n" * newtabwidth)
1263
+ text.configure(tabs=pixels)
1264
+
1265
+ ### begin autoindent code ### (configuration was moved to beginning of class)
1266
+
1267
+ def set_indentation_params(self, is_py_src, guess=True):
1268
+ if is_py_src and guess:
1269
+ i = self.guess_indent()
1270
+ if 2 <= i <= 8:
1271
+ self.indentwidth = i
1272
+ if self.indentwidth != self.tabwidth:
1273
+ self.usetabs = False
1274
+ self.set_tk_tabwidth(self.tabwidth)
1275
+
1276
+ def smart_backspace_event(self, event):
1277
+ text = self.text
1278
+ first, last = self.get_selection_indices()
1279
+ if first and last:
1280
+ text.delete(first, last)
1281
+ text.mark_set("insert", first)
1282
+ return "break"
1283
+ # Delete whitespace left, until hitting a real char or closest
1284
+ # preceding virtual tab stop.
1285
+ chars = text.get("insert linestart", "insert")
1286
+ if chars == '':
1287
+ if text.compare("insert", ">", "1.0"):
1288
+ # easy: delete preceding newline
1289
+ text.delete("insert-1c")
1290
+ else:
1291
+ text.bell() # at start of buffer
1292
+ return "break"
1293
+ if chars[-1] not in " \t":
1294
+ # easy: delete preceding real char
1295
+ text.delete("insert-1c")
1296
+ return "break"
1297
+ # Ick. It may require *inserting* spaces if we back up over a
1298
+ # tab character! This is written to be clear, not fast.
1299
+ tabwidth = self.tabwidth
1300
+ have = len(chars.expandtabs(tabwidth))
1301
+ assert have > 0
1302
+ want = ((have - 1) // self.indentwidth) * self.indentwidth
1303
+ # Debug prompt is multilined....
1304
+ ncharsdeleted = 0
1305
+ while 1:
1306
+ if chars == self.prompt_last_line: # '' unless PyShell
1307
+ break
1308
+ chars = chars[:-1]
1309
+ ncharsdeleted = ncharsdeleted + 1
1310
+ have = len(chars.expandtabs(tabwidth))
1311
+ if have <= want or chars[-1] not in " \t":
1312
+ break
1313
+ text.undo_block_start()
1314
+ text.delete("insert-%dc" % ncharsdeleted, "insert")
1315
+ if have < want:
1316
+ text.insert("insert", ' ' * (want - have))
1317
+ text.undo_block_stop()
1318
+ return "break"
1319
+
1320
+ def smart_indent_event(self, event):
1321
+ # if intraline selection:
1322
+ # delete it
1323
+ # elif multiline selection:
1324
+ # do indent-region
1325
+ # else:
1326
+ # indent one level
1327
+ text = self.text
1328
+ first, last = self.get_selection_indices()
1329
+ text.undo_block_start()
1330
+ try:
1331
+ if first and last:
1332
+ if index2line(first) != index2line(last):
1333
+ return self.fregion.indent_region_event(event)
1334
+ text.delete(first, last)
1335
+ text.mark_set("insert", first)
1336
+ prefix = text.get("insert linestart", "insert")
1337
+ raw, effective = get_line_indent(prefix, self.tabwidth)
1338
+ if raw == len(prefix):
1339
+ # only whitespace to the left
1340
+ self.reindent_to(effective + self.indentwidth)
1341
+ else:
1342
+ # tab to the next 'stop' within or to right of line's text:
1343
+ if self.usetabs:
1344
+ pad = '\t'
1345
+ else:
1346
+ effective = len(prefix.expandtabs(self.tabwidth))
1347
+ n = self.indentwidth
1348
+ pad = ' ' * (n - effective % n)
1349
+ text.insert("insert", pad)
1350
+ text.see("insert")
1351
+ return "break"
1352
+ finally:
1353
+ text.undo_block_stop()
1354
+
1355
+ def newline_and_indent_event(self, event):
1356
+ """Insert a newline and indentation after Enter keypress event.
1357
+
1358
+ Properly position the cursor on the new line based on information
1359
+ from the current line. This takes into account if the current line
1360
+ is a shell prompt, is empty, has selected text, contains a block
1361
+ opener, contains a block closer, is a continuation line, or
1362
+ is inside a string.
1363
+ """
1364
+ text = self.text
1365
+ first, last = self.get_selection_indices()
1366
+ text.undo_block_start()
1367
+ try: # Close undo block and expose new line in finally clause.
1368
+ if first and last:
1369
+ text.delete(first, last)
1370
+ text.mark_set("insert", first)
1371
+ line = text.get("insert linestart", "insert")
1372
+
1373
+ # Count leading whitespace for indent size.
1374
+ i, n = 0, len(line)
1375
+ while i < n and line[i] in " \t":
1376
+ i += 1
1377
+ if i == n:
1378
+ # The cursor is in or at leading indentation in a continuation
1379
+ # line; just inject an empty line at the start.
1380
+ text.insert("insert linestart", '\n')
1381
+ return "break"
1382
+ indent = line[:i]
1383
+
1384
+ # Strip whitespace before insert point unless it's in the prompt.
1385
+ i = 0
1386
+ while line and line[-1] in " \t" and line != self.prompt_last_line:
1387
+ line = line[:-1]
1388
+ i += 1
1389
+ if i:
1390
+ text.delete("insert - %d chars" % i, "insert")
1391
+
1392
+ # Strip whitespace after insert point.
1393
+ while text.get("insert") in " \t":
1394
+ text.delete("insert")
1395
+
1396
+ # Insert new line.
1397
+ text.insert("insert", '\n')
1398
+
1399
+ # Adjust indentation for continuations and block open/close.
1400
+ # First need to find the last statement.
1401
+ lno = index2line(text.index('insert'))
1402
+ y = pyparse.Parser(self.indentwidth, self.tabwidth)
1403
+ if not self.prompt_last_line:
1404
+ for context in self.num_context_lines:
1405
+ startat = max(lno - context, 1)
1406
+ startatindex = repr(startat) + ".0"
1407
+ rawtext = text.get(startatindex, "insert")
1408
+ y.set_code(rawtext)
1409
+ bod = y.find_good_parse_start(
1410
+ self._build_char_in_string_func(startatindex))
1411
+ if bod is not None or startat == 1:
1412
+ break
1413
+ y.set_lo(bod or 0)
1414
+ else:
1415
+ r = text.tag_prevrange("console", "insert")
1416
+ if r:
1417
+ startatindex = r[1]
1418
+ else:
1419
+ startatindex = "1.0"
1420
+ rawtext = text.get(startatindex, "insert")
1421
+ y.set_code(rawtext)
1422
+ y.set_lo(0)
1423
+
1424
+ c = y.get_continuation_type()
1425
+ if c != pyparse.C_NONE:
1426
+ # The current statement hasn't ended yet.
1427
+ if c == pyparse.C_STRING_FIRST_LINE:
1428
+ # After the first line of a string do not indent at all.
1429
+ pass
1430
+ elif c == pyparse.C_STRING_NEXT_LINES:
1431
+ # Inside a string which started before this line;
1432
+ # just mimic the current indent.
1433
+ text.insert("insert", indent)
1434
+ elif c == pyparse.C_BRACKET:
1435
+ # Line up with the first (if any) element of the
1436
+ # last open bracket structure; else indent one
1437
+ # level beyond the indent of the line with the
1438
+ # last open bracket.
1439
+ self.reindent_to(y.compute_bracket_indent())
1440
+ elif c == pyparse.C_BACKSLASH:
1441
+ # If more than one line in this statement already, just
1442
+ # mimic the current indent; else if initial line
1443
+ # has a start on an assignment stmt, indent to
1444
+ # beyond leftmost =; else to beyond first chunk of
1445
+ # non-whitespace on initial line.
1446
+ if y.get_num_lines_in_stmt() > 1:
1447
+ text.insert("insert", indent)
1448
+ else:
1449
+ self.reindent_to(y.compute_backslash_indent())
1450
+ else:
1451
+ assert 0, "bogus continuation type %r" % (c,)
1452
+ return "break"
1453
+
1454
+ # This line starts a brand new statement; indent relative to
1455
+ # indentation of initial line of closest preceding
1456
+ # interesting statement.
1457
+ indent = y.get_base_indent_string()
1458
+ text.insert("insert", indent)
1459
+ if y.is_block_opener():
1460
+ self.smart_indent_event(event)
1461
+ elif indent and y.is_block_closer():
1462
+ self.smart_backspace_event(event)
1463
+ return "break"
1464
+ finally:
1465
+ text.see("insert")
1466
+ text.undo_block_stop()
1467
+
1468
+ # Our editwin provides an is_char_in_string function that works
1469
+ # with a Tk text index, but PyParse only knows about offsets into
1470
+ # a string. This builds a function for PyParse that accepts an
1471
+ # offset.
1472
+
1473
+ def _build_char_in_string_func(self, startindex):
1474
+ def inner(offset, _startindex=startindex,
1475
+ _icis=self.is_char_in_string):
1476
+ return _icis(_startindex + "+%dc" % offset)
1477
+ return inner
1478
+
1479
+ # XXX this isn't bound to anything -- see tabwidth comments
1480
+ ## def change_tabwidth_event(self, event):
1481
+ ## new = self._asktabwidth()
1482
+ ## if new != self.tabwidth:
1483
+ ## self.tabwidth = new
1484
+ ## self.set_indentation_params(0, guess=0)
1485
+ ## return "break"
1486
+
1487
+ # Make string that displays as n leading blanks.
1488
+
1489
+ def _make_blanks(self, n):
1490
+ if self.usetabs:
1491
+ ntabs, nspaces = divmod(n, self.tabwidth)
1492
+ return '\t' * ntabs + ' ' * nspaces
1493
+ else:
1494
+ return ' ' * n
1495
+
1496
+ # Delete from beginning of line to insert point, then reinsert
1497
+ # column logical (meaning use tabs if appropriate) spaces.
1498
+
1499
+ def reindent_to(self, column):
1500
+ text = self.text
1501
+ text.undo_block_start()
1502
+ if text.compare("insert linestart", "!=", "insert"):
1503
+ text.delete("insert linestart", "insert")
1504
+ if column:
1505
+ text.insert("insert", self._make_blanks(column))
1506
+ text.undo_block_stop()
1507
+
1508
+ # Guess indentwidth from text content.
1509
+ # Return guessed indentwidth. This should not be believed unless
1510
+ # it's in a reasonable range (e.g., it will be 0 if no indented
1511
+ # blocks are found).
1512
+
1513
+ def guess_indent(self):
1514
+ opener, indented = IndentSearcher(self.text, self.tabwidth).run()
1515
+ if opener and indented:
1516
+ raw, indentsmall = get_line_indent(opener, self.tabwidth)
1517
+ raw, indentlarge = get_line_indent(indented, self.tabwidth)
1518
+ else:
1519
+ indentsmall = indentlarge = 0
1520
+ return indentlarge - indentsmall
1521
+
1522
+ def toggle_line_numbers_event(self, event=None):
1523
+ if self.line_numbers is None:
1524
+ return
1525
+
1526
+ if self.line_numbers.is_shown:
1527
+ self.line_numbers.hide_sidebar()
1528
+ menu_label = "Show"
1529
+ else:
1530
+ self.line_numbers.show_sidebar()
1531
+ menu_label = "Hide"
1532
+ self.update_menu_label(menu='options', index='*ine*umbers',
1533
+ label=f'{menu_label} Line Numbers')
1534
+
1535
+ # "line.col" -> line, as an int
1536
+ def index2line(index):
1537
+ return int(float(index))
1538
+
1539
+
1540
+ _line_indent_re = re.compile(r'[ \t]*')
1541
+ def get_line_indent(line, tabwidth):
1542
+ """Return a line's indentation as (# chars, effective # of spaces).
1543
+
1544
+ The effective # of spaces is the length after properly "expanding"
1545
+ the tabs into spaces, as done by str.expandtabs(tabwidth).
1546
+ """
1547
+ m = _line_indent_re.match(line)
1548
+ return m.end(), len(m.group().expandtabs(tabwidth))
1549
+
1550
+
1551
+ class IndentSearcher:
1552
+
1553
+ # .run() chews over the Text widget, looking for a block opener
1554
+ # and the stmt following it. Returns a pair,
1555
+ # (line containing block opener, line containing stmt)
1556
+ # Either or both may be None.
1557
+
1558
+ def __init__(self, text, tabwidth):
1559
+ self.text = text
1560
+ self.tabwidth = tabwidth
1561
+ self.i = self.finished = 0
1562
+ self.blkopenline = self.indentedline = None
1563
+
1564
+ def readline(self):
1565
+ if self.finished:
1566
+ return ""
1567
+ i = self.i = self.i + 1
1568
+ mark = repr(i) + ".0"
1569
+ if self.text.compare(mark, ">=", "end"):
1570
+ return ""
1571
+ return self.text.get(mark, mark + " lineend+1c")
1572
+
1573
+ def tokeneater(self, type, token, start, end, line,
1574
+ INDENT=tokenize.INDENT,
1575
+ NAME=tokenize.NAME,
1576
+ OPENERS=('class', 'def', 'for', 'if', 'try', 'while')):
1577
+ if self.finished:
1578
+ pass
1579
+ elif type == NAME and token in OPENERS:
1580
+ self.blkopenline = line
1581
+ elif type == INDENT and self.blkopenline:
1582
+ self.indentedline = line
1583
+ self.finished = 1
1584
+
1585
+ def run(self):
1586
+ save_tabsize = tokenize.tabsize
1587
+ tokenize.tabsize = self.tabwidth
1588
+ try:
1589
+ try:
1590
+ tokens = tokenize.generate_tokens(self.readline)
1591
+ for token in tokens:
1592
+ self.tokeneater(*token)
1593
+ except (tokenize.TokenError, SyntaxError):
1594
+ # since we cut off the tokenizer early, we can trigger
1595
+ # spurious errors
1596
+ pass
1597
+ finally:
1598
+ tokenize.tabsize = save_tabsize
1599
+ return self.blkopenline, self.indentedline
1600
+
1601
+ ### end autoindent code ###
1602
+
1603
+ def prepstr(s):
1604
+ # Helper to extract the underscore from a string, e.g.
1605
+ # prepstr("Co_py") returns (2, "Copy").
1606
+ i = s.find('_')
1607
+ if i >= 0:
1608
+ s = s[:i] + s[i+1:]
1609
+ return i, s
1610
+
1611
+
1612
+ keynames = {
1613
+ 'bracketleft': '[',
1614
+ 'bracketright': ']',
1615
+ 'slash': '/',
1616
+ }
1617
+
1618
+ def get_accelerator(keydefs, eventname):
1619
+ keylist = keydefs.get(eventname)
1620
+ # issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5
1621
+ # if not keylist:
1622
+ if (not keylist) or (macosx.isCocoaTk() and eventname in {
1623
+ "<<open-module>>",
1624
+ "<<goto-line>>",
1625
+ "<<change-indentwidth>>"}):
1626
+ return ""
1627
+ s = keylist[0]
1628
+ s = re.sub(r"-[a-z]\b", lambda m: m.group().upper(), s)
1629
+ s = re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), m.group()), s)
1630
+ s = re.sub("Key-", "", s)
1631
+ s = re.sub("Cancel","Ctrl-Break",s) # dscherer@cmu.edu
1632
+ s = re.sub("Control-", "Ctrl-", s)
1633
+ s = re.sub("-", "+", s)
1634
+ s = re.sub("><", " ", s)
1635
+ s = re.sub("<", "", s)
1636
+ s = re.sub(">", "", s)
1637
+ return s
1638
+
1639
+
1640
+ def fixwordbreaks(root):
1641
+ # On Windows, tcl/tk breaks 'words' only on spaces, as in Command Prompt.
1642
+ # We want Motif style everywhere. See #21474, msg218992 and followup.
1643
+ tk = root.tk
1644
+ tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is loaded
1645
+ tk.call('set', 'tcl_wordchars', r'\w')
1646
+ tk.call('set', 'tcl_nonwordchars', r'\W')
1647
+
1648
+
1649
+ def _editor_window(parent): # htest #
1650
+ # error if close master window first - timer event, after script
1651
+ root = parent
1652
+ fixwordbreaks(root)
1653
+ if sys.argv[1:]:
1654
+ filename = sys.argv[1]
1655
+ else:
1656
+ filename = None
1657
+ macosx.setupApp(root, None)
1658
+ edit = EditorWindow(root=root, filename=filename)
1659
+ text = edit.text
1660
+ text['height'] = 10
1661
+ for i in range(20):
1662
+ text.insert('insert', ' '*i + str(i) + '\n')
1663
+ # text.bind("<<close-all-windows>>", edit.close_event)
1664
+ # Does not stop error, neither does following
1665
+ # edit.text.bind("<<close-window>>", edit.close_event)
1666
+
1667
+ if __name__ == '__main__':
1668
+ from unittest import main
1669
+ main('idlelib.idle_test.test_editor', verbosity=2, exit=False)
1670
+
1671
+ from idlelib.idle_test.htest import run
1672
+ run(_editor_window)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/extend.txt ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Writing an IDLE extension
2
+ =========================
3
+
4
+ An IDLE extension can define new key bindings and menu entries for IDLE
5
+ edit windows. There is a simple mechanism to load extensions when IDLE
6
+ starts up and to attach them to each edit window. (It is also possible
7
+ to make other changes to IDLE, but this must be done by editing the IDLE
8
+ source code.)
9
+
10
+ The list of extensions loaded at startup time is configured by editing
11
+ the file config-extensions.def. See below for details.
12
+
13
+ An IDLE extension is defined by a class. Methods of the class define
14
+ actions that are invoked by event bindings or menu entries. Class (or
15
+ instance) variables define the bindings and menu additions; these are
16
+ automatically applied by IDLE when the extension is linked to an edit
17
+ window.
18
+
19
+ An IDLE extension class is instantiated with a single argument,
20
+ `editwin', an EditorWindow instance. The extension cannot assume much
21
+ about this argument, but it is guaranteed to have the following instance
22
+ variables:
23
+
24
+ text a Text instance (a widget)
25
+ io an IOBinding instance (more about this later)
26
+ flist the FileList instance (shared by all edit windows)
27
+
28
+ (There are a few more, but they are rarely useful.)
29
+
30
+ The extension class must not directly bind Window Manager (e.g. X) events.
31
+ Rather, it must define one or more virtual events, e.g. <<z-in>>, and
32
+ corresponding methods, e.g. z_in_event(). The virtual events will be
33
+ bound to the corresponding methods, and Window Manager events can then be bound
34
+ to the virtual events. (This indirection is done so that the key bindings can
35
+ easily be changed, and so that other sources of virtual events can exist, such
36
+ as menu entries.)
37
+
38
+ An extension can define menu entries. This is done with a class or instance
39
+ variable named menudefs; it should be a list of pairs, where each pair is a
40
+ menu name (lowercase) and a list of menu entries. Each menu entry is either
41
+ None (to insert a separator entry) or a pair of strings (menu_label,
42
+ virtual_event). Here, menu_label is the label of the menu entry, and
43
+ virtual_event is the virtual event to be generated when the entry is selected.
44
+ An underscore in the menu label is removed; the character following the
45
+ underscore is displayed underlined, to indicate the shortcut character (for
46
+ Windows).
47
+
48
+ At the moment, extensions cannot define whole new menus; they must define
49
+ entries in existing menus. Some menus are not present on some windows; such
50
+ entry definitions are then ignored, but key bindings are still applied. (This
51
+ should probably be refined in the future.)
52
+
53
+ Extensions are not required to define menu entries for all the events they
54
+ implement. (They are also not required to create keybindings, but in that
55
+ case there must be empty bindings in cofig-extensions.def)
56
+
57
+ Here is a partial example from zzdummy.py:
58
+
59
+ class ZzDummy:
60
+
61
+ menudefs = [
62
+ ('format', [
63
+ ('Z in', '<<z-in>>'),
64
+ ('Z out', '<<z-out>>'),
65
+ ] )
66
+ ]
67
+
68
+ def __init__(self, editwin):
69
+ self.editwin = editwin
70
+
71
+ def z_in_event(self, event=None):
72
+ "...Do what you want here..."
73
+
74
+ The final piece of the puzzle is the file "config-extensions.def", which is
75
+ used to configure the loading of extensions and to establish key (or, more
76
+ generally, event) bindings to the virtual events defined in the extensions.
77
+
78
+ See the comments at the top of config-extensions.def for information. It's
79
+ currently necessary to manually modify that file to change IDLE's extension
80
+ loading or extension key bindings.
81
+
82
+ For further information on binding refer to the Tkinter Resources web page at
83
+ python.org and to the Tk Command "bind" man page.
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/filelist.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "idlelib.filelist"
2
+
3
+ import os
4
+ from tkinter import messagebox
5
+
6
+
7
+ class FileList:
8
+
9
+ # N.B. this import overridden in PyShellFileList.
10
+ from idlelib.editor import EditorWindow
11
+
12
+ def __init__(self, root):
13
+ self.root = root
14
+ self.dict = {}
15
+ self.inversedict = {}
16
+ self.vars = {} # For EditorWindow.getrawvar (shared Tcl variables)
17
+
18
+ def open(self, filename, action=None):
19
+ assert filename
20
+ filename = self.canonize(filename)
21
+ if os.path.isdir(filename):
22
+ # This can happen when bad filename is passed on command line:
23
+ messagebox.showerror(
24
+ "File Error",
25
+ "%r is a directory." % (filename,),
26
+ master=self.root)
27
+ return None
28
+ key = os.path.normcase(filename)
29
+ if key in self.dict:
30
+ edit = self.dict[key]
31
+ edit.top.wakeup()
32
+ return edit
33
+ if action:
34
+ # Don't create window, perform 'action', e.g. open in same window
35
+ return action(filename)
36
+ else:
37
+ edit = self.EditorWindow(self, filename, key)
38
+ if edit.good_load:
39
+ return edit
40
+ else:
41
+ edit._close()
42
+ return None
43
+
44
+ def gotofileline(self, filename, lineno=None):
45
+ edit = self.open(filename)
46
+ if edit is not None and lineno is not None:
47
+ edit.gotoline(lineno)
48
+
49
+ def new(self, filename=None):
50
+ return self.EditorWindow(self, filename)
51
+
52
+ def close_all_callback(self, *args, **kwds):
53
+ for edit in list(self.inversedict):
54
+ reply = edit.close()
55
+ if reply == "cancel":
56
+ break
57
+ return "break"
58
+
59
+ def unregister_maybe_terminate(self, edit):
60
+ try:
61
+ key = self.inversedict[edit]
62
+ except KeyError:
63
+ print("Don't know this EditorWindow object. (close)")
64
+ return
65
+ if key:
66
+ del self.dict[key]
67
+ del self.inversedict[edit]
68
+ if not self.inversedict:
69
+ self.root.quit()
70
+
71
+ def filename_changed_edit(self, edit):
72
+ edit.saved_change_hook()
73
+ try:
74
+ key = self.inversedict[edit]
75
+ except KeyError:
76
+ print("Don't know this EditorWindow object. (rename)")
77
+ return
78
+ filename = edit.io.filename
79
+ if not filename:
80
+ if key:
81
+ del self.dict[key]
82
+ self.inversedict[edit] = None
83
+ return
84
+ filename = self.canonize(filename)
85
+ newkey = os.path.normcase(filename)
86
+ if newkey == key:
87
+ return
88
+ if newkey in self.dict:
89
+ conflict = self.dict[newkey]
90
+ self.inversedict[conflict] = None
91
+ messagebox.showerror(
92
+ "Name Conflict",
93
+ "You now have multiple edit windows open for %r" % (filename,),
94
+ master=self.root)
95
+ self.dict[newkey] = edit
96
+ self.inversedict[edit] = newkey
97
+ if key:
98
+ try:
99
+ del self.dict[key]
100
+ except KeyError:
101
+ pass
102
+
103
+ def canonize(self, filename):
104
+ if not os.path.isabs(filename):
105
+ try:
106
+ pwd = os.getcwd()
107
+ except OSError:
108
+ pass
109
+ else:
110
+ filename = os.path.join(pwd, filename)
111
+ return os.path.normpath(filename)
112
+
113
+
114
+ def _test(): # TODO check and convert to htest
115
+ from tkinter import Tk
116
+ from idlelib.editor import fixwordbreaks
117
+ from idlelib.run import fix_scaling
118
+ root = Tk()
119
+ fix_scaling(root)
120
+ fixwordbreaks(root)
121
+ root.withdraw()
122
+ flist = FileList(root)
123
+ flist.new()
124
+ if flist.inversedict:
125
+ root.mainloop()
126
+
127
+ if __name__ == '__main__':
128
+ from unittest import main
129
+ main('idlelib.idle_test.test_filelist', verbosity=2)
130
+
131
+ # _test()
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/format.py ADDED
@@ -0,0 +1,426 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Format all or a selected region (line slice) of text.
2
+
3
+ Region formatting options: paragraph, comment block, indent, deindent,
4
+ comment, uncomment, tabify, and untabify.
5
+
6
+ File renamed from paragraph.py with functions added from editor.py.
7
+ """
8
+ import re
9
+ from tkinter.messagebox import askyesno
10
+ from tkinter.simpledialog import askinteger
11
+ from idlelib.config import idleConf
12
+
13
+
14
+ class FormatParagraph:
15
+ """Format a paragraph, comment block, or selection to a max width.
16
+
17
+ Does basic, standard text formatting, and also understands Python
18
+ comment blocks. Thus, for editing Python source code, this
19
+ extension is really only suitable for reformatting these comment
20
+ blocks or triple-quoted strings.
21
+
22
+ Known problems with comment reformatting:
23
+ * If there is a selection marked, and the first line of the
24
+ selection is not complete, the block will probably not be detected
25
+ as comments, and will have the normal "text formatting" rules
26
+ applied.
27
+ * If a comment block has leading whitespace that mixes tabs and
28
+ spaces, they will not be considered part of the same block.
29
+ * Fancy comments, like this bulleted list, aren't handled :-)
30
+ """
31
+ def __init__(self, editwin):
32
+ self.editwin = editwin
33
+
34
+ @classmethod
35
+ def reload(cls):
36
+ cls.max_width = idleConf.GetOption('extensions', 'FormatParagraph',
37
+ 'max-width', type='int', default=72)
38
+
39
+ def close(self):
40
+ self.editwin = None
41
+
42
+ def format_paragraph_event(self, event, limit=None):
43
+ """Formats paragraph to a max width specified in idleConf.
44
+
45
+ If text is selected, format_paragraph_event will start breaking lines
46
+ at the max width, starting from the beginning selection.
47
+
48
+ If no text is selected, format_paragraph_event uses the current
49
+ cursor location to determine the paragraph (lines of text surrounded
50
+ by blank lines) and formats it.
51
+
52
+ The length limit parameter is for testing with a known value.
53
+ """
54
+ limit = self.max_width if limit is None else limit
55
+ text = self.editwin.text
56
+ first, last = self.editwin.get_selection_indices()
57
+ if first and last:
58
+ data = text.get(first, last)
59
+ comment_header = get_comment_header(data)
60
+ else:
61
+ first, last, comment_header, data = \
62
+ find_paragraph(text, text.index("insert"))
63
+ if comment_header:
64
+ newdata = reformat_comment(data, limit, comment_header)
65
+ else:
66
+ newdata = reformat_paragraph(data, limit)
67
+ text.tag_remove("sel", "1.0", "end")
68
+
69
+ if newdata != data:
70
+ text.mark_set("insert", first)
71
+ text.undo_block_start()
72
+ text.delete(first, last)
73
+ text.insert(first, newdata)
74
+ text.undo_block_stop()
75
+ else:
76
+ text.mark_set("insert", last)
77
+ text.see("insert")
78
+ return "break"
79
+
80
+
81
+ FormatParagraph.reload()
82
+
83
+ def find_paragraph(text, mark):
84
+ """Returns the start/stop indices enclosing the paragraph that mark is in.
85
+
86
+ Also returns the comment format string, if any, and paragraph of text
87
+ between the start/stop indices.
88
+ """
89
+ lineno, col = map(int, mark.split("."))
90
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
91
+
92
+ # Look for start of next paragraph if the index passed in is a blank line
93
+ while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line):
94
+ lineno = lineno + 1
95
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
96
+ first_lineno = lineno
97
+ comment_header = get_comment_header(line)
98
+ comment_header_len = len(comment_header)
99
+
100
+ # Once start line found, search for end of paragraph (a blank line)
101
+ while get_comment_header(line)==comment_header and \
102
+ not is_all_white(line[comment_header_len:]):
103
+ lineno = lineno + 1
104
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
105
+ last = "%d.0" % lineno
106
+
107
+ # Search back to beginning of paragraph (first blank line before)
108
+ lineno = first_lineno - 1
109
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
110
+ while lineno > 0 and \
111
+ get_comment_header(line)==comment_header and \
112
+ not is_all_white(line[comment_header_len:]):
113
+ lineno = lineno - 1
114
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
115
+ first = "%d.0" % (lineno+1)
116
+
117
+ return first, last, comment_header, text.get(first, last)
118
+
119
+ # This should perhaps be replaced with textwrap.wrap
120
+ def reformat_paragraph(data, limit):
121
+ """Return data reformatted to specified width (limit)."""
122
+ lines = data.split("\n")
123
+ i = 0
124
+ n = len(lines)
125
+ while i < n and is_all_white(lines[i]):
126
+ i = i+1
127
+ if i >= n:
128
+ return data
129
+ indent1 = get_indent(lines[i])
130
+ if i+1 < n and not is_all_white(lines[i+1]):
131
+ indent2 = get_indent(lines[i+1])
132
+ else:
133
+ indent2 = indent1
134
+ new = lines[:i]
135
+ partial = indent1
136
+ while i < n and not is_all_white(lines[i]):
137
+ # XXX Should take double space after period (etc.) into account
138
+ words = re.split(r"(\s+)", lines[i])
139
+ for j in range(0, len(words), 2):
140
+ word = words[j]
141
+ if not word:
142
+ continue # Can happen when line ends in whitespace
143
+ if len((partial + word).expandtabs()) > limit and \
144
+ partial != indent1:
145
+ new.append(partial.rstrip())
146
+ partial = indent2
147
+ partial = partial + word + " "
148
+ if j+1 < len(words) and words[j+1] != " ":
149
+ partial = partial + " "
150
+ i = i+1
151
+ new.append(partial.rstrip())
152
+ # XXX Should reformat remaining paragraphs as well
153
+ new.extend(lines[i:])
154
+ return "\n".join(new)
155
+
156
+ def reformat_comment(data, limit, comment_header):
157
+ """Return data reformatted to specified width with comment header."""
158
+
159
+ # Remove header from the comment lines
160
+ lc = len(comment_header)
161
+ data = "\n".join(line[lc:] for line in data.split("\n"))
162
+ # Reformat to maxformatwidth chars or a 20 char width,
163
+ # whichever is greater.
164
+ format_width = max(limit - len(comment_header), 20)
165
+ newdata = reformat_paragraph(data, format_width)
166
+ # re-split and re-insert the comment header.
167
+ newdata = newdata.split("\n")
168
+ # If the block ends in a \n, we don't want the comment prefix
169
+ # inserted after it. (Im not sure it makes sense to reformat a
170
+ # comment block that is not made of complete lines, but whatever!)
171
+ # Can't think of a clean solution, so we hack away
172
+ block_suffix = ""
173
+ if not newdata[-1]:
174
+ block_suffix = "\n"
175
+ newdata = newdata[:-1]
176
+ return '\n'.join(comment_header+line for line in newdata) + block_suffix
177
+
178
+ def is_all_white(line):
179
+ """Return True if line is empty or all whitespace."""
180
+
181
+ return re.match(r"^\s*$", line) is not None
182
+
183
+ def get_indent(line):
184
+ """Return the initial space or tab indent of line."""
185
+ return re.match(r"^([ \t]*)", line).group()
186
+
187
+ def get_comment_header(line):
188
+ """Return string with leading whitespace and '#' from line or ''.
189
+
190
+ A null return indicates that the line is not a comment line. A non-
191
+ null return, such as ' #', will be used to find the other lines of
192
+ a comment block with the same indent.
193
+ """
194
+ m = re.match(r"^([ \t]*#*)", line)
195
+ if m is None: return ""
196
+ return m.group(1)
197
+
198
+
199
+ # Copied from editor.py; importing it would cause an import cycle.
200
+ _line_indent_re = re.compile(r'[ \t]*')
201
+
202
+ def get_line_indent(line, tabwidth):
203
+ """Return a line's indentation as (# chars, effective # of spaces).
204
+
205
+ The effective # of spaces is the length after properly "expanding"
206
+ the tabs into spaces, as done by str.expandtabs(tabwidth).
207
+ """
208
+ m = _line_indent_re.match(line)
209
+ return m.end(), len(m.group().expandtabs(tabwidth))
210
+
211
+
212
+ class FormatRegion:
213
+ "Format selected text (region)."
214
+
215
+ def __init__(self, editwin):
216
+ self.editwin = editwin
217
+
218
+ def get_region(self):
219
+ """Return line information about the selected text region.
220
+
221
+ If text is selected, the first and last indices will be
222
+ for the selection. If there is no text selected, the
223
+ indices will be the current cursor location.
224
+
225
+ Return a tuple containing (first index, last index,
226
+ string representation of text, list of text lines).
227
+ """
228
+ text = self.editwin.text
229
+ first, last = self.editwin.get_selection_indices()
230
+ if first and last:
231
+ head = text.index(first + " linestart")
232
+ tail = text.index(last + "-1c lineend +1c")
233
+ else:
234
+ head = text.index("insert linestart")
235
+ tail = text.index("insert lineend +1c")
236
+ chars = text.get(head, tail)
237
+ lines = chars.split("\n")
238
+ return head, tail, chars, lines
239
+
240
+ def set_region(self, head, tail, chars, lines):
241
+ """Replace the text between the given indices.
242
+
243
+ Args:
244
+ head: Starting index of text to replace.
245
+ tail: Ending index of text to replace.
246
+ chars: Expected to be string of current text
247
+ between head and tail.
248
+ lines: List of new lines to insert between head
249
+ and tail.
250
+ """
251
+ text = self.editwin.text
252
+ newchars = "\n".join(lines)
253
+ if newchars == chars:
254
+ text.bell()
255
+ return
256
+ text.tag_remove("sel", "1.0", "end")
257
+ text.mark_set("insert", head)
258
+ text.undo_block_start()
259
+ text.delete(head, tail)
260
+ text.insert(head, newchars)
261
+ text.undo_block_stop()
262
+ text.tag_add("sel", head, "insert")
263
+
264
+ def indent_region_event(self, event=None):
265
+ "Indent region by indentwidth spaces."
266
+ head, tail, chars, lines = self.get_region()
267
+ for pos in range(len(lines)):
268
+ line = lines[pos]
269
+ if line:
270
+ raw, effective = get_line_indent(line, self.editwin.tabwidth)
271
+ effective = effective + self.editwin.indentwidth
272
+ lines[pos] = self.editwin._make_blanks(effective) + line[raw:]
273
+ self.set_region(head, tail, chars, lines)
274
+ return "break"
275
+
276
+ def dedent_region_event(self, event=None):
277
+ "Dedent region by indentwidth spaces."
278
+ head, tail, chars, lines = self.get_region()
279
+ for pos in range(len(lines)):
280
+ line = lines[pos]
281
+ if line:
282
+ raw, effective = get_line_indent(line, self.editwin.tabwidth)
283
+ effective = max(effective - self.editwin.indentwidth, 0)
284
+ lines[pos] = self.editwin._make_blanks(effective) + line[raw:]
285
+ self.set_region(head, tail, chars, lines)
286
+ return "break"
287
+
288
+ def comment_region_event(self, event=None):
289
+ """Comment out each line in region.
290
+
291
+ ## is appended to the beginning of each line to comment it out.
292
+ """
293
+ head, tail, chars, lines = self.get_region()
294
+ for pos in range(len(lines) - 1):
295
+ line = lines[pos]
296
+ lines[pos] = '##' + line
297
+ self.set_region(head, tail, chars, lines)
298
+ return "break"
299
+
300
+ def uncomment_region_event(self, event=None):
301
+ """Uncomment each line in region.
302
+
303
+ Remove ## or # in the first positions of a line. If the comment
304
+ is not in the beginning position, this command will have no effect.
305
+ """
306
+ head, tail, chars, lines = self.get_region()
307
+ for pos in range(len(lines)):
308
+ line = lines[pos]
309
+ if not line:
310
+ continue
311
+ if line[:2] == '##':
312
+ line = line[2:]
313
+ elif line[:1] == '#':
314
+ line = line[1:]
315
+ lines[pos] = line
316
+ self.set_region(head, tail, chars, lines)
317
+ return "break"
318
+
319
+ def tabify_region_event(self, event=None):
320
+ "Convert leading spaces to tabs for each line in selected region."
321
+ head, tail, chars, lines = self.get_region()
322
+ tabwidth = self._asktabwidth()
323
+ if tabwidth is None:
324
+ return
325
+ for pos in range(len(lines)):
326
+ line = lines[pos]
327
+ if line:
328
+ raw, effective = get_line_indent(line, tabwidth)
329
+ ntabs, nspaces = divmod(effective, tabwidth)
330
+ lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:]
331
+ self.set_region(head, tail, chars, lines)
332
+ return "break"
333
+
334
+ def untabify_region_event(self, event=None):
335
+ "Expand tabs to spaces for each line in region."
336
+ head, tail, chars, lines = self.get_region()
337
+ tabwidth = self._asktabwidth()
338
+ if tabwidth is None:
339
+ return
340
+ for pos in range(len(lines)):
341
+ lines[pos] = lines[pos].expandtabs(tabwidth)
342
+ self.set_region(head, tail, chars, lines)
343
+ return "break"
344
+
345
+ def _asktabwidth(self):
346
+ "Return value for tab width."
347
+ return askinteger(
348
+ "Tab width",
349
+ "Columns per tab? (2-16)",
350
+ parent=self.editwin.text,
351
+ initialvalue=self.editwin.indentwidth,
352
+ minvalue=2,
353
+ maxvalue=16)
354
+
355
+
356
+ class Indents:
357
+ "Change future indents."
358
+
359
+ def __init__(self, editwin):
360
+ self.editwin = editwin
361
+
362
+ def toggle_tabs_event(self, event):
363
+ editwin = self.editwin
364
+ usetabs = editwin.usetabs
365
+ if askyesno(
366
+ "Toggle tabs",
367
+ "Turn tabs " + ("on", "off")[usetabs] +
368
+ "?\nIndent width " +
369
+ ("will be", "remains at")[usetabs] + " 8." +
370
+ "\n Note: a tab is always 8 columns",
371
+ parent=editwin.text):
372
+ editwin.usetabs = not usetabs
373
+ # Try to prevent inconsistent indentation.
374
+ # User must change indent width manually after using tabs.
375
+ editwin.indentwidth = 8
376
+ return "break"
377
+
378
+ def change_indentwidth_event(self, event):
379
+ editwin = self.editwin
380
+ new = askinteger(
381
+ "Indent width",
382
+ "New indent width (2-16)\n(Always use 8 when using tabs)",
383
+ parent=editwin.text,
384
+ initialvalue=editwin.indentwidth,
385
+ minvalue=2,
386
+ maxvalue=16)
387
+ if new and new != editwin.indentwidth and not editwin.usetabs:
388
+ editwin.indentwidth = new
389
+ return "break"
390
+
391
+
392
+ class Rstrip: # 'Strip Trailing Whitespace" on "Format" menu.
393
+ def __init__(self, editwin):
394
+ self.editwin = editwin
395
+
396
+ def do_rstrip(self, event=None):
397
+ text = self.editwin.text
398
+ undo = self.editwin.undo
399
+ undo.undo_block_start()
400
+
401
+ end_line = int(float(text.index('end')))
402
+ for cur in range(1, end_line):
403
+ txt = text.get('%i.0' % cur, '%i.end' % cur)
404
+ raw = len(txt)
405
+ cut = len(txt.rstrip())
406
+ # Since text.delete() marks file as changed, even if not,
407
+ # only call it when needed to actually delete something.
408
+ if cut < raw:
409
+ text.delete('%i.%i' % (cur, cut), '%i.end' % cur)
410
+
411
+ if (text.get('end-2c') == '\n' # File ends with at least 1 newline;
412
+ and not hasattr(self.editwin, 'interp')): # & is not Shell.
413
+ # Delete extra user endlines.
414
+ while (text.index('end-1c') > '1.0' # Stop if file empty.
415
+ and text.get('end-3c') == '\n'):
416
+ text.delete('end-3c')
417
+ # Because tk indexes are slice indexes and never raise,
418
+ # a file with only newlines will be emptied.
419
+ # patchcheck.py does the same.
420
+
421
+ undo.undo_block_stop()
422
+
423
+
424
+ if __name__ == "__main__":
425
+ from unittest import main
426
+ main('idlelib.idle_test.test_format', verbosity=2, exit=False)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/grep.py ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Grep dialog for Find in Files functionality.
2
+
3
+ Inherits from SearchDialogBase for GUI and uses searchengine
4
+ to prepare search pattern.
5
+ """
6
+ import fnmatch
7
+ import os
8
+ import sys
9
+
10
+ from tkinter import StringVar, BooleanVar
11
+ from tkinter.ttk import Checkbutton # Frame imported in ...Base
12
+
13
+ from idlelib.searchbase import SearchDialogBase
14
+ from idlelib import searchengine
15
+
16
+ # Importing OutputWindow here fails due to import loop
17
+ # EditorWindow -> GrepDialog -> OutputWindow -> EditorWindow
18
+
19
+
20
+ def grep(text, io=None, flist=None):
21
+ """Open the Find in Files dialog.
22
+
23
+ Module-level function to access the singleton GrepDialog
24
+ instance and open the dialog. If text is selected, it is
25
+ used as the search phrase; otherwise, the previous entry
26
+ is used.
27
+
28
+ Args:
29
+ text: Text widget that contains the selected text for
30
+ default search phrase.
31
+ io: iomenu.IOBinding instance with default path to search.
32
+ flist: filelist.FileList instance for OutputWindow parent.
33
+ """
34
+ root = text._root()
35
+ engine = searchengine.get(root)
36
+ if not hasattr(engine, "_grepdialog"):
37
+ engine._grepdialog = GrepDialog(root, engine, flist)
38
+ dialog = engine._grepdialog
39
+ searchphrase = text.get("sel.first", "sel.last")
40
+ dialog.open(text, searchphrase, io)
41
+
42
+
43
+ def walk_error(msg):
44
+ "Handle os.walk error."
45
+ print(msg)
46
+
47
+
48
+ def findfiles(folder, pattern, recursive):
49
+ """Generate file names in dir that match pattern.
50
+
51
+ Args:
52
+ folder: Root directory to search.
53
+ pattern: File pattern to match.
54
+ recursive: True to include subdirectories.
55
+ """
56
+ for dirpath, _, filenames in os.walk(folder, onerror=walk_error):
57
+ yield from (os.path.join(dirpath, name)
58
+ for name in filenames
59
+ if fnmatch.fnmatch(name, pattern))
60
+ if not recursive:
61
+ break
62
+
63
+
64
+ class GrepDialog(SearchDialogBase):
65
+ "Dialog for searching multiple files."
66
+
67
+ title = "Find in Files Dialog"
68
+ icon = "Grep"
69
+ needwrapbutton = 0
70
+
71
+ def __init__(self, root, engine, flist):
72
+ """Create search dialog for searching for a phrase in the file system.
73
+
74
+ Uses SearchDialogBase as the basis for the GUI and a
75
+ searchengine instance to prepare the search.
76
+
77
+ Attributes:
78
+ flist: filelist.Filelist instance for OutputWindow parent.
79
+ globvar: String value of Entry widget for path to search.
80
+ globent: Entry widget for globvar. Created in
81
+ create_entries().
82
+ recvar: Boolean value of Checkbutton widget for
83
+ traversing through subdirectories.
84
+ """
85
+ super().__init__(root, engine)
86
+ self.flist = flist
87
+ self.globvar = StringVar(root)
88
+ self.recvar = BooleanVar(root)
89
+
90
+ def open(self, text, searchphrase, io=None):
91
+ """Make dialog visible on top of others and ready to use.
92
+
93
+ Extend the SearchDialogBase open() to set the initial value
94
+ for globvar.
95
+
96
+ Args:
97
+ text: Multicall object containing the text information.
98
+ searchphrase: String phrase to search.
99
+ io: iomenu.IOBinding instance containing file path.
100
+ """
101
+ SearchDialogBase.open(self, text, searchphrase)
102
+ if io:
103
+ path = io.filename or ""
104
+ else:
105
+ path = ""
106
+ dir, base = os.path.split(path)
107
+ head, tail = os.path.splitext(base)
108
+ if not tail:
109
+ tail = ".py"
110
+ self.globvar.set(os.path.join(dir, "*" + tail))
111
+
112
+ def create_entries(self):
113
+ "Create base entry widgets and add widget for search path."
114
+ SearchDialogBase.create_entries(self)
115
+ self.globent = self.make_entry("In files:", self.globvar)[0]
116
+
117
+ def create_other_buttons(self):
118
+ "Add check button to recurse down subdirectories."
119
+ btn = Checkbutton(
120
+ self.make_frame()[0], variable=self.recvar,
121
+ text="Recurse down subdirectories")
122
+ btn.pack(side="top", fill="both")
123
+
124
+ def create_command_buttons(self):
125
+ "Create base command buttons and add button for Search Files."
126
+ SearchDialogBase.create_command_buttons(self)
127
+ self.make_button("Search Files", self.default_command, isdef=True)
128
+
129
+ def default_command(self, event=None):
130
+ """Grep for search pattern in file path. The default command is bound
131
+ to <Return>.
132
+
133
+ If entry values are populated, set OutputWindow as stdout
134
+ and perform search. The search dialog is closed automatically
135
+ when the search begins.
136
+ """
137
+ prog = self.engine.getprog()
138
+ if not prog:
139
+ return
140
+ path = self.globvar.get()
141
+ if not path:
142
+ self.top.bell()
143
+ return
144
+ from idlelib.outwin import OutputWindow # leave here!
145
+ save = sys.stdout
146
+ try:
147
+ sys.stdout = OutputWindow(self.flist)
148
+ self.grep_it(prog, path)
149
+ finally:
150
+ sys.stdout = save
151
+
152
+ def grep_it(self, prog, path):
153
+ """Search for prog within the lines of the files in path.
154
+
155
+ For the each file in the path directory, open the file and
156
+ search each line for the matching pattern. If the pattern is
157
+ found, write the file and line information to stdout (which
158
+ is an OutputWindow).
159
+
160
+ Args:
161
+ prog: The compiled, cooked search pattern.
162
+ path: String containing the search path.
163
+ """
164
+ folder, filepat = os.path.split(path)
165
+ if not folder:
166
+ folder = os.curdir
167
+ filelist = sorted(findfiles(folder, filepat, self.recvar.get()))
168
+ self.close()
169
+ pat = self.engine.getpat()
170
+ print(f"Searching {pat!r} in {path} ...")
171
+ hits = 0
172
+ try:
173
+ for fn in filelist:
174
+ try:
175
+ with open(fn, errors='replace') as f:
176
+ for lineno, line in enumerate(f, 1):
177
+ if line[-1:] == '\n':
178
+ line = line[:-1]
179
+ if prog.search(line):
180
+ sys.stdout.write(f"{fn}: {lineno}: {line}\n")
181
+ hits += 1
182
+ except OSError as msg:
183
+ print(msg)
184
+ print(f"Hits found: {hits}\n(Hint: right-click to open locations.)"
185
+ if hits else "No hits.")
186
+ except AttributeError:
187
+ # Tk window has been closed, OutputWindow.text = None,
188
+ # so in OW.write, OW.text.insert fails.
189
+ pass
190
+
191
+
192
+ def _grep_dialog(parent): # htest #
193
+ from tkinter import Toplevel, Text, SEL, END
194
+ from tkinter.ttk import Frame, Button
195
+ from idlelib.pyshell import PyShellFileList
196
+
197
+ top = Toplevel(parent)
198
+ top.title("Test GrepDialog")
199
+ x, y = map(int, parent.geometry().split('+')[1:])
200
+ top.geometry(f"+{x}+{y + 175}")
201
+
202
+ flist = PyShellFileList(top)
203
+ frame = Frame(top)
204
+ frame.pack()
205
+ text = Text(frame, height=5)
206
+ text.pack()
207
+
208
+ def show_grep_dialog():
209
+ text.tag_add(SEL, "1.0", END)
210
+ grep(text, flist=flist)
211
+ text.tag_remove(SEL, "1.0", END)
212
+
213
+ button = Button(frame, text="Show GrepDialog", command=show_grep_dialog)
214
+ button.pack()
215
+
216
+ if __name__ == "__main__":
217
+ from unittest import main
218
+ main('idlelib.idle_test.test_grep', verbosity=2, exit=False)
219
+
220
+ from idlelib.idle_test.htest import run
221
+ run(_grep_dialog)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/help.html ADDED
@@ -0,0 +1,1014 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <!DOCTYPE html>
3
+
4
+ <html>
5
+ <head>
6
+ <meta charset="utf-8" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <title>IDLE &#8212; Python 3.10.0a6 documentation</title>
9
+ <link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
10
+ <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
11
+
12
+ <script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
13
+ <script src="../_static/jquery.js"></script>
14
+ <script src="../_static/underscore.js"></script>
15
+ <script src="../_static/doctools.js"></script>
16
+ <script src="../_static/language_data.js"></script>
17
+
18
+ <script src="../_static/sidebar.js"></script>
19
+
20
+ <link rel="search" type="application/opensearchdescription+xml"
21
+ title="Search within Python 3.10.0a6 documentation"
22
+ href="../_static/opensearch.xml"/>
23
+ <link rel="author" title="About these documents" href="../about.html" />
24
+ <link rel="index" title="Index" href="../genindex.html" />
25
+ <link rel="search" title="Search" href="../search.html" />
26
+ <link rel="copyright" title="Copyright" href="../copyright.html" />
27
+ <link rel="next" title="Other Graphical User Interface Packages" href="othergui.html" />
28
+ <link rel="prev" title="tkinter.tix — Extension widgets for Tk" href="tkinter.tix.html" />
29
+ <link rel="canonical" href="https://docs.python.org/3/library/idle.html" />
30
+
31
+
32
+
33
+
34
+
35
+ <style>
36
+ @media only screen {
37
+ table.full-width-table {
38
+ width: 100%;
39
+ }
40
+ }
41
+ </style>
42
+
43
+ <link rel="shortcut icon" type="image/png" href="../_static/py.png" />
44
+
45
+ <script type="text/javascript" src="../_static/copybutton.js"></script>
46
+
47
+
48
+
49
+
50
+ </head><body>
51
+
52
+ <div class="related" role="navigation" aria-label="related navigation">
53
+ <h3>Navigation</h3>
54
+ <ul>
55
+ <li class="right" style="margin-right: 10px">
56
+ <a href="../genindex.html" title="General Index"
57
+ accesskey="I">index</a></li>
58
+ <li class="right" >
59
+ <a href="../py-modindex.html" title="Python Module Index"
60
+ >modules</a> |</li>
61
+ <li class="right" >
62
+ <a href="othergui.html" title="Other Graphical User Interface Packages"
63
+ accesskey="N">next</a> |</li>
64
+ <li class="right" >
65
+ <a href="tkinter.tix.html" title="tkinter.tix — Extension widgets for Tk"
66
+ accesskey="P">previous</a> |</li>
67
+
68
+ <li><img src="../_static/py.png" alt=""
69
+ style="vertical-align: middle; margin-top: -1px"/></li>
70
+ <li><a href="https://www.python.org/">Python</a> &#187;</li>
71
+
72
+
73
+ <li id="cpython-language-and-version">
74
+ <a href="../index.html">3.10.0a6 Documentation</a> &#187;
75
+ </li>
76
+
77
+ <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
78
+ <li class="nav-item nav-item-2"><a href="tk.html" accesskey="U">Graphical User Interfaces with Tk</a> &#187;</li>
79
+ <li class="nav-item nav-item-this"><a href="">IDLE</a></li>
80
+ <li class="right">
81
+
82
+
83
+ <div class="inline-search" style="display: none" role="search">
84
+ <form class="inline-search" action="../search.html" method="get">
85
+ <input placeholder="Quick search" type="text" name="q" />
86
+ <input type="submit" value="Go" />
87
+ <input type="hidden" name="check_keywords" value="yes" />
88
+ <input type="hidden" name="area" value="default" />
89
+ </form>
90
+ </div>
91
+ <script type="text/javascript">$('.inline-search').show(0);</script>
92
+ |
93
+ </li>
94
+
95
+ </ul>
96
+ </div>
97
+
98
+ <div class="document">
99
+ <div class="documentwrapper">
100
+ <div class="bodywrapper">
101
+ <div class="body" role="main">
102
+
103
+ <div class="section" id="idle">
104
+ <span id="id1"></span><h1>IDLE<a class="headerlink" href="#idle" title="Permalink to this headline">¶</a></h1>
105
+ <p><strong>Source code:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/master/Lib/idlelib/">Lib/idlelib/</a></p>
106
+ <hr class="docutils" id="index-0" />
107
+ <p>IDLE is Python’s Integrated Development and Learning Environment.</p>
108
+ <p>IDLE has the following features:</p>
109
+ <ul class="simple">
110
+ <li><p>coded in 100% pure Python, using the <a class="reference internal" href="tkinter.html#module-tkinter" title="tkinter: Interface to Tcl/Tk for graphical user interfaces"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter</span></code></a> GUI toolkit</p></li>
111
+ <li><p>cross-platform: works mostly the same on Windows, Unix, and macOS</p></li>
112
+ <li><p>Python shell window (interactive interpreter) with colorizing
113
+ of code input, output, and error messages</p></li>
114
+ <li><p>multi-window text editor with multiple undo, Python colorizing,
115
+ smart indent, call tips, auto completion, and other features</p></li>
116
+ <li><p>search within any window, replace within editor windows, and search
117
+ through multiple files (grep)</p></li>
118
+ <li><p>debugger with persistent breakpoints, stepping, and viewing
119
+ of global and local namespaces</p></li>
120
+ <li><p>configuration, browsers, and other dialogs</p></li>
121
+ </ul>
122
+ <div class="section" id="menus">
123
+ <h2>Menus<a class="headerlink" href="#menus" title="Permalink to this headline">¶</a></h2>
124
+ <p>IDLE has two main window types, the Shell window and the Editor window. It is
125
+ possible to have multiple editor windows simultaneously. On Windows and
126
+ Linux, each has its own top menu. Each menu documented below indicates
127
+ which window type it is associated with.</p>
128
+ <p>Output windows, such as used for Edit =&gt; Find in Files, are a subtype of editor
129
+ window. They currently have the same top menu but a different
130
+ default title and context menu.</p>
131
+ <p>On macOS, there is one application menu. It dynamically changes according
132
+ to the window currently selected. It has an IDLE menu, and some entries
133
+ described below are moved around to conform to Apple guidelines.</p>
134
+ <div class="section" id="file-menu-shell-and-editor">
135
+ <h3>File menu (Shell and Editor)<a class="headerlink" href="#file-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
136
+ <dl class="simple">
137
+ <dt>New File</dt><dd><p>Create a new file editing window.</p>
138
+ </dd>
139
+ <dt>Open…</dt><dd><p>Open an existing file with an Open dialog.</p>
140
+ </dd>
141
+ <dt>Recent Files</dt><dd><p>Open a list of recent files. Click one to open it.</p>
142
+ </dd>
143
+ <dt>Open Module…</dt><dd><p>Open an existing module (searches sys.path).</p>
144
+ </dd>
145
+ </dl>
146
+ <dl class="simple" id="index-1">
147
+ <dt>Class Browser</dt><dd><p>Show functions, classes, and methods in the current Editor file in a
148
+ tree structure. In the shell, open a module first.</p>
149
+ </dd>
150
+ <dt>Path Browser</dt><dd><p>Show sys.path directories, modules, functions, classes and methods in a
151
+ tree structure.</p>
152
+ </dd>
153
+ <dt>Save</dt><dd><p>Save the current window to the associated file, if there is one. Windows
154
+ that have been changed since being opened or last saved have a * before
155
+ and after the window title. If there is no associated file,
156
+ do Save As instead.</p>
157
+ </dd>
158
+ <dt>Save As…</dt><dd><p>Save the current window with a Save As dialog. The file saved becomes the
159
+ new associated file for the window.</p>
160
+ </dd>
161
+ <dt>Save Copy As…</dt><dd><p>Save the current window to different file without changing the associated
162
+ file.</p>
163
+ </dd>
164
+ <dt>Print Window</dt><dd><p>Print the current window to the default printer.</p>
165
+ </dd>
166
+ <dt>Close</dt><dd><p>Close the current window (ask to save if unsaved).</p>
167
+ </dd>
168
+ <dt>Exit</dt><dd><p>Close all windows and quit IDLE (ask to save unsaved windows).</p>
169
+ </dd>
170
+ </dl>
171
+ </div>
172
+ <div class="section" id="edit-menu-shell-and-editor">
173
+ <h3>Edit menu (Shell and Editor)<a class="headerlink" href="#edit-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
174
+ <dl class="simple">
175
+ <dt>Undo</dt><dd><p>Undo the last change to the current window. A maximum of 1000 changes may
176
+ be undone.</p>
177
+ </dd>
178
+ <dt>Redo</dt><dd><p>Redo the last undone change to the current window.</p>
179
+ </dd>
180
+ <dt>Cut</dt><dd><p>Copy selection into the system-wide clipboard; then delete the selection.</p>
181
+ </dd>
182
+ <dt>Copy</dt><dd><p>Copy selection into the system-wide clipboard.</p>
183
+ </dd>
184
+ <dt>Paste</dt><dd><p>Insert contents of the system-wide clipboard into the current window.</p>
185
+ </dd>
186
+ </dl>
187
+ <p>The clipboard functions are also available in context menus.</p>
188
+ <dl class="simple">
189
+ <dt>Select All</dt><dd><p>Select the entire contents of the current window.</p>
190
+ </dd>
191
+ <dt>Find…</dt><dd><p>Open a search dialog with many options</p>
192
+ </dd>
193
+ <dt>Find Again</dt><dd><p>Repeat the last search, if there is one.</p>
194
+ </dd>
195
+ <dt>Find Selection</dt><dd><p>Search for the currently selected string, if there is one.</p>
196
+ </dd>
197
+ <dt>Find in Files…</dt><dd><p>Open a file search dialog. Put results in a new output window.</p>
198
+ </dd>
199
+ <dt>Replace…</dt><dd><p>Open a search-and-replace dialog.</p>
200
+ </dd>
201
+ <dt>Go to Line</dt><dd><p>Move the cursor to the beginning of the line requested and make that
202
+ line visible. A request past the end of the file goes to the end.
203
+ Clear any selection and update the line and column status.</p>
204
+ </dd>
205
+ <dt>Show Completions</dt><dd><p>Open a scrollable list allowing selection of existing names. See
206
+ <a class="reference internal" href="#completions"><span class="std std-ref">Completions</span></a> in the Editing and navigation section below.</p>
207
+ </dd>
208
+ <dt>Expand Word</dt><dd><p>Expand a prefix you have typed to match a full word in the same window;
209
+ repeat to get a different expansion.</p>
210
+ </dd>
211
+ <dt>Show call tip</dt><dd><p>After an unclosed parenthesis for a function, open a small window with
212
+ function parameter hints. See <a class="reference internal" href="#calltips"><span class="std std-ref">Calltips</span></a> in the
213
+ Editing and navigation section below.</p>
214
+ </dd>
215
+ <dt>Show surrounding parens</dt><dd><p>Highlight the surrounding parenthesis.</p>
216
+ </dd>
217
+ </dl>
218
+ </div>
219
+ <div class="section" id="format-menu-editor-window-only">
220
+ <span id="format-menu"></span><h3>Format menu (Editor window only)<a class="headerlink" href="#format-menu-editor-window-only" title="Permalink to this headline">¶</a></h3>
221
+ <dl class="simple">
222
+ <dt>Indent Region</dt><dd><p>Shift selected lines right by the indent width (default 4 spaces).</p>
223
+ </dd>
224
+ <dt>Dedent Region</dt><dd><p>Shift selected lines left by the indent width (default 4 spaces).</p>
225
+ </dd>
226
+ <dt>Comment Out Region</dt><dd><p>Insert ## in front of selected lines.</p>
227
+ </dd>
228
+ <dt>Uncomment Region</dt><dd><p>Remove leading # or ## from selected lines.</p>
229
+ </dd>
230
+ <dt>Tabify Region</dt><dd><p>Turn <em>leading</em> stretches of spaces into tabs. (Note: We recommend using
231
+ 4 space blocks to indent Python code.)</p>
232
+ </dd>
233
+ <dt>Untabify Region</dt><dd><p>Turn <em>all</em> tabs into the correct number of spaces.</p>
234
+ </dd>
235
+ <dt>Toggle Tabs</dt><dd><p>Open a dialog to switch between indenting with spaces and tabs.</p>
236
+ </dd>
237
+ <dt>New Indent Width</dt><dd><p>Open a dialog to change indent width. The accepted default by the Python
238
+ community is 4 spaces.</p>
239
+ </dd>
240
+ <dt>Format Paragraph</dt><dd><p>Reformat the current blank-line-delimited paragraph in comment block or
241
+ multiline string or selected line in a string. All lines in the
242
+ paragraph will be formatted to less than N columns, where N defaults to 72.</p>
243
+ </dd>
244
+ <dt>Strip trailing whitespace</dt><dd><p>Remove trailing space and other whitespace characters after the last
245
+ non-whitespace character of a line by applying str.rstrip to each line,
246
+ including lines within multiline strings. Except for Shell windows,
247
+ remove extra newlines at the end of the file.</p>
248
+ </dd>
249
+ </dl>
250
+ </div>
251
+ <div class="section" id="run-menu-editor-window-only">
252
+ <span id="index-2"></span><h3>Run menu (Editor window only)<a class="headerlink" href="#run-menu-editor-window-only" title="Permalink to this headline">¶</a></h3>
253
+ <dl class="simple" id="run-module">
254
+ <dt>Run Module</dt><dd><p>Do <a class="reference internal" href="#check-module"><span class="std std-ref">Check Module</span></a>. If no error, restart the shell to clean the
255
+ environment, then execute the module. Output is displayed in the Shell
256
+ window. Note that output requires use of <code class="docutils literal notranslate"><span class="pre">print</span></code> or <code class="docutils literal notranslate"><span class="pre">write</span></code>.
257
+ When execution is complete, the Shell retains focus and displays a prompt.
258
+ At this point, one may interactively explore the result of execution.
259
+ This is similar to executing a file with <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-i</span> <span class="pre">file</span></code> at a command
260
+ line.</p>
261
+ </dd>
262
+ </dl>
263
+ <dl class="simple" id="run-custom">
264
+ <dt>Run… Customized</dt><dd><p>Same as <a class="reference internal" href="#run-module"><span class="std std-ref">Run Module</span></a>, but run the module with customized
265
+ settings. <em>Command Line Arguments</em> extend <a class="reference internal" href="sys.html#sys.argv" title="sys.argv"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.argv</span></code></a> as if passed
266
+ on a command line. The module can be run in the Shell without restarting.</p>
267
+ </dd>
268
+ </dl>
269
+ <dl class="simple" id="check-module">
270
+ <dt>Check Module</dt><dd><p>Check the syntax of the module currently open in the Editor window. If the
271
+ module has not been saved IDLE will either prompt the user to save or
272
+ autosave, as selected in the General tab of the Idle Settings dialog. If
273
+ there is a syntax error, the approximate location is indicated in the
274
+ Editor window.</p>
275
+ </dd>
276
+ </dl>
277
+ <dl class="simple" id="python-shell">
278
+ <dt>Python Shell</dt><dd><p>Open or wake up the Python Shell window.</p>
279
+ </dd>
280
+ </dl>
281
+ </div>
282
+ <div class="section" id="shell-menu-shell-window-only">
283
+ <h3>Shell menu (Shell window only)<a class="headerlink" href="#shell-menu-shell-window-only" title="Permalink to this headline">¶</a></h3>
284
+ <dl class="simple">
285
+ <dt>View Last Restart</dt><dd><p>Scroll the shell window to the last Shell restart.</p>
286
+ </dd>
287
+ <dt>Restart Shell</dt><dd><p>Restart the shell to clean the environment and reset display and exception handling.</p>
288
+ </dd>
289
+ <dt>Previous History</dt><dd><p>Cycle through earlier commands in history which match the current entry.</p>
290
+ </dd>
291
+ <dt>Next History</dt><dd><p>Cycle through later commands in history which match the current entry.</p>
292
+ </dd>
293
+ <dt>Interrupt Execution</dt><dd><p>Stop a running program.</p>
294
+ </dd>
295
+ </dl>
296
+ </div>
297
+ <div class="section" id="debug-menu-shell-window-only">
298
+ <h3>Debug menu (Shell window only)<a class="headerlink" href="#debug-menu-shell-window-only" title="Permalink to this headline">¶</a></h3>
299
+ <dl class="simple">
300
+ <dt>Go to File/Line</dt><dd><p>Look on the current line. with the cursor, and the line above for a filename
301
+ and line number. If found, open the file if not already open, and show the
302
+ line. Use this to view source lines referenced in an exception traceback
303
+ and lines found by Find in Files. Also available in the context menu of
304
+ the Shell window and Output windows.</p>
305
+ </dd>
306
+ </dl>
307
+ <dl class="simple" id="index-3">
308
+ <dt>Debugger (toggle)</dt><dd><p>When activated, code entered in the Shell or run from an Editor will run
309
+ under the debugger. In the Editor, breakpoints can be set with the context
310
+ menu. This feature is still incomplete and somewhat experimental.</p>
311
+ </dd>
312
+ <dt>Stack Viewer</dt><dd><p>Show the stack traceback of the last exception in a tree widget, with
313
+ access to locals and globals.</p>
314
+ </dd>
315
+ <dt>Auto-open Stack Viewer</dt><dd><p>Toggle automatically opening the stack viewer on an unhandled exception.</p>
316
+ </dd>
317
+ </dl>
318
+ </div>
319
+ <div class="section" id="options-menu-shell-and-editor">
320
+ <h3>Options menu (Shell and Editor)<a class="headerlink" href="#options-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
321
+ <dl class="simple">
322
+ <dt>Configure IDLE</dt><dd><p>Open a configuration dialog and change preferences for the following:
323
+ fonts, indentation, keybindings, text color themes, startup windows and
324
+ size, additional help sources, and extensions. On macOS, open the
325
+ configuration dialog by selecting Preferences in the application
326
+ menu. For more details, see
327
+ <a class="reference internal" href="#preferences"><span class="std std-ref">Setting preferences</span></a> under Help and preferences.</p>
328
+ </dd>
329
+ </dl>
330
+ <p>Most configuration options apply to all windows or all future windows.
331
+ The option items below only apply to the active window.</p>
332
+ <dl class="simple">
333
+ <dt>Show/Hide Code Context (Editor Window only)</dt><dd><p>Open a pane at the top of the edit window which shows the block context
334
+ of the code which has scrolled above the top of the window. See
335
+ <a class="reference internal" href="#code-context"><span class="std std-ref">Code Context</span></a> in the Editing and Navigation section
336
+ below.</p>
337
+ </dd>
338
+ <dt>Show/Hide Line Numbers (Editor Window only)</dt><dd><p>Open a column to the left of the edit window which shows the number
339
+ of each line of text. The default is off, which may be changed in the
340
+ preferences (see <a class="reference internal" href="#preferences"><span class="std std-ref">Setting preferences</span></a>).</p>
341
+ </dd>
342
+ <dt>Zoom/Restore Height</dt><dd><p>Toggles the window between normal size and maximum height. The initial size
343
+ defaults to 40 lines by 80 chars unless changed on the General tab of the
344
+ Configure IDLE dialog. The maximum height for a screen is determined by
345
+ momentarily maximizing a window the first time one is zoomed on the screen.
346
+ Changing screen settings may invalidate the saved height. This toggle has
347
+ no effect when a window is maximized.</p>
348
+ </dd>
349
+ </dl>
350
+ </div>
351
+ <div class="section" id="window-menu-shell-and-editor">
352
+ <h3>Window menu (Shell and Editor)<a class="headerlink" href="#window-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
353
+ <p>Lists the names of all open windows; select one to bring it to the foreground
354
+ (deiconifying it if necessary).</p>
355
+ </div>
356
+ <div class="section" id="help-menu-shell-and-editor">
357
+ <h3>Help menu (Shell and Editor)<a class="headerlink" href="#help-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
358
+ <dl class="simple">
359
+ <dt>About IDLE</dt><dd><p>Display version, copyright, license, credits, and more.</p>
360
+ </dd>
361
+ <dt>IDLE Help</dt><dd><p>Display this IDLE document, detailing the menu options, basic editing and
362
+ navigation, and other tips.</p>
363
+ </dd>
364
+ <dt>Python Docs</dt><dd><p>Access local Python documentation, if installed, or start a web browser
365
+ and open docs.python.org showing the latest Python documentation.</p>
366
+ </dd>
367
+ <dt>Turtle Demo</dt><dd><p>Run the turtledemo module with example Python code and turtle drawings.</p>
368
+ </dd>
369
+ </dl>
370
+ <p>Additional help sources may be added here with the Configure IDLE dialog under
371
+ the General tab. See the <a class="reference internal" href="#help-sources"><span class="std std-ref">Help sources</span></a> subsection below
372
+ for more on Help menu choices.</p>
373
+ </div>
374
+ <div class="section" id="context-menus">
375
+ <span id="index-4"></span><h3>Context Menus<a class="headerlink" href="#context-menus" title="Permalink to this headline">¶</a></h3>
376
+ <p>Open a context menu by right-clicking in a window (Control-click on macOS).
377
+ Context menus have the standard clipboard functions also on the Edit menu.</p>
378
+ <dl class="simple">
379
+ <dt>Cut</dt><dd><p>Copy selection into the system-wide clipboard; then delete the selection.</p>
380
+ </dd>
381
+ <dt>Copy</dt><dd><p>Copy selection into the system-wide clipboard.</p>
382
+ </dd>
383
+ <dt>Paste</dt><dd><p>Insert contents of the system-wide clipboard into the current window.</p>
384
+ </dd>
385
+ </dl>
386
+ <p>Editor windows also have breakpoint functions. Lines with a breakpoint set are
387
+ specially marked. Breakpoints only have an effect when running under the
388
+ debugger. Breakpoints for a file are saved in the user’s <code class="docutils literal notranslate"><span class="pre">.idlerc</span></code>
389
+ directory.</p>
390
+ <dl class="simple">
391
+ <dt>Set Breakpoint</dt><dd><p>Set a breakpoint on the current line.</p>
392
+ </dd>
393
+ <dt>Clear Breakpoint</dt><dd><p>Clear the breakpoint on that line.</p>
394
+ </dd>
395
+ </dl>
396
+ <p>Shell and Output windows also have the following.</p>
397
+ <dl class="simple">
398
+ <dt>Go to file/line</dt><dd><p>Same as in Debug menu.</p>
399
+ </dd>
400
+ </dl>
401
+ <p>The Shell window also has an output squeezing facility explained in the <em>Python
402
+ Shell window</em> subsection below.</p>
403
+ <dl class="simple">
404
+ <dt>Squeeze</dt><dd><p>If the cursor is over an output line, squeeze all the output between
405
+ the code above and the prompt below down to a ‘Squeezed text’ label.</p>
406
+ </dd>
407
+ </dl>
408
+ </div>
409
+ </div>
410
+ <div class="section" id="editing-and-navigation">
411
+ <span id="id2"></span><h2>Editing and navigation<a class="headerlink" href="#editing-and-navigation" title="Permalink to this headline">¶</a></h2>
412
+ <div class="section" id="editor-windows">
413
+ <h3>Editor windows<a class="headerlink" href="#editor-windows" title="Permalink to this headline">¶</a></h3>
414
+ <p>IDLE may open editor windows when it starts, depending on settings
415
+ and how you start IDLE. Thereafter, use the File menu. There can be only
416
+ one open editor window for a given file.</p>
417
+ <p>The title bar contains the name of the file, the full path, and the version
418
+ of Python and IDLE running the window. The status bar contains the line
419
+ number (‘Ln’) and column number (‘Col’). Line numbers start with 1;
420
+ column numbers with 0.</p>
421
+ <p>IDLE assumes that files with a known .py* extension contain Python code
422
+ and that other files do not. Run Python code with the Run menu.</p>
423
+ </div>
424
+ <div class="section" id="key-bindings">
425
+ <h3>Key bindings<a class="headerlink" href="#key-bindings" title="Permalink to this headline">¶</a></h3>
426
+ <p>In this section, ‘C’ refers to the <kbd class="kbd docutils literal notranslate">Control</kbd> key on Windows and Unix and
427
+ the <kbd class="kbd docutils literal notranslate">Command</kbd> key on macOS.</p>
428
+ <ul>
429
+ <li><p><kbd class="kbd docutils literal notranslate">Backspace</kbd> deletes to the left; <kbd class="kbd docutils literal notranslate">Del</kbd> deletes to the right</p></li>
430
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Backspace</kbd></kbd> delete word left; <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Del</kbd></kbd> delete word to the right</p></li>
431
+ <li><p>Arrow keys and <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Page</kbd> <kbd class="kbd docutils literal notranslate">Up</kbd></kbd>/<kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Page</kbd> <kbd class="kbd docutils literal notranslate">Down</kbd></kbd> to move around</p></li>
432
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">LeftArrow</kbd></kbd> and <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">RightArrow</kbd></kbd> moves by words</p></li>
433
+ <li><p><kbd class="kbd docutils literal notranslate">Home</kbd>/<kbd class="kbd docutils literal notranslate">End</kbd> go to begin/end of line</p></li>
434
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Home</kbd></kbd>/<kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">End</kbd></kbd> go to begin/end of file</p></li>
435
+ <li><p>Some useful Emacs bindings are inherited from Tcl/Tk:</p>
436
+ <blockquote>
437
+ <div><ul class="simple">
438
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">a</kbd></kbd> beginning of line</p></li>
439
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">e</kbd></kbd> end of line</p></li>
440
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">k</kbd></kbd> kill line (but doesn’t put it in clipboard)</p></li>
441
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">l</kbd></kbd> center window around the insertion point</p></li>
442
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">b</kbd></kbd> go backward one character without deleting (usually you can
443
+ also use the cursor key for this)</p></li>
444
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">f</kbd></kbd> go forward one character without deleting (usually you can
445
+ also use the cursor key for this)</p></li>
446
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd> go up one line (usually you can also use the cursor key for
447
+ this)</p></li>
448
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">d</kbd></kbd> delete next character</p></li>
449
+ </ul>
450
+ </div></blockquote>
451
+ </li>
452
+ </ul>
453
+ <p>Standard keybindings (like <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">c</kbd></kbd> to copy and <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">v</kbd></kbd> to paste)
454
+ may work. Keybindings are selected in the Configure IDLE dialog.</p>
455
+ </div>
456
+ <div class="section" id="automatic-indentation">
457
+ <h3>Automatic indentation<a class="headerlink" href="#automatic-indentation" title="Permalink to this headline">¶</a></h3>
458
+ <p>After a block-opening statement, the next line is indented by 4 spaces (in the
459
+ Python Shell window by one tab). After certain keywords (break, return etc.)
460
+ the next line is dedented. In leading indentation, <kbd class="kbd docutils literal notranslate">Backspace</kbd> deletes up
461
+ to 4 spaces if they are there. <kbd class="kbd docutils literal notranslate">Tab</kbd> inserts spaces (in the Python
462
+ Shell window one tab), number depends on Indent width. Currently, tabs
463
+ are restricted to four spaces due to Tcl/Tk limitations.</p>
464
+ <p>See also the indent/dedent region commands on the
465
+ <a class="reference internal" href="#format-menu"><span class="std std-ref">Format menu</span></a>.</p>
466
+ </div>
467
+ <div class="section" id="completions">
468
+ <span id="id3"></span><h3>Completions<a class="headerlink" href="#completions" title="Permalink to this headline">¶</a></h3>
469
+ <p>Completions are supplied, when requested and available, for module
470
+ names, attributes of classes or functions, or filenames. Each request
471
+ method displays a completion box with existing names. (See tab
472
+ completions below for an exception.) For any box, change the name
473
+ being completed and the item highlighted in the box by
474
+ typing and deleting characters; by hitting <kbd class="kbd docutils literal notranslate">Up</kbd>, <kbd class="kbd docutils literal notranslate">Down</kbd>,
475
+ <kbd class="kbd docutils literal notranslate">PageUp</kbd>, <kbd class="kbd docutils literal notranslate">PageDown</kbd>, <kbd class="kbd docutils literal notranslate">Home</kbd>, and <kbd class="kbd docutils literal notranslate">End</kbd> keys;
476
+ and by a single click within the box. Close the box with <kbd class="kbd docutils literal notranslate">Escape</kbd>,
477
+ <kbd class="kbd docutils literal notranslate">Enter</kbd>, and double <kbd class="kbd docutils literal notranslate">Tab</kbd> keys or clicks outside the box.
478
+ A double click within the box selects and closes.</p>
479
+ <p>One way to open a box is to type a key character and wait for a
480
+ predefined interval. This defaults to 2 seconds; customize it
481
+ in the settings dialog. (To prevent auto popups, set the delay to a
482
+ large number of milliseconds, such as 100000000.) For imported module
483
+ names or class or function attributes, type ‘.’.
484
+ For filenames in the root directory, type <a class="reference internal" href="os.html#os.sep" title="os.sep"><code class="xref py py-data docutils literal notranslate"><span class="pre">os.sep</span></code></a> or
485
+ <a class="reference internal" href="os.html#os.altsep" title="os.altsep"><code class="xref py py-data docutils literal notranslate"><span class="pre">os.altsep</span></code></a> immediately after an opening quote. (On Windows,
486
+ one can specify a drive first.) Move into subdirectories by typing a
487
+ directory name and a separator.</p>
488
+ <p>Instead of waiting, or after a box is closed, open a completion box
489
+ immediately with Show Completions on the Edit menu. The default hot
490
+ key is <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">space</kbd></kbd>. If one types a prefix for the desired name
491
+ before opening the box, the first match or near miss is made visible.
492
+ The result is the same as if one enters a prefix
493
+ after the box is displayed. Show Completions after a quote completes
494
+ filenames in the current directory instead of a root directory.</p>
495
+ <p>Hitting <kbd class="kbd docutils literal notranslate">Tab</kbd> after a prefix usually has the same effect as Show
496
+ Completions. (With no prefix, it indents.) However, if there is only
497
+ one match to the prefix, that match is immediately added to the editor
498
+ text without opening a box.</p>
499
+ <p>Invoking ‘Show Completions’, or hitting <kbd class="kbd docutils literal notranslate">Tab</kbd> after a prefix,
500
+ outside of a string and without a preceding ‘.’ opens a box with
501
+ keywords, builtin names, and available module-level names.</p>
502
+ <p>When editing code in an editor (as oppose to Shell), increase the
503
+ available module-level names by running your code
504
+ and not restarting the Shell thereafter. This is especially useful
505
+ after adding imports at the top of a file. This also increases
506
+ possible attribute completions.</p>
507
+ <p>Completion boxes intially exclude names beginning with ‘_’ or, for
508
+ modules, not included in ‘__all__’. The hidden names can be accessed
509
+ by typing ‘_’ after ‘.’, either before or after the box is opened.</p>
510
+ </div>
511
+ <div class="section" id="calltips">
512
+ <span id="id4"></span><h3>Calltips<a class="headerlink" href="#calltips" title="Permalink to this headline">¶</a></h3>
513
+ <p>A calltip is shown automatically when one types <kbd class="kbd docutils literal notranslate">(</kbd> after the name
514
+ of an <em>accessible</em> function. A function name expression may include
515
+ dots and subscripts. A calltip remains until it is clicked, the cursor
516
+ is moved out of the argument area, or <kbd class="kbd docutils literal notranslate">)</kbd> is typed. Whenever the
517
+ cursor is in the argument part of a definition, select Edit and “Show
518
+ Call Tip” on the menu or enter its shortcut to display a calltip.</p>
519
+ <p>The calltip consists of the function’s signature and docstring up to
520
+ the latter’s first blank line or the fifth non-blank line. (Some builtin
521
+ functions lack an accessible signature.) A ‘/’ or ‘*’ in the signature
522
+ indicates that the preceding or following arguments are passed by
523
+ position or name (keyword) only. Details are subject to change.</p>
524
+ <p>In Shell, the accessible functions depends on what modules have been
525
+ imported into the user process, including those imported by Idle itself,
526
+ and which definitions have been run, all since the last restart.</p>
527
+ <p>For example, restart the Shell and enter <code class="docutils literal notranslate"><span class="pre">itertools.count(</span></code>. A calltip
528
+ appears because Idle imports itertools into the user process for its own
529
+ use. (This could change.) Enter <code class="docutils literal notranslate"><span class="pre">turtle.write(</span></code> and nothing appears.
530
+ Idle does not itself import turtle. The menu entry and shortcut also do
531
+ nothing. Enter <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">turtle</span></code>. Thereafter, <code class="docutils literal notranslate"><span class="pre">turtle.write(</span></code>
532
+ will display a calltip.</p>
533
+ <p>In an editor, import statements have no effect until one runs the file.
534
+ One might want to run a file after writing import statements, after
535
+ adding function definitions, or after opening an existing file.</p>
536
+ </div>
537
+ <div class="section" id="code-context">
538
+ <span id="id5"></span><h3>Code Context<a class="headerlink" href="#code-context" title="Permalink to this headline">¶</a></h3>
539
+ <p>Within an editor window containing Python code, code context can be toggled
540
+ in order to show or hide a pane at the top of the window. When shown, this
541
+ pane freezes the opening lines for block code, such as those beginning with
542
+ <code class="docutils literal notranslate"><span class="pre">class</span></code>, <code class="docutils literal notranslate"><span class="pre">def</span></code>, or <code class="docutils literal notranslate"><span class="pre">if</span></code> keywords, that would have otherwise scrolled
543
+ out of view. The size of the pane will be expanded and contracted as needed
544
+ to show the all current levels of context, up to the maximum number of
545
+ lines defined in the Configure IDLE dialog (which defaults to 15). If there
546
+ are no current context lines and the feature is toggled on, a single blank
547
+ line will display. Clicking on a line in the context pane will move that
548
+ line to the top of the editor.</p>
549
+ <p>The text and background colors for the context pane can be configured under
550
+ the Highlights tab in the Configure IDLE dialog.</p>
551
+ </div>
552
+ <div class="section" id="python-shell-window">
553
+ <h3>Python Shell window<a class="headerlink" href="#python-shell-window" title="Permalink to this headline">¶</a></h3>
554
+ <p>With IDLE’s Shell, one enters, edits, and recalls complete statements.
555
+ Most consoles and terminals only work with a single physical line at a time.</p>
556
+ <p>When one pastes code into Shell, it is not compiled and possibly executed
557
+ until one hits <kbd class="kbd docutils literal notranslate">Return</kbd>. One may edit pasted code first.
558
+ If one pastes more that one statement into Shell, the result will be a
559
+ <a class="reference internal" href="exceptions.html#SyntaxError" title="SyntaxError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">SyntaxError</span></code></a> when multiple statements are compiled as if they were one.</p>
560
+ <p>The editing features described in previous subsections work when entering
561
+ code interactively. IDLE’s Shell window also responds to the following keys.</p>
562
+ <ul>
563
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">c</kbd></kbd> interrupts executing command</p></li>
564
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">d</kbd></kbd> sends end-of-file; closes window if typed at a <code class="docutils literal notranslate"><span class="pre">&gt;&gt;&gt;</span></code> prompt</p></li>
565
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">/</kbd></kbd> (Expand word) is also useful to reduce typing</p>
566
+ <p>Command history</p>
567
+ <ul class="simple">
568
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd> retrieves previous command matching what you have typed. On
569
+ macOS use <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd>.</p></li>
570
+ <li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">n</kbd></kbd> retrieves next. On macOS use <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">n</kbd></kbd>.</p></li>
571
+ <li><p><kbd class="kbd docutils literal notranslate">Return</kbd> while on any previous command retrieves that command</p></li>
572
+ </ul>
573
+ </li>
574
+ </ul>
575
+ </div>
576
+ <div class="section" id="text-colors">
577
+ <h3>Text colors<a class="headerlink" href="#text-colors" title="Permalink to this headline">¶</a></h3>
578
+ <p>Idle defaults to black on white text, but colors text with special meanings.
579
+ For the shell, these are shell output, shell error, user output, and
580
+ user error. For Python code, at the shell prompt or in an editor, these are
581
+ keywords, builtin class and function names, names following <code class="docutils literal notranslate"><span class="pre">class</span></code> and
582
+ <code class="docutils literal notranslate"><span class="pre">def</span></code>, strings, and comments. For any text window, these are the cursor (when
583
+ present), found text (when possible), and selected text.</p>
584
+ <p>Text coloring is done in the background, so uncolorized text is occasionally
585
+ visible. To change the color scheme, use the Configure IDLE dialog
586
+ Highlighting tab. The marking of debugger breakpoint lines in the editor and
587
+ text in popups and dialogs is not user-configurable.</p>
588
+ </div>
589
+ </div>
590
+ <div class="section" id="startup-and-code-execution">
591
+ <h2>Startup and code execution<a class="headerlink" href="#startup-and-code-execution" title="Permalink to this headline">¶</a></h2>
592
+ <p>Upon startup with the <code class="docutils literal notranslate"><span class="pre">-s</span></code> option, IDLE will execute the file referenced by
593
+ the environment variables <span class="target" id="index-5"></span><code class="xref std std-envvar docutils literal notranslate"><span class="pre">IDLESTARTUP</span></code> or <span class="target" id="index-6"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONSTARTUP"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONSTARTUP</span></code></a>.
594
+ IDLE first checks for <code class="docutils literal notranslate"><span class="pre">IDLESTARTUP</span></code>; if <code class="docutils literal notranslate"><span class="pre">IDLESTARTUP</span></code> is present the file
595
+ referenced is run. If <code class="docutils literal notranslate"><span class="pre">IDLESTARTUP</span></code> is not present, IDLE checks for
596
+ <code class="docutils literal notranslate"><span class="pre">PYTHONSTARTUP</span></code>. Files referenced by these environment variables are
597
+ convenient places to store functions that are used frequently from the IDLE
598
+ shell, or for executing import statements to import common modules.</p>
599
+ <p>In addition, <code class="docutils literal notranslate"><span class="pre">Tk</span></code> also loads a startup file if it is present. Note that the
600
+ Tk file is loaded unconditionally. This additional file is <code class="docutils literal notranslate"><span class="pre">.Idle.py</span></code> and is
601
+ looked for in the user’s home directory. Statements in this file will be
602
+ executed in the Tk namespace, so this file is not useful for importing
603
+ functions to be used from IDLE’s Python shell.</p>
604
+ <div class="section" id="command-line-usage">
605
+ <h3>Command line usage<a class="headerlink" href="#command-line-usage" title="Permalink to this headline">¶</a></h3>
606
+ <div class="highlight-none notranslate"><div class="highlight"><pre><span></span>idle.py [-c command] [-d] [-e] [-h] [-i] [-r file] [-s] [-t title] [-] [arg] ...
607
+
608
+ -c command run command in the shell window
609
+ -d enable debugger and open shell window
610
+ -e open editor window
611
+ -h print help message with legal combinations and exit
612
+ -i open shell window
613
+ -r file run file in shell window
614
+ -s run $IDLESTARTUP or $PYTHONSTARTUP first, in shell window
615
+ -t title set title of shell window
616
+ - run stdin in shell (- must be last option before args)
617
+ </pre></div>
618
+ </div>
619
+ <p>If there are arguments:</p>
620
+ <ul class="simple">
621
+ <li><p>If <code class="docutils literal notranslate"><span class="pre">-</span></code>, <code class="docutils literal notranslate"><span class="pre">-c</span></code>, or <code class="docutils literal notranslate"><span class="pre">r</span></code> is used, all arguments are placed in
622
+ <code class="docutils literal notranslate"><span class="pre">sys.argv[1:...]</span></code> and <code class="docutils literal notranslate"><span class="pre">sys.argv[0]</span></code> is set to <code class="docutils literal notranslate"><span class="pre">''</span></code>, <code class="docutils literal notranslate"><span class="pre">'-c'</span></code>,
623
+ or <code class="docutils literal notranslate"><span class="pre">'-r'</span></code>. No editor window is opened, even if that is the default
624
+ set in the Options dialog.</p></li>
625
+ <li><p>Otherwise, arguments are files opened for editing and
626
+ <code class="docutils literal notranslate"><span class="pre">sys.argv</span></code> reflects the arguments passed to IDLE itself.</p></li>
627
+ </ul>
628
+ </div>
629
+ <div class="section" id="startup-failure">
630
+ <h3>Startup failure<a class="headerlink" href="#startup-failure" title="Permalink to this headline">¶</a></h3>
631
+ <p>IDLE uses a socket to communicate between the IDLE GUI process and the user
632
+ code execution process. A connection must be established whenever the Shell
633
+ starts or restarts. (The latter is indicated by a divider line that says
634
+ ‘RESTART’). If the user process fails to connect to the GUI process, it
635
+ usually displays a <code class="docutils literal notranslate"><span class="pre">Tk</span></code> error box with a ‘cannot connect’ message
636
+ that directs the user here. It then exits.</p>
637
+ <p>One specific connection failure on Unix systems results from
638
+ misconfigured masquerading rules somewhere in a system’s network setup.
639
+ When IDLE is started from a terminal, one will see a message starting
640
+ with <code class="docutils literal notranslate"><span class="pre">**</span> <span class="pre">Invalid</span> <span class="pre">host:</span></code>.
641
+ The valid value is <code class="docutils literal notranslate"><span class="pre">127.0.0.1</span> <span class="pre">(idlelib.rpc.LOCALHOST)</span></code>.
642
+ One can diagnose with <code class="docutils literal notranslate"><span class="pre">tcpconnect</span> <span class="pre">-irv</span> <span class="pre">127.0.0.1</span> <span class="pre">6543</span></code> in one
643
+ terminal window and <code class="docutils literal notranslate"><span class="pre">tcplisten</span> <span class="pre">&lt;same</span> <span class="pre">args&gt;</span></code> in another.</p>
644
+ <p>A common cause of failure is a user-written file with the same name as a
645
+ standard library module, such as <em>random.py</em> and <em>tkinter.py</em>. When such a
646
+ file is located in the same directory as a file that is about to be run,
647
+ IDLE cannot import the stdlib file. The current fix is to rename the
648
+ user file.</p>
649
+ <p>Though less common than in the past, an antivirus or firewall program may
650
+ stop the connection. If the program cannot be taught to allow the
651
+ connection, then it must be turned off for IDLE to work. It is safe to
652
+ allow this internal connection because no data is visible on external
653
+ ports. A similar problem is a network mis-configuration that blocks
654
+ connections.</p>
655
+ <p>Python installation issues occasionally stop IDLE: multiple versions can
656
+ clash, or a single installation might need admin access. If one undo the
657
+ clash, or cannot or does not want to run as admin, it might be easiest to
658
+ completely remove Python and start over.</p>
659
+ <p>A zombie pythonw.exe process could be a problem. On Windows, use Task
660
+ Manager to check for one and stop it if there is. Sometimes a restart
661
+ initiated by a program crash or Keyboard Interrupt (control-C) may fail
662
+ to connect. Dismissing the error box or using Restart Shell on the Shell
663
+ menu may fix a temporary problem.</p>
664
+ <p>When IDLE first starts, it attempts to read user configuration files in
665
+ <code class="docutils literal notranslate"><span class="pre">~/.idlerc/</span></code> (~ is one’s home directory). If there is a problem, an error
666
+ message should be displayed. Leaving aside random disk glitches, this can
667
+ be prevented by never editing the files by hand. Instead, use the
668
+ configuration dialog, under Options. Once there is an error in a user
669
+ configuration file, the best solution may be to delete it and start over
670
+ with the settings dialog.</p>
671
+ <p>If IDLE quits with no message, and it was not started from a console, try
672
+ starting it from a console or terminal (<code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">idlelib</span></code>) and see if
673
+ this results in an error message.</p>
674
+ <p>On Unix-based systems with tcl/tk older than <code class="docutils literal notranslate"><span class="pre">8.6.11</span></code> (see
675
+ <code class="docutils literal notranslate"><span class="pre">About</span> <span class="pre">IDLE</span></code>) certain characters of certain fonts can cause
676
+ a tk failure with a message to the terminal. This can happen either
677
+ if one starts IDLE to edit a file with such a character or later
678
+ when entering such a character. If one cannot upgrade tcl/tk,
679
+ then re-configure IDLE to use a font that works better.</p>
680
+ </div>
681
+ <div class="section" id="running-user-code">
682
+ <h3>Running user code<a class="headerlink" href="#running-user-code" title="Permalink to this headline">¶</a></h3>
683
+ <p>With rare exceptions, the result of executing Python code with IDLE is
684
+ intended to be the same as executing the same code by the default method,
685
+ directly with Python in a text-mode system console or terminal window.
686
+ However, the different interface and operation occasionally affect
687
+ visible results. For instance, <code class="docutils literal notranslate"><span class="pre">sys.modules</span></code> starts with more entries,
688
+ and <code class="docutils literal notranslate"><span class="pre">threading.activeCount()</span></code> returns 2 instead of 1.</p>
689
+ <p>By default, IDLE runs user code in a separate OS process rather than in
690
+ the user interface process that runs the shell and editor. In the execution
691
+ process, it replaces <code class="docutils literal notranslate"><span class="pre">sys.stdin</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code>, and <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code>
692
+ with objects that get input from and send output to the Shell window.
693
+ The original values stored in <code class="docutils literal notranslate"><span class="pre">sys.__stdin__</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.__stdout__</span></code>, and
694
+ <code class="docutils literal notranslate"><span class="pre">sys.__stderr__</span></code> are not touched, but may be <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p>
695
+ <p>Sending print output from one process to a text widget in another is
696
+ slower than printing to a system terminal in the same process.
697
+ This has the most effect when printing multiple arguments, as the string
698
+ for each argument, each separator, the newline are sent separately.
699
+ For development, this is usually not a problem, but if one wants to
700
+ print faster in IDLE, format and join together everything one wants
701
+ displayed together and then print a single string. Both format strings
702
+ and <a class="reference internal" href="stdtypes.html#str.join" title="str.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.join()</span></code></a> can help combine fields and lines.</p>
703
+ <p>IDLE’s standard stream replacements are not inherited by subprocesses
704
+ created in the execution process, whether directly by user code or by
705
+ modules such as multiprocessing. If such subprocess use <code class="docutils literal notranslate"><span class="pre">input</span></code> from
706
+ sys.stdin or <code class="docutils literal notranslate"><span class="pre">print</span></code> or <code class="docutils literal notranslate"><span class="pre">write</span></code> to sys.stdout or sys.stderr,
707
+ IDLE should be started in a command line window. The secondary subprocess
708
+ will then be attached to that window for input and output.</p>
709
+ <p>If <code class="docutils literal notranslate"><span class="pre">sys</span></code> is reset by user code, such as with <code class="docutils literal notranslate"><span class="pre">importlib.reload(sys)</span></code>,
710
+ IDLE’s changes are lost and input from the keyboard and output to the screen
711
+ will not work correctly.</p>
712
+ <p>When Shell has the focus, it controls the keyboard and screen. This is
713
+ normally transparent, but functions that directly access the keyboard
714
+ and screen will not work. These include system-specific functions that
715
+ determine whether a key has been pressed and if so, which.</p>
716
+ <p>The IDLE code running in the execution process adds frames to the call stack
717
+ that would not be there otherwise. IDLE wraps <code class="docutils literal notranslate"><span class="pre">sys.getrecursionlimit</span></code> and
718
+ <code class="docutils literal notranslate"><span class="pre">sys.setrecursionlimit</span></code> to reduce the effect of the additional stack
719
+ frames.</p>
720
+ <p>When user code raises SystemExit either directly or by calling sys.exit,
721
+ IDLE returns to a Shell prompt instead of exiting.</p>
722
+ </div>
723
+ <div class="section" id="user-output-in-shell">
724
+ <h3>User output in Shell<a class="headerlink" href="#user-output-in-shell" title="Permalink to this headline">¶</a></h3>
725
+ <p>When a program outputs text, the result is determined by the
726
+ corresponding output device. When IDLE executes user code, <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code>
727
+ and <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code> are connected to the display area of IDLE’s Shell. Some of
728
+ its features are inherited from the underlying Tk Text widget. Others
729
+ are programmed additions. Where it matters, Shell is designed for development
730
+ rather than production runs.</p>
731
+ <p>For instance, Shell never throws away output. A program that sends unlimited
732
+ output to Shell will eventually fill memory, resulting in a memory error.
733
+ In contrast, some system text windows only keep the last n lines of output.
734
+ A Windows console, for instance, keeps a user-settable 1 to 9999 lines,
735
+ with 300 the default.</p>
736
+ <p>A Tk Text widget, and hence IDLE’s Shell, displays characters (codepoints) in
737
+ the BMP (Basic Multilingual Plane) subset of Unicode. Which characters are
738
+ displayed with a proper glyph and which with a replacement box depends on the
739
+ operating system and installed fonts. Tab characters cause the following text
740
+ to begin after the next tab stop. (They occur every 8 ‘characters’). Newline
741
+ characters cause following text to appear on a new line. Other control
742
+ characters are ignored or displayed as a space, box, or something else,
743
+ depending on the operating system and font. (Moving the text cursor through
744
+ such output with arrow keys may exhibit some surprising spacing behavior.)</p>
745
+ <div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">s</span> <span class="o">=</span> <span class="s1">&#39;a</span><span class="se">\t</span><span class="s1">b</span><span class="se">\a</span><span class="s1">&lt;</span><span class="se">\x02</span><span class="s1">&gt;&lt;</span><span class="se">\r</span><span class="s1">&gt;</span><span class="se">\b</span><span class="s1">c</span><span class="se">\n</span><span class="s1">d&#39;</span> <span class="c1"># Enter 22 chars.</span>
746
+ <span class="gp">&gt;&gt;&gt; </span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
747
+ <span class="go">14</span>
748
+ <span class="gp">&gt;&gt;&gt; </span><span class="n">s</span> <span class="c1"># Display repr(s)</span>
749
+ <span class="go">&#39;a\tb\x07&lt;\x02&gt;&lt;\r&gt;\x08c\nd&#39;</span>
750
+ <span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="c1"># Display s as is.</span>
751
+ <span class="go"># Result varies by OS and font. Try it.</span>
752
+ </pre></div>
753
+ </div>
754
+ <p>The <code class="docutils literal notranslate"><span class="pre">repr</span></code> function is used for interactive echo of expression
755
+ values. It returns an altered version of the input string in which
756
+ control codes, some BMP codepoints, and all non-BMP codepoints are
757
+ replaced with escape codes. As demonstrated above, it allows one to
758
+ identify the characters in a string, regardless of how they are displayed.</p>
759
+ <p>Normal and error output are generally kept separate (on separate lines)
760
+ from code input and each other. They each get different highlight colors.</p>
761
+ <p>For SyntaxError tracebacks, the normal ‘^’ marking where the error was
762
+ detected is replaced by coloring the text with an error highlight.
763
+ When code run from a file causes other exceptions, one may right click
764
+ on a traceback line to jump to the corresponding line in an IDLE editor.
765
+ The file will be opened if necessary.</p>
766
+ <p>Shell has a special facility for squeezing output lines down to a
767
+ ‘Squeezed text’ label. This is done automatically
768
+ for output over N lines (N = 50 by default).
769
+ N can be changed in the PyShell section of the General
770
+ page of the Settings dialog. Output with fewer lines can be squeezed by
771
+ right clicking on the output. This can be useful lines long enough to slow
772
+ down scrolling.</p>
773
+ <p>Squeezed output is expanded in place by double-clicking the label.
774
+ It can also be sent to the clipboard or a separate view window by
775
+ right-clicking the label.</p>
776
+ </div>
777
+ <div class="section" id="developing-tkinter-applications">
778
+ <h3>Developing tkinter applications<a class="headerlink" href="#developing-tkinter-applications" title="Permalink to this headline">¶</a></h3>
779
+ <p>IDLE is intentionally different from standard Python in order to
780
+ facilitate development of tkinter programs. Enter <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">tkinter</span> <span class="pre">as</span> <span class="pre">tk;</span>
781
+ <span class="pre">root</span> <span class="pre">=</span> <span class="pre">tk.Tk()</span></code> in standard Python and nothing appears. Enter the same
782
+ in IDLE and a tk window appears. In standard Python, one must also enter
783
+ <code class="docutils literal notranslate"><span class="pre">root.update()</span></code> to see the window. IDLE does the equivalent in the
784
+ background, about 20 times a second, which is about every 50 milliseconds.
785
+ Next enter <code class="docutils literal notranslate"><span class="pre">b</span> <span class="pre">=</span> <span class="pre">tk.Button(root,</span> <span class="pre">text='button');</span> <span class="pre">b.pack()</span></code>. Again,
786
+ nothing visibly changes in standard Python until one enters <code class="docutils literal notranslate"><span class="pre">root.update()</span></code>.</p>
787
+ <p>Most tkinter programs run <code class="docutils literal notranslate"><span class="pre">root.mainloop()</span></code>, which usually does not
788
+ return until the tk app is destroyed. If the program is run with
789
+ <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-i</span></code> or from an IDLE editor, a <code class="docutils literal notranslate"><span class="pre">&gt;&gt;&gt;</span></code> shell prompt does not
790
+ appear until <code class="docutils literal notranslate"><span class="pre">mainloop()</span></code> returns, at which time there is nothing left
791
+ to interact with.</p>
792
+ <p>When running a tkinter program from an IDLE editor, one can comment out
793
+ the mainloop call. One then gets a shell prompt immediately and can
794
+ interact with the live application. One just has to remember to
795
+ re-enable the mainloop call when running in standard Python.</p>
796
+ </div>
797
+ <div class="section" id="running-without-a-subprocess">
798
+ <h3>Running without a subprocess<a class="headerlink" href="#running-without-a-subprocess" title="Permalink to this headline">¶</a></h3>
799
+ <p>By default, IDLE executes user code in a separate subprocess via a socket,
800
+ which uses the internal loopback interface. This connection is not
801
+ externally visible and no data is sent to or received from the Internet.
802
+ If firewall software complains anyway, you can ignore it.</p>
803
+ <p>If the attempt to make the socket connection fails, Idle will notify you.
804
+ Such failures are sometimes transient, but if persistent, the problem
805
+ may be either a firewall blocking the connection or misconfiguration of
806
+ a particular system. Until the problem is fixed, one can run Idle with
807
+ the -n command line switch.</p>
808
+ <p>If IDLE is started with the -n command line switch it will run in a
809
+ single process and will not create the subprocess which runs the RPC
810
+ Python execution server. This can be useful if Python cannot create
811
+ the subprocess or the RPC socket interface on your platform. However,
812
+ in this mode user code is not isolated from IDLE itself. Also, the
813
+ environment is not restarted when Run/Run Module (F5) is selected. If
814
+ your code has been modified, you must reload() the affected modules and
815
+ re-import any specific items (e.g. from foo import baz) if the changes
816
+ are to take effect. For these reasons, it is preferable to run IDLE
817
+ with the default subprocess if at all possible.</p>
818
+ <div class="deprecated">
819
+ <p><span class="versionmodified deprecated">Deprecated since version 3.4.</span></p>
820
+ </div>
821
+ </div>
822
+ </div>
823
+ <div class="section" id="help-and-preferences">
824
+ <h2>Help and preferences<a class="headerlink" href="#help-and-preferences" title="Permalink to this headline">¶</a></h2>
825
+ <div class="section" id="help-sources">
826
+ <span id="id6"></span><h3>Help sources<a class="headerlink" href="#help-sources" title="Permalink to this headline">¶</a></h3>
827
+ <p>Help menu entry “IDLE Help” displays a formatted html version of the
828
+ IDLE chapter of the Library Reference. The result, in a read-only
829
+ tkinter text window, is close to what one sees in a web browser.
830
+ Navigate through the text with a mousewheel,
831
+ the scrollbar, or up and down arrow keys held down.
832
+ Or click the TOC (Table of Contents) button and select a section
833
+ header in the opened box.</p>
834
+ <p>Help menu entry “Python Docs” opens the extensive sources of help,
835
+ including tutorials, available at <code class="docutils literal notranslate"><span class="pre">docs.python.org/x.y</span></code>, where ‘x.y’
836
+ is the currently running Python version. If your system
837
+ has an off-line copy of the docs (this may be an installation option),
838
+ that will be opened instead.</p>
839
+ <p>Selected URLs can be added or removed from the help menu at any time using the
840
+ General tab of the Configure IDLE dialog.</p>
841
+ </div>
842
+ <div class="section" id="setting-preferences">
843
+ <span id="preferences"></span><h3>Setting preferences<a class="headerlink" href="#setting-preferences" title="Permalink to this headline">¶</a></h3>
844
+ <p>The font preferences, highlighting, keys, and general preferences can be
845
+ changed via Configure IDLE on the Option menu.
846
+ Non-default user settings are saved in a <code class="docutils literal notranslate"><span class="pre">.idlerc</span></code> directory in the user’s
847
+ home directory. Problems caused by bad user configuration files are solved
848
+ by editing or deleting one or more of the files in <code class="docutils literal notranslate"><span class="pre">.idlerc</span></code>.</p>
849
+ <p>On the Font tab, see the text sample for the effect of font face and size
850
+ on multiple characters in multiple languages. Edit the sample to add
851
+ other characters of personal interest. Use the sample to select
852
+ monospaced fonts. If particular characters have problems in Shell or an
853
+ editor, add them to the top of the sample and try changing first size
854
+ and then font.</p>
855
+ <p>On the Highlights and Keys tab, select a built-in or custom color theme
856
+ and key set. To use a newer built-in color theme or key set with older
857
+ IDLEs, save it as a new custom theme or key set and it well be accessible
858
+ to older IDLEs.</p>
859
+ </div>
860
+ <div class="section" id="idle-on-macos">
861
+ <h3>IDLE on macOS<a class="headerlink" href="#idle-on-macos" title="Permalink to this headline">¶</a></h3>
862
+ <p>Under System Preferences: Dock, one can set “Prefer tabs when opening
863
+ documents” to “Always”. This setting is not compatible with the tk/tkinter
864
+ GUI framework used by IDLE, and it breaks a few IDLE features.</p>
865
+ </div>
866
+ <div class="section" id="extensions">
867
+ <h3>Extensions<a class="headerlink" href="#extensions" title="Permalink to this headline">¶</a></h3>
868
+ <p>IDLE contains an extension facility. Preferences for extensions can be
869
+ changed with the Extensions tab of the preferences dialog. See the
870
+ beginning of config-extensions.def in the idlelib directory for further
871
+ information. The only current default extension is zzdummy, an example
872
+ also used for testing.</p>
873
+ </div>
874
+ </div>
875
+ </div>
876
+
877
+
878
+ <div class="clearer"></div>
879
+ </div>
880
+ </div>
881
+ </div>
882
+ <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
883
+ <div class="sphinxsidebarwrapper">
884
+ <h3><a href="../contents.html">Table of Contents</a></h3>
885
+ <ul>
886
+ <li><a class="reference internal" href="#">IDLE</a><ul>
887
+ <li><a class="reference internal" href="#menus">Menus</a><ul>
888
+ <li><a class="reference internal" href="#file-menu-shell-and-editor">File menu (Shell and Editor)</a></li>
889
+ <li><a class="reference internal" href="#edit-menu-shell-and-editor">Edit menu (Shell and Editor)</a></li>
890
+ <li><a class="reference internal" href="#format-menu-editor-window-only">Format menu (Editor window only)</a></li>
891
+ <li><a class="reference internal" href="#run-menu-editor-window-only">Run menu (Editor window only)</a></li>
892
+ <li><a class="reference internal" href="#shell-menu-shell-window-only">Shell menu (Shell window only)</a></li>
893
+ <li><a class="reference internal" href="#debug-menu-shell-window-only">Debug menu (Shell window only)</a></li>
894
+ <li><a class="reference internal" href="#options-menu-shell-and-editor">Options menu (Shell and Editor)</a></li>
895
+ <li><a class="reference internal" href="#window-menu-shell-and-editor">Window menu (Shell and Editor)</a></li>
896
+ <li><a class="reference internal" href="#help-menu-shell-and-editor">Help menu (Shell and Editor)</a></li>
897
+ <li><a class="reference internal" href="#context-menus">Context Menus</a></li>
898
+ </ul>
899
+ </li>
900
+ <li><a class="reference internal" href="#editing-and-navigation">Editing and navigation</a><ul>
901
+ <li><a class="reference internal" href="#editor-windows">Editor windows</a></li>
902
+ <li><a class="reference internal" href="#key-bindings">Key bindings</a></li>
903
+ <li><a class="reference internal" href="#automatic-indentation">Automatic indentation</a></li>
904
+ <li><a class="reference internal" href="#completions">Completions</a></li>
905
+ <li><a class="reference internal" href="#calltips">Calltips</a></li>
906
+ <li><a class="reference internal" href="#code-context">Code Context</a></li>
907
+ <li><a class="reference internal" href="#python-shell-window">Python Shell window</a></li>
908
+ <li><a class="reference internal" href="#text-colors">Text colors</a></li>
909
+ </ul>
910
+ </li>
911
+ <li><a class="reference internal" href="#startup-and-code-execution">Startup and code execution</a><ul>
912
+ <li><a class="reference internal" href="#command-line-usage">Command line usage</a></li>
913
+ <li><a class="reference internal" href="#startup-failure">Startup failure</a></li>
914
+ <li><a class="reference internal" href="#running-user-code">Running user code</a></li>
915
+ <li><a class="reference internal" href="#user-output-in-shell">User output in Shell</a></li>
916
+ <li><a class="reference internal" href="#developing-tkinter-applications">Developing tkinter applications</a></li>
917
+ <li><a class="reference internal" href="#running-without-a-subprocess">Running without a subprocess</a></li>
918
+ </ul>
919
+ </li>
920
+ <li><a class="reference internal" href="#help-and-preferences">Help and preferences</a><ul>
921
+ <li><a class="reference internal" href="#help-sources">Help sources</a></li>
922
+ <li><a class="reference internal" href="#setting-preferences">Setting preferences</a></li>
923
+ <li><a class="reference internal" href="#idle-on-macos">IDLE on macOS</a></li>
924
+ <li><a class="reference internal" href="#extensions">Extensions</a></li>
925
+ </ul>
926
+ </li>
927
+ </ul>
928
+ </li>
929
+ </ul>
930
+
931
+ <h4>Previous topic</h4>
932
+ <p class="topless"><a href="tkinter.tix.html"
933
+ title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.tix</span></code> — Extension widgets for Tk</a></p>
934
+ <h4>Next topic</h4>
935
+ <p class="topless"><a href="othergui.html"
936
+ title="next chapter">Other Graphical User Interface Packages</a></p>
937
+ <div role="note" aria-label="source link">
938
+ <h3>This Page</h3>
939
+ <ul class="this-page-menu">
940
+ <li><a href="../bugs.html">Report a Bug</a></li>
941
+ <li>
942
+ <a href="https://github.com/python/cpython/blob/master/Doc/library/idle.rst"
943
+ rel="nofollow">Show Source
944
+ </a>
945
+ </li>
946
+ </ul>
947
+ </div>
948
+ </div>
949
+ </div>
950
+ <div class="clearer"></div>
951
+ </div>
952
+ <div class="related" role="navigation" aria-label="related navigation">
953
+ <h3>Navigation</h3>
954
+ <ul>
955
+ <li class="right" style="margin-right: 10px">
956
+ <a href="../genindex.html" title="General Index"
957
+ >index</a></li>
958
+ <li class="right" >
959
+ <a href="../py-modindex.html" title="Python Module Index"
960
+ >modules</a> |</li>
961
+ <li class="right" >
962
+ <a href="othergui.html" title="Other Graphical User Interface Packages"
963
+ >next</a> |</li>
964
+ <li class="right" >
965
+ <a href="tkinter.tix.html" title="tkinter.tix — Extension widgets for Tk"
966
+ >previous</a> |</li>
967
+
968
+ <li><img src="../_static/py.png" alt=""
969
+ style="vertical-align: middle; margin-top: -1px"/></li>
970
+ <li><a href="https://www.python.org/">Python</a> &#187;</li>
971
+
972
+
973
+ <li id="cpython-language-and-version">
974
+ <a href="../index.html">3.10.0a6 Documentation</a> &#187;
975
+ </li>
976
+
977
+ <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
978
+ <li class="nav-item nav-item-2"><a href="tk.html" >Graphical User Interfaces with Tk</a> &#187;</li>
979
+ <li class="nav-item nav-item-this"><a href="">IDLE</a></li>
980
+ <li class="right">
981
+
982
+
983
+ <div class="inline-search" style="display: none" role="search">
984
+ <form class="inline-search" action="../search.html" method="get">
985
+ <input placeholder="Quick search" type="text" name="q" />
986
+ <input type="submit" value="Go" />
987
+ <input type="hidden" name="check_keywords" value="yes" />
988
+ <input type="hidden" name="area" value="default" />
989
+ </form>
990
+ </div>
991
+ <script type="text/javascript">$('.inline-search').show(0);</script>
992
+ |
993
+ </li>
994
+
995
+ </ul>
996
+ </div>
997
+ <div class="footer">
998
+ &copy; <a href="../copyright.html">Copyright</a> 2001-2021, Python Software Foundation.
999
+ <br />
1000
+
1001
+ The Python Software Foundation is a non-profit corporation.
1002
+ <a href="https://www.python.org/psf/donations/">Please donate.</a>
1003
+ <br />
1004
+ <br />
1005
+
1006
+ Last updated on Mar 29, 2021.
1007
+ <a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
1008
+ <br />
1009
+
1010
+ Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
1011
+ </div>
1012
+
1013
+ </body>
1014
+ </html>
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/help.py ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ help.py: Implement the Idle help menu.
2
+ Contents are subject to revision at any time, without notice.
3
+
4
+
5
+ Help => About IDLE: display About Idle dialog
6
+
7
+ <to be moved here from help_about.py>
8
+
9
+
10
+ Help => IDLE Help: Display help.html with proper formatting.
11
+ Doc/library/idle.rst (Sphinx)=> Doc/build/html/library/idle.html
12
+ (help.copy_strip)=> Lib/idlelib/help.html
13
+
14
+ HelpParser - Parse help.html and render to tk Text.
15
+
16
+ HelpText - Display formatted help.html.
17
+
18
+ HelpFrame - Contain text, scrollbar, and table-of-contents.
19
+ (This will be needed for display in a future tabbed window.)
20
+
21
+ HelpWindow - Display HelpFrame in a standalone window.
22
+
23
+ copy_strip - Copy idle.html to help.html, rstripping each line.
24
+
25
+ show_idlehelp - Create HelpWindow. Called in EditorWindow.help_dialog.
26
+ """
27
+ from html.parser import HTMLParser
28
+ from os.path import abspath, dirname, isfile, join
29
+ from platform import python_version
30
+
31
+ from tkinter import Toplevel, Text, Menu
32
+ from tkinter.ttk import Frame, Menubutton, Scrollbar, Style
33
+ from tkinter import font as tkfont
34
+
35
+ from idlelib.config import idleConf
36
+
37
+ ## About IDLE ##
38
+
39
+
40
+ ## IDLE Help ##
41
+
42
+ class HelpParser(HTMLParser):
43
+ """Render help.html into a text widget.
44
+
45
+ The overridden handle_xyz methods handle a subset of html tags.
46
+ The supplied text should have the needed tag configurations.
47
+ The behavior for unsupported tags, such as table, is undefined.
48
+ If the tags generated by Sphinx change, this class, especially
49
+ the handle_starttag and handle_endtags methods, might have to also.
50
+ """
51
+ def __init__(self, text):
52
+ HTMLParser.__init__(self, convert_charrefs=True)
53
+ self.text = text # Text widget we're rendering into.
54
+ self.tags = '' # Current block level text tags to apply.
55
+ self.chartags = '' # Current character level text tags.
56
+ self.show = False # Exclude html page navigation.
57
+ self.hdrlink = False # Exclude html header links.
58
+ self.level = 0 # Track indentation level.
59
+ self.pre = False # Displaying preformatted text?
60
+ self.hprefix = '' # Heading prefix (like '25.5'?) to remove.
61
+ self.nested_dl = False # In a nested <dl>?
62
+ self.simplelist = False # In a simple list (no double spacing)?
63
+ self.toc = [] # Pair headers with text indexes for toc.
64
+ self.header = '' # Text within header tags for toc.
65
+ self.prevtag = None # Previous tag info (opener?, tag).
66
+
67
+ def indent(self, amt=1):
68
+ "Change indent (+1, 0, -1) and tags."
69
+ self.level += amt
70
+ self.tags = '' if self.level == 0 else 'l'+str(self.level)
71
+
72
+ def handle_starttag(self, tag, attrs):
73
+ "Handle starttags in help.html."
74
+ class_ = ''
75
+ for a, v in attrs:
76
+ if a == 'class':
77
+ class_ = v
78
+ s = ''
79
+ if tag == 'div' and class_ == 'section':
80
+ self.show = True # Start main content.
81
+ elif tag == 'div' and class_ == 'sphinxsidebar':
82
+ self.show = False # End main content.
83
+ elif tag == 'p' and self.prevtag and not self.prevtag[0]:
84
+ # Begin a new block for <p> tags after a closed tag.
85
+ # Avoid extra lines, e.g. after <pre> tags.
86
+ lastline = self.text.get('end-1c linestart', 'end-1c')
87
+ s = '\n\n' if lastline and not lastline.isspace() else '\n'
88
+ elif tag == 'span' and class_ == 'pre':
89
+ self.chartags = 'pre'
90
+ elif tag == 'span' and class_ == 'versionmodified':
91
+ self.chartags = 'em'
92
+ elif tag == 'em':
93
+ self.chartags = 'em'
94
+ elif tag in ['ul', 'ol']:
95
+ if class_.find('simple') != -1:
96
+ s = '\n'
97
+ self.simplelist = True
98
+ else:
99
+ self.simplelist = False
100
+ self.indent()
101
+ elif tag == 'dl':
102
+ if self.level > 0:
103
+ self.nested_dl = True
104
+ elif tag == 'li':
105
+ s = '\n* ' if self.simplelist else '\n\n* '
106
+ elif tag == 'dt':
107
+ s = '\n\n' if not self.nested_dl else '\n' # Avoid extra line.
108
+ self.nested_dl = False
109
+ elif tag == 'dd':
110
+ self.indent()
111
+ s = '\n'
112
+ elif tag == 'pre':
113
+ self.pre = True
114
+ if self.show:
115
+ self.text.insert('end', '\n\n')
116
+ self.tags = 'preblock'
117
+ elif tag == 'a' and class_ == 'headerlink':
118
+ self.hdrlink = True
119
+ elif tag == 'h1':
120
+ self.tags = tag
121
+ elif tag in ['h2', 'h3']:
122
+ if self.show:
123
+ self.header = ''
124
+ self.text.insert('end', '\n\n')
125
+ self.tags = tag
126
+ if self.show:
127
+ self.text.insert('end', s, (self.tags, self.chartags))
128
+ self.prevtag = (True, tag)
129
+
130
+ def handle_endtag(self, tag):
131
+ "Handle endtags in help.html."
132
+ if tag in ['h1', 'h2', 'h3']:
133
+ assert self.level == 0
134
+ if self.show:
135
+ indent = (' ' if tag == 'h3' else
136
+ ' ' if tag == 'h2' else
137
+ '')
138
+ self.toc.append((indent+self.header, self.text.index('insert')))
139
+ self.tags = ''
140
+ elif tag in ['span', 'em']:
141
+ self.chartags = ''
142
+ elif tag == 'a':
143
+ self.hdrlink = False
144
+ elif tag == 'pre':
145
+ self.pre = False
146
+ self.tags = ''
147
+ elif tag in ['ul', 'dd', 'ol']:
148
+ self.indent(-1)
149
+ self.prevtag = (False, tag)
150
+
151
+ def handle_data(self, data):
152
+ "Handle date segments in help.html."
153
+ if self.show and not self.hdrlink:
154
+ d = data if self.pre else data.replace('\n', ' ')
155
+ if self.tags == 'h1':
156
+ try:
157
+ self.hprefix = d[0:d.index(' ')]
158
+ except ValueError:
159
+ self.hprefix = ''
160
+ if self.tags in ['h1', 'h2', 'h3']:
161
+ if (self.hprefix != '' and
162
+ d[0:len(self.hprefix)] == self.hprefix):
163
+ d = d[len(self.hprefix):]
164
+ self.header += d.strip()
165
+ self.text.insert('end', d, (self.tags, self.chartags))
166
+
167
+
168
+ class HelpText(Text):
169
+ "Display help.html."
170
+ def __init__(self, parent, filename):
171
+ "Configure tags and feed file to parser."
172
+ uwide = idleConf.GetOption('main', 'EditorWindow', 'width', type='int')
173
+ uhigh = idleConf.GetOption('main', 'EditorWindow', 'height', type='int')
174
+ uhigh = 3 * uhigh // 4 # Lines average 4/3 of editor line height.
175
+ Text.__init__(self, parent, wrap='word', highlightthickness=0,
176
+ padx=5, borderwidth=0, width=uwide, height=uhigh)
177
+
178
+ normalfont = self.findfont(['TkDefaultFont', 'arial', 'helvetica'])
179
+ fixedfont = self.findfont(['TkFixedFont', 'monaco', 'courier'])
180
+ self['font'] = (normalfont, 12)
181
+ self.tag_configure('em', font=(normalfont, 12, 'italic'))
182
+ self.tag_configure('h1', font=(normalfont, 20, 'bold'))
183
+ self.tag_configure('h2', font=(normalfont, 18, 'bold'))
184
+ self.tag_configure('h3', font=(normalfont, 15, 'bold'))
185
+ self.tag_configure('pre', font=(fixedfont, 12), background='#f6f6ff')
186
+ self.tag_configure('preblock', font=(fixedfont, 10), lmargin1=25,
187
+ borderwidth=1, relief='solid', background='#eeffcc')
188
+ self.tag_configure('l1', lmargin1=25, lmargin2=25)
189
+ self.tag_configure('l2', lmargin1=50, lmargin2=50)
190
+ self.tag_configure('l3', lmargin1=75, lmargin2=75)
191
+ self.tag_configure('l4', lmargin1=100, lmargin2=100)
192
+
193
+ self.parser = HelpParser(self)
194
+ with open(filename, encoding='utf-8') as f:
195
+ contents = f.read()
196
+ self.parser.feed(contents)
197
+ self['state'] = 'disabled'
198
+
199
+ def findfont(self, names):
200
+ "Return name of first font family derived from names."
201
+ for name in names:
202
+ if name.lower() in (x.lower() for x in tkfont.names(root=self)):
203
+ font = tkfont.Font(name=name, exists=True, root=self)
204
+ return font.actual()['family']
205
+ elif name.lower() in (x.lower()
206
+ for x in tkfont.families(root=self)):
207
+ return name
208
+
209
+
210
+ class HelpFrame(Frame):
211
+ "Display html text, scrollbar, and toc."
212
+ def __init__(self, parent, filename):
213
+ Frame.__init__(self, parent)
214
+ self.text = text = HelpText(self, filename)
215
+ self.style = Style(parent)
216
+ self['style'] = 'helpframe.TFrame'
217
+ self.style.configure('helpframe.TFrame', background=text['background'])
218
+ self.toc = toc = self.toc_menu(text)
219
+ self.scroll = scroll = Scrollbar(self, command=text.yview)
220
+ text['yscrollcommand'] = scroll.set
221
+
222
+ self.rowconfigure(0, weight=1)
223
+ self.columnconfigure(1, weight=1) # Only expand the text widget.
224
+ toc.grid(row=0, column=0, sticky='nw')
225
+ text.grid(row=0, column=1, sticky='nsew')
226
+ scroll.grid(row=0, column=2, sticky='ns')
227
+
228
+ def toc_menu(self, text):
229
+ "Create table of contents as drop-down menu."
230
+ toc = Menubutton(self, text='TOC')
231
+ drop = Menu(toc, tearoff=False)
232
+ for lbl, dex in text.parser.toc:
233
+ drop.add_command(label=lbl, command=lambda dex=dex:text.yview(dex))
234
+ toc['menu'] = drop
235
+ return toc
236
+
237
+
238
+ class HelpWindow(Toplevel):
239
+ "Display frame with rendered html."
240
+ def __init__(self, parent, filename, title):
241
+ Toplevel.__init__(self, parent)
242
+ self.wm_title(title)
243
+ self.protocol("WM_DELETE_WINDOW", self.destroy)
244
+ HelpFrame(self, filename).grid(column=0, row=0, sticky='nsew')
245
+ self.grid_columnconfigure(0, weight=1)
246
+ self.grid_rowconfigure(0, weight=1)
247
+
248
+
249
+ def copy_strip():
250
+ """Copy idle.html to idlelib/help.html, stripping trailing whitespace.
251
+
252
+ Files with trailing whitespace cannot be pushed to the git cpython
253
+ repository. For 3.x (on Windows), help.html is generated, after
254
+ editing idle.rst on the master branch, with
255
+ sphinx-build -bhtml . build/html
256
+ python_d.exe -c "from idlelib.help import copy_strip; copy_strip()"
257
+ Check build/html/library/idle.html, the help.html diff, and the text
258
+ displayed by Help => IDLE Help. Add a blurb and create a PR.
259
+
260
+ It can be worthwhile to occasionally generate help.html without
261
+ touching idle.rst. Changes to the master version and to the doc
262
+ build system may result in changes that should not changed
263
+ the displayed text, but might break HelpParser.
264
+
265
+ As long as master and maintenance versions of idle.rst remain the
266
+ same, help.html can be backported. The internal Python version
267
+ number is not displayed. If maintenance idle.rst diverges from
268
+ the master version, then instead of backporting help.html from
269
+ master, repeat the procedure above to generate a maintenance
270
+ version.
271
+ """
272
+ src = join(abspath(dirname(dirname(dirname(__file__)))),
273
+ 'Doc', 'build', 'html', 'library', 'idle.html')
274
+ dst = join(abspath(dirname(__file__)), 'help.html')
275
+ with open(src, 'rb') as inn,\
276
+ open(dst, 'wb') as out:
277
+ for line in inn:
278
+ out.write(line.rstrip() + b'\n')
279
+ print(f'{src} copied to {dst}')
280
+
281
+ def show_idlehelp(parent):
282
+ "Create HelpWindow; called from Idle Help event handler."
283
+ filename = join(abspath(dirname(__file__)), 'help.html')
284
+ if not isfile(filename):
285
+ # Try copy_strip, present message.
286
+ return
287
+ HelpWindow(parent, filename, 'IDLE Help (%s)' % python_version())
288
+
289
+ if __name__ == '__main__':
290
+ from unittest import main
291
+ main('idlelib.idle_test.test_help', verbosity=2, exit=False)
292
+
293
+ from idlelib.idle_test.htest import run
294
+ run(show_idlehelp)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/help_about.py ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """About Dialog for IDLE
2
+
3
+ """
4
+ import os
5
+ import sys
6
+ from platform import python_version, architecture
7
+
8
+ from tkinter import Toplevel, Frame, Label, Button, PhotoImage
9
+ from tkinter import SUNKEN, TOP, BOTTOM, LEFT, X, BOTH, W, EW, NSEW, E
10
+
11
+ from idlelib import textview
12
+
13
+
14
+ def build_bits():
15
+ "Return bits for platform."
16
+ if sys.platform == 'darwin':
17
+ return '64' if sys.maxsize > 2**32 else '32'
18
+ else:
19
+ return architecture()[0][:2]
20
+
21
+
22
+ class AboutDialog(Toplevel):
23
+ """Modal about dialog for idle
24
+
25
+ """
26
+ def __init__(self, parent, title=None, *, _htest=False, _utest=False):
27
+ """Create popup, do not return until tk widget destroyed.
28
+
29
+ parent - parent of this dialog
30
+ title - string which is title of popup dialog
31
+ _htest - bool, change box location when running htest
32
+ _utest - bool, don't wait_window when running unittest
33
+ """
34
+ Toplevel.__init__(self, parent)
35
+ self.configure(borderwidth=5)
36
+ # place dialog below parent if running htest
37
+ self.geometry("+%d+%d" % (
38
+ parent.winfo_rootx()+30,
39
+ parent.winfo_rooty()+(30 if not _htest else 100)))
40
+ self.bg = "#bbbbbb"
41
+ self.fg = "#000000"
42
+ self.create_widgets()
43
+ self.resizable(height=False, width=False)
44
+ self.title(title or
45
+ f'About IDLE {python_version()} ({build_bits()} bit)')
46
+ self.transient(parent)
47
+ self.grab_set()
48
+ self.protocol("WM_DELETE_WINDOW", self.ok)
49
+ self.parent = parent
50
+ self.button_ok.focus_set()
51
+ self.bind('<Return>', self.ok) # dismiss dialog
52
+ self.bind('<Escape>', self.ok) # dismiss dialog
53
+ self._current_textview = None
54
+ self._utest = _utest
55
+
56
+ if not _utest:
57
+ self.deiconify()
58
+ self.wait_window()
59
+
60
+ def create_widgets(self):
61
+ frame = Frame(self, borderwidth=2, relief=SUNKEN)
62
+ frame_buttons = Frame(self)
63
+ frame_buttons.pack(side=BOTTOM, fill=X)
64
+ frame.pack(side=TOP, expand=True, fill=BOTH)
65
+ self.button_ok = Button(frame_buttons, text='Close',
66
+ command=self.ok)
67
+ self.button_ok.pack(padx=5, pady=5)
68
+
69
+ frame_background = Frame(frame, bg=self.bg)
70
+ frame_background.pack(expand=True, fill=BOTH)
71
+
72
+ header = Label(frame_background, text='IDLE', fg=self.fg,
73
+ bg=self.bg, font=('courier', 24, 'bold'))
74
+ header.grid(row=0, column=0, sticky=E, padx=10, pady=10)
75
+
76
+ tk_patchlevel = self.tk.call('info', 'patchlevel')
77
+ ext = '.png' if tk_patchlevel >= '8.6' else '.gif'
78
+ icon = os.path.join(os.path.abspath(os.path.dirname(__file__)),
79
+ 'Icons', f'idle_48{ext}')
80
+ self.icon_image = PhotoImage(master=self._root(), file=icon)
81
+ logo = Label(frame_background, image=self.icon_image, bg=self.bg)
82
+ logo.grid(row=0, column=0, sticky=W, rowspan=2, padx=10, pady=10)
83
+
84
+ byline_text = "Python's Integrated Development\nand Learning Environment" + 5*'\n'
85
+ byline = Label(frame_background, text=byline_text, justify=LEFT,
86
+ fg=self.fg, bg=self.bg)
87
+ byline.grid(row=2, column=0, sticky=W, columnspan=3, padx=10, pady=5)
88
+ email = Label(frame_background, text='email: idle-dev@python.org',
89
+ justify=LEFT, fg=self.fg, bg=self.bg)
90
+ email.grid(row=6, column=0, columnspan=2, sticky=W, padx=10, pady=0)
91
+ docs = Label(frame_background, text='https://docs.python.org/' +
92
+ python_version()[:3] + '/library/idle.html',
93
+ justify=LEFT, fg=self.fg, bg=self.bg)
94
+ docs.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0)
95
+
96
+ Frame(frame_background, borderwidth=1, relief=SUNKEN,
97
+ height=2, bg=self.bg).grid(row=8, column=0, sticky=EW,
98
+ columnspan=3, padx=5, pady=5)
99
+
100
+ pyver = Label(frame_background,
101
+ text='Python version: ' + python_version(),
102
+ fg=self.fg, bg=self.bg)
103
+ pyver.grid(row=9, column=0, sticky=W, padx=10, pady=0)
104
+ tkver = Label(frame_background, text='Tk version: ' + tk_patchlevel,
105
+ fg=self.fg, bg=self.bg)
106
+ tkver.grid(row=9, column=1, sticky=W, padx=2, pady=0)
107
+ py_buttons = Frame(frame_background, bg=self.bg)
108
+ py_buttons.grid(row=10, column=0, columnspan=2, sticky=NSEW)
109
+ self.py_license = Button(py_buttons, text='License', width=8,
110
+ highlightbackground=self.bg,
111
+ command=self.show_py_license)
112
+ self.py_license.pack(side=LEFT, padx=10, pady=10)
113
+ self.py_copyright = Button(py_buttons, text='Copyright', width=8,
114
+ highlightbackground=self.bg,
115
+ command=self.show_py_copyright)
116
+ self.py_copyright.pack(side=LEFT, padx=10, pady=10)
117
+ self.py_credits = Button(py_buttons, text='Credits', width=8,
118
+ highlightbackground=self.bg,
119
+ command=self.show_py_credits)
120
+ self.py_credits.pack(side=LEFT, padx=10, pady=10)
121
+
122
+ Frame(frame_background, borderwidth=1, relief=SUNKEN,
123
+ height=2, bg=self.bg).grid(row=11, column=0, sticky=EW,
124
+ columnspan=3, padx=5, pady=5)
125
+
126
+ idlever = Label(frame_background,
127
+ text='IDLE version: ' + python_version(),
128
+ fg=self.fg, bg=self.bg)
129
+ idlever.grid(row=12, column=0, sticky=W, padx=10, pady=0)
130
+ idle_buttons = Frame(frame_background, bg=self.bg)
131
+ idle_buttons.grid(row=13, column=0, columnspan=3, sticky=NSEW)
132
+ self.readme = Button(idle_buttons, text='README', width=8,
133
+ highlightbackground=self.bg,
134
+ command=self.show_readme)
135
+ self.readme.pack(side=LEFT, padx=10, pady=10)
136
+ self.idle_news = Button(idle_buttons, text='NEWS', width=8,
137
+ highlightbackground=self.bg,
138
+ command=self.show_idle_news)
139
+ self.idle_news.pack(side=LEFT, padx=10, pady=10)
140
+ self.idle_credits = Button(idle_buttons, text='Credits', width=8,
141
+ highlightbackground=self.bg,
142
+ command=self.show_idle_credits)
143
+ self.idle_credits.pack(side=LEFT, padx=10, pady=10)
144
+
145
+ # License, copyright, and credits are of type _sitebuiltins._Printer
146
+ def show_py_license(self):
147
+ "Handle License button event."
148
+ self.display_printer_text('About - License', license)
149
+
150
+ def show_py_copyright(self):
151
+ "Handle Copyright button event."
152
+ self.display_printer_text('About - Copyright', copyright)
153
+
154
+ def show_py_credits(self):
155
+ "Handle Python Credits button event."
156
+ self.display_printer_text('About - Python Credits', credits)
157
+
158
+ # Encode CREDITS.txt to utf-8 for proper version of Loewis.
159
+ # Specify others as ascii until need utf-8, so catch errors.
160
+ def show_idle_credits(self):
161
+ "Handle Idle Credits button event."
162
+ self.display_file_text('About - Credits', 'CREDITS.txt', 'utf-8')
163
+
164
+ def show_readme(self):
165
+ "Handle Readme button event."
166
+ self.display_file_text('About - Readme', 'README.txt', 'ascii')
167
+
168
+ def show_idle_news(self):
169
+ "Handle News button event."
170
+ self.display_file_text('About - NEWS', 'NEWS.txt', 'utf-8')
171
+
172
+ def display_printer_text(self, title, printer):
173
+ """Create textview for built-in constants.
174
+
175
+ Built-in constants have type _sitebuiltins._Printer. The
176
+ text is extracted from the built-in and then sent to a text
177
+ viewer with self as the parent and title as the title of
178
+ the popup.
179
+ """
180
+ printer._Printer__setup()
181
+ text = '\n'.join(printer._Printer__lines)
182
+ self._current_textview = textview.view_text(
183
+ self, title, text, _utest=self._utest)
184
+
185
+ def display_file_text(self, title, filename, encoding=None):
186
+ """Create textview for filename.
187
+
188
+ The filename needs to be in the current directory. The path
189
+ is sent to a text viewer with self as the parent, title as
190
+ the title of the popup, and the file encoding.
191
+ """
192
+ fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), filename)
193
+ self._current_textview = textview.view_file(
194
+ self, title, fn, encoding, _utest=self._utest)
195
+
196
+ def ok(self, event=None):
197
+ "Dismiss help_about dialog."
198
+ self.grab_release()
199
+ self.destroy()
200
+
201
+
202
+ if __name__ == '__main__':
203
+ from unittest import main
204
+ main('idlelib.idle_test.test_help_about', verbosity=2, exit=False)
205
+
206
+ from idlelib.idle_test.htest import run
207
+ run(AboutDialog)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/history.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "Implement Idle Shell history mechanism with History class"
2
+
3
+ from idlelib.config import idleConf
4
+
5
+
6
+ class History:
7
+ ''' Implement Idle Shell history mechanism.
8
+
9
+ store - Store source statement (called from pyshell.resetoutput).
10
+ fetch - Fetch stored statement matching prefix already entered.
11
+ history_next - Bound to <<history-next>> event (default Alt-N).
12
+ history_prev - Bound to <<history-prev>> event (default Alt-P).
13
+ '''
14
+ def __init__(self, text):
15
+ '''Initialize data attributes and bind event methods.
16
+
17
+ .text - Idle wrapper of tk Text widget, with .bell().
18
+ .history - source statements, possibly with multiple lines.
19
+ .prefix - source already entered at prompt; filters history list.
20
+ .pointer - index into history.
21
+ .cyclic - wrap around history list (or not).
22
+ '''
23
+ self.text = text
24
+ self.history = []
25
+ self.prefix = None
26
+ self.pointer = None
27
+ self.cyclic = idleConf.GetOption("main", "History", "cyclic", 1, "bool")
28
+ text.bind("<<history-previous>>", self.history_prev)
29
+ text.bind("<<history-next>>", self.history_next)
30
+
31
+ def history_next(self, event):
32
+ "Fetch later statement; start with ealiest if cyclic."
33
+ self.fetch(reverse=False)
34
+ return "break"
35
+
36
+ def history_prev(self, event):
37
+ "Fetch earlier statement; start with most recent."
38
+ self.fetch(reverse=True)
39
+ return "break"
40
+
41
+ def fetch(self, reverse):
42
+ '''Fetch statement and replace current line in text widget.
43
+
44
+ Set prefix and pointer as needed for successive fetches.
45
+ Reset them to None, None when returning to the start line.
46
+ Sound bell when return to start line or cannot leave a line
47
+ because cyclic is False.
48
+ '''
49
+ nhist = len(self.history)
50
+ pointer = self.pointer
51
+ prefix = self.prefix
52
+ if pointer is not None and prefix is not None:
53
+ if self.text.compare("insert", "!=", "end-1c") or \
54
+ self.text.get("iomark", "end-1c") != self.history[pointer]:
55
+ pointer = prefix = None
56
+ self.text.mark_set("insert", "end-1c") # != after cursor move
57
+ if pointer is None or prefix is None:
58
+ prefix = self.text.get("iomark", "end-1c")
59
+ if reverse:
60
+ pointer = nhist # will be decremented
61
+ else:
62
+ if self.cyclic:
63
+ pointer = -1 # will be incremented
64
+ else: # abort history_next
65
+ self.text.bell()
66
+ return
67
+ nprefix = len(prefix)
68
+ while 1:
69
+ pointer += -1 if reverse else 1
70
+ if pointer < 0 or pointer >= nhist:
71
+ self.text.bell()
72
+ if not self.cyclic and pointer < 0: # abort history_prev
73
+ return
74
+ else:
75
+ if self.text.get("iomark", "end-1c") != prefix:
76
+ self.text.delete("iomark", "end-1c")
77
+ self.text.insert("iomark", prefix)
78
+ pointer = prefix = None
79
+ break
80
+ item = self.history[pointer]
81
+ if item[:nprefix] == prefix and len(item) > nprefix:
82
+ self.text.delete("iomark", "end-1c")
83
+ self.text.insert("iomark", item)
84
+ break
85
+ self.text.see("insert")
86
+ self.text.tag_remove("sel", "1.0", "end")
87
+ self.pointer = pointer
88
+ self.prefix = prefix
89
+
90
+ def store(self, source):
91
+ "Store Shell input statement into history list."
92
+ source = source.strip()
93
+ if len(source) > 2:
94
+ # avoid duplicates
95
+ try:
96
+ self.history.remove(source)
97
+ except ValueError:
98
+ pass
99
+ self.history.append(source)
100
+ self.pointer = None
101
+ self.prefix = None
102
+
103
+
104
+ if __name__ == "__main__":
105
+ from unittest import main
106
+ main('idlelib.idle_test.test_history', verbosity=2, exit=False)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/hyperparser.py ADDED
@@ -0,0 +1,312 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Provide advanced parsing abilities for ParenMatch and other extensions.
2
+
3
+ HyperParser uses PyParser. PyParser mostly gives information on the
4
+ proper indentation of code. HyperParser gives additional information on
5
+ the structure of code.
6
+ """
7
+ from keyword import iskeyword
8
+ import string
9
+
10
+ from idlelib import pyparse
11
+
12
+ # all ASCII chars that may be in an identifier
13
+ _ASCII_ID_CHARS = frozenset(string.ascii_letters + string.digits + "_")
14
+ # all ASCII chars that may be the first char of an identifier
15
+ _ASCII_ID_FIRST_CHARS = frozenset(string.ascii_letters + "_")
16
+
17
+ # lookup table for whether 7-bit ASCII chars are valid in a Python identifier
18
+ _IS_ASCII_ID_CHAR = [(chr(x) in _ASCII_ID_CHARS) for x in range(128)]
19
+ # lookup table for whether 7-bit ASCII chars are valid as the first
20
+ # char in a Python identifier
21
+ _IS_ASCII_ID_FIRST_CHAR = \
22
+ [(chr(x) in _ASCII_ID_FIRST_CHARS) for x in range(128)]
23
+
24
+
25
+ class HyperParser:
26
+ def __init__(self, editwin, index):
27
+ "To initialize, analyze the surroundings of the given index."
28
+
29
+ self.editwin = editwin
30
+ self.text = text = editwin.text
31
+
32
+ parser = pyparse.Parser(editwin.indentwidth, editwin.tabwidth)
33
+
34
+ def index2line(index):
35
+ return int(float(index))
36
+ lno = index2line(text.index(index))
37
+
38
+ if not editwin.prompt_last_line:
39
+ for context in editwin.num_context_lines:
40
+ startat = max(lno - context, 1)
41
+ startatindex = repr(startat) + ".0"
42
+ stopatindex = "%d.end" % lno
43
+ # We add the newline because PyParse requires a newline
44
+ # at end. We add a space so that index won't be at end
45
+ # of line, so that its status will be the same as the
46
+ # char before it, if should.
47
+ parser.set_code(text.get(startatindex, stopatindex)+' \n')
48
+ bod = parser.find_good_parse_start(
49
+ editwin._build_char_in_string_func(startatindex))
50
+ if bod is not None or startat == 1:
51
+ break
52
+ parser.set_lo(bod or 0)
53
+ else:
54
+ r = text.tag_prevrange("console", index)
55
+ if r:
56
+ startatindex = r[1]
57
+ else:
58
+ startatindex = "1.0"
59
+ stopatindex = "%d.end" % lno
60
+ # We add the newline because PyParse requires it. We add a
61
+ # space so that index won't be at end of line, so that its
62
+ # status will be the same as the char before it, if should.
63
+ parser.set_code(text.get(startatindex, stopatindex)+' \n')
64
+ parser.set_lo(0)
65
+
66
+ # We want what the parser has, minus the last newline and space.
67
+ self.rawtext = parser.code[:-2]
68
+ # Parser.code apparently preserves the statement we are in, so
69
+ # that stopatindex can be used to synchronize the string with
70
+ # the text box indices.
71
+ self.stopatindex = stopatindex
72
+ self.bracketing = parser.get_last_stmt_bracketing()
73
+ # find which pairs of bracketing are openers. These always
74
+ # correspond to a character of rawtext.
75
+ self.isopener = [i>0 and self.bracketing[i][1] >
76
+ self.bracketing[i-1][1]
77
+ for i in range(len(self.bracketing))]
78
+
79
+ self.set_index(index)
80
+
81
+ def set_index(self, index):
82
+ """Set the index to which the functions relate.
83
+
84
+ The index must be in the same statement.
85
+ """
86
+ indexinrawtext = (len(self.rawtext) -
87
+ len(self.text.get(index, self.stopatindex)))
88
+ if indexinrawtext < 0:
89
+ raise ValueError("Index %s precedes the analyzed statement"
90
+ % index)
91
+ self.indexinrawtext = indexinrawtext
92
+ # find the rightmost bracket to which index belongs
93
+ self.indexbracket = 0
94
+ while (self.indexbracket < len(self.bracketing)-1 and
95
+ self.bracketing[self.indexbracket+1][0] < self.indexinrawtext):
96
+ self.indexbracket += 1
97
+ if (self.indexbracket < len(self.bracketing)-1 and
98
+ self.bracketing[self.indexbracket+1][0] == self.indexinrawtext and
99
+ not self.isopener[self.indexbracket+1]):
100
+ self.indexbracket += 1
101
+
102
+ def is_in_string(self):
103
+ """Is the index given to the HyperParser in a string?"""
104
+ # The bracket to which we belong should be an opener.
105
+ # If it's an opener, it has to have a character.
106
+ return (self.isopener[self.indexbracket] and
107
+ self.rawtext[self.bracketing[self.indexbracket][0]]
108
+ in ('"', "'"))
109
+
110
+ def is_in_code(self):
111
+ """Is the index given to the HyperParser in normal code?"""
112
+ return (not self.isopener[self.indexbracket] or
113
+ self.rawtext[self.bracketing[self.indexbracket][0]]
114
+ not in ('#', '"', "'"))
115
+
116
+ def get_surrounding_brackets(self, openers='([{', mustclose=False):
117
+ """Return bracket indexes or None.
118
+
119
+ If the index given to the HyperParser is surrounded by a
120
+ bracket defined in openers (or at least has one before it),
121
+ return the indices of the opening bracket and the closing
122
+ bracket (or the end of line, whichever comes first).
123
+
124
+ If it is not surrounded by brackets, or the end of line comes
125
+ before the closing bracket and mustclose is True, returns None.
126
+ """
127
+
128
+ bracketinglevel = self.bracketing[self.indexbracket][1]
129
+ before = self.indexbracket
130
+ while (not self.isopener[before] or
131
+ self.rawtext[self.bracketing[before][0]] not in openers or
132
+ self.bracketing[before][1] > bracketinglevel):
133
+ before -= 1
134
+ if before < 0:
135
+ return None
136
+ bracketinglevel = min(bracketinglevel, self.bracketing[before][1])
137
+ after = self.indexbracket + 1
138
+ while (after < len(self.bracketing) and
139
+ self.bracketing[after][1] >= bracketinglevel):
140
+ after += 1
141
+
142
+ beforeindex = self.text.index("%s-%dc" %
143
+ (self.stopatindex, len(self.rawtext)-self.bracketing[before][0]))
144
+ if (after >= len(self.bracketing) or
145
+ self.bracketing[after][0] > len(self.rawtext)):
146
+ if mustclose:
147
+ return None
148
+ afterindex = self.stopatindex
149
+ else:
150
+ # We are after a real char, so it is a ')' and we give the
151
+ # index before it.
152
+ afterindex = self.text.index(
153
+ "%s-%dc" % (self.stopatindex,
154
+ len(self.rawtext)-(self.bracketing[after][0]-1)))
155
+
156
+ return beforeindex, afterindex
157
+
158
+ # the set of built-in identifiers which are also keywords,
159
+ # i.e. keyword.iskeyword() returns True for them
160
+ _ID_KEYWORDS = frozenset({"True", "False", "None"})
161
+
162
+ @classmethod
163
+ def _eat_identifier(cls, str, limit, pos):
164
+ """Given a string and pos, return the number of chars in the
165
+ identifier which ends at pos, or 0 if there is no such one.
166
+
167
+ This ignores non-identifier eywords are not identifiers.
168
+ """
169
+ is_ascii_id_char = _IS_ASCII_ID_CHAR
170
+
171
+ # Start at the end (pos) and work backwards.
172
+ i = pos
173
+
174
+ # Go backwards as long as the characters are valid ASCII
175
+ # identifier characters. This is an optimization, since it
176
+ # is faster in the common case where most of the characters
177
+ # are ASCII.
178
+ while i > limit and (
179
+ ord(str[i - 1]) < 128 and
180
+ is_ascii_id_char[ord(str[i - 1])]
181
+ ):
182
+ i -= 1
183
+
184
+ # If the above loop ended due to reaching a non-ASCII
185
+ # character, continue going backwards using the most generic
186
+ # test for whether a string contains only valid identifier
187
+ # characters.
188
+ if i > limit and ord(str[i - 1]) >= 128:
189
+ while i - 4 >= limit and ('a' + str[i - 4:pos]).isidentifier():
190
+ i -= 4
191
+ if i - 2 >= limit and ('a' + str[i - 2:pos]).isidentifier():
192
+ i -= 2
193
+ if i - 1 >= limit and ('a' + str[i - 1:pos]).isidentifier():
194
+ i -= 1
195
+
196
+ # The identifier candidate starts here. If it isn't a valid
197
+ # identifier, don't eat anything. At this point that is only
198
+ # possible if the first character isn't a valid first
199
+ # character for an identifier.
200
+ if not str[i:pos].isidentifier():
201
+ return 0
202
+ elif i < pos:
203
+ # All characters in str[i:pos] are valid ASCII identifier
204
+ # characters, so it is enough to check that the first is
205
+ # valid as the first character of an identifier.
206
+ if not _IS_ASCII_ID_FIRST_CHAR[ord(str[i])]:
207
+ return 0
208
+
209
+ # All keywords are valid identifiers, but should not be
210
+ # considered identifiers here, except for True, False and None.
211
+ if i < pos and (
212
+ iskeyword(str[i:pos]) and
213
+ str[i:pos] not in cls._ID_KEYWORDS
214
+ ):
215
+ return 0
216
+
217
+ return pos - i
218
+
219
+ # This string includes all chars that may be in a white space
220
+ _whitespace_chars = " \t\n\\"
221
+
222
+ def get_expression(self):
223
+ """Return a string with the Python expression which ends at the
224
+ given index, which is empty if there is no real one.
225
+ """
226
+ if not self.is_in_code():
227
+ raise ValueError("get_expression should only be called "
228
+ "if index is inside a code.")
229
+
230
+ rawtext = self.rawtext
231
+ bracketing = self.bracketing
232
+
233
+ brck_index = self.indexbracket
234
+ brck_limit = bracketing[brck_index][0]
235
+ pos = self.indexinrawtext
236
+
237
+ last_identifier_pos = pos
238
+ postdot_phase = True
239
+
240
+ while 1:
241
+ # Eat whitespaces, comments, and if postdot_phase is False - a dot
242
+ while 1:
243
+ if pos>brck_limit and rawtext[pos-1] in self._whitespace_chars:
244
+ # Eat a whitespace
245
+ pos -= 1
246
+ elif (not postdot_phase and
247
+ pos > brck_limit and rawtext[pos-1] == '.'):
248
+ # Eat a dot
249
+ pos -= 1
250
+ postdot_phase = True
251
+ # The next line will fail if we are *inside* a comment,
252
+ # but we shouldn't be.
253
+ elif (pos == brck_limit and brck_index > 0 and
254
+ rawtext[bracketing[brck_index-1][0]] == '#'):
255
+ # Eat a comment
256
+ brck_index -= 2
257
+ brck_limit = bracketing[brck_index][0]
258
+ pos = bracketing[brck_index+1][0]
259
+ else:
260
+ # If we didn't eat anything, quit.
261
+ break
262
+
263
+ if not postdot_phase:
264
+ # We didn't find a dot, so the expression end at the
265
+ # last identifier pos.
266
+ break
267
+
268
+ ret = self._eat_identifier(rawtext, brck_limit, pos)
269
+ if ret:
270
+ # There is an identifier to eat
271
+ pos = pos - ret
272
+ last_identifier_pos = pos
273
+ # Now, to continue the search, we must find a dot.
274
+ postdot_phase = False
275
+ # (the loop continues now)
276
+
277
+ elif pos == brck_limit:
278
+ # We are at a bracketing limit. If it is a closing
279
+ # bracket, eat the bracket, otherwise, stop the search.
280
+ level = bracketing[brck_index][1]
281
+ while brck_index > 0 and bracketing[brck_index-1][1] > level:
282
+ brck_index -= 1
283
+ if bracketing[brck_index][0] == brck_limit:
284
+ # We were not at the end of a closing bracket
285
+ break
286
+ pos = bracketing[brck_index][0]
287
+ brck_index -= 1
288
+ brck_limit = bracketing[brck_index][0]
289
+ last_identifier_pos = pos
290
+ if rawtext[pos] in "([":
291
+ # [] and () may be used after an identifier, so we
292
+ # continue. postdot_phase is True, so we don't allow a dot.
293
+ pass
294
+ else:
295
+ # We can't continue after other types of brackets
296
+ if rawtext[pos] in "'\"":
297
+ # Scan a string prefix
298
+ while pos > 0 and rawtext[pos - 1] in "rRbBuU":
299
+ pos -= 1
300
+ last_identifier_pos = pos
301
+ break
302
+
303
+ else:
304
+ # We've found an operator or something.
305
+ break
306
+
307
+ return rawtext[last_identifier_pos:self.indexinrawtext]
308
+
309
+
310
+ if __name__ == '__main__':
311
+ from unittest import main
312
+ main('idlelib.idle_test.test_hyperparser', verbosity=2)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/idle.bat ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ @echo off
2
+ rem Start IDLE using the appropriate Python interpreter
3
+ set CURRDIR=%~dp0
4
+ start "IDLE" "%CURRDIR%..\..\pythonw.exe" "%CURRDIR%idle.pyw" %1 %2 %3 %4 %5 %6 %7 %8 %9
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/idle.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os.path
2
+ import sys
3
+
4
+
5
+ # Enable running IDLE with idlelib in a non-standard location.
6
+ # This was once used to run development versions of IDLE.
7
+ # Because PEP 434 declared idle.py a public interface,
8
+ # removal should require deprecation.
9
+ idlelib_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
10
+ if idlelib_dir not in sys.path:
11
+ sys.path.insert(0, idlelib_dir)
12
+
13
+ from idlelib.pyshell import main # This is subject to change
14
+ main()
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/idle.pyw ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ try:
2
+ import idlelib.pyshell
3
+ except ImportError:
4
+ # IDLE is not installed, but maybe pyshell is on sys.path:
5
+ from . import pyshell
6
+ import os
7
+ idledir = os.path.dirname(os.path.abspath(pyshell.__file__))
8
+ if idledir != os.getcwd():
9
+ # We're not in the IDLE directory, help the subprocess find run.py
10
+ pypath = os.environ.get('PYTHONPATH', '')
11
+ if pypath:
12
+ os.environ['PYTHONPATH'] = pypath + ':' + idledir
13
+ else:
14
+ os.environ['PYTHONPATH'] = idledir
15
+ pyshell.main()
16
+ else:
17
+ idlelib.pyshell.main()
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/macosx.py ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ A number of functions that enhance IDLE on macOS.
3
+ """
4
+ from os.path import expanduser
5
+ import plistlib
6
+ from sys import platform # Used in _init_tk_type, changed by test.
7
+
8
+ import tkinter
9
+
10
+
11
+ ## Define functions that query the Mac graphics type.
12
+ ## _tk_type and its initializer are private to this section.
13
+
14
+ _tk_type = None
15
+
16
+ def _init_tk_type():
17
+ """
18
+ Initializes OS X Tk variant values for
19
+ isAquaTk(), isCarbonTk(), isCocoaTk(), and isXQuartz().
20
+ """
21
+ global _tk_type
22
+ if platform == 'darwin':
23
+ root = tkinter.Tk()
24
+ ws = root.tk.call('tk', 'windowingsystem')
25
+ if 'x11' in ws:
26
+ _tk_type = "xquartz"
27
+ elif 'aqua' not in ws:
28
+ _tk_type = "other"
29
+ elif 'AppKit' in root.tk.call('winfo', 'server', '.'):
30
+ _tk_type = "cocoa"
31
+ else:
32
+ _tk_type = "carbon"
33
+ root.destroy()
34
+ else:
35
+ _tk_type = "other"
36
+
37
+ def isAquaTk():
38
+ """
39
+ Returns True if IDLE is using a native OS X Tk (Cocoa or Carbon).
40
+ """
41
+ if not _tk_type:
42
+ _init_tk_type()
43
+ return _tk_type == "cocoa" or _tk_type == "carbon"
44
+
45
+ def isCarbonTk():
46
+ """
47
+ Returns True if IDLE is using a Carbon Aqua Tk (instead of the
48
+ newer Cocoa Aqua Tk).
49
+ """
50
+ if not _tk_type:
51
+ _init_tk_type()
52
+ return _tk_type == "carbon"
53
+
54
+ def isCocoaTk():
55
+ """
56
+ Returns True if IDLE is using a Cocoa Aqua Tk.
57
+ """
58
+ if not _tk_type:
59
+ _init_tk_type()
60
+ return _tk_type == "cocoa"
61
+
62
+ def isXQuartz():
63
+ """
64
+ Returns True if IDLE is using an OS X X11 Tk.
65
+ """
66
+ if not _tk_type:
67
+ _init_tk_type()
68
+ return _tk_type == "xquartz"
69
+
70
+
71
+ def tkVersionWarning(root):
72
+ """
73
+ Returns a string warning message if the Tk version in use appears to
74
+ be one known to cause problems with IDLE.
75
+ 1. Apple Cocoa-based Tk 8.5.7 shipped with Mac OS X 10.6 is unusable.
76
+ 2. Apple Cocoa-based Tk 8.5.9 in OS X 10.7 and 10.8 is better but
77
+ can still crash unexpectedly.
78
+ """
79
+
80
+ if isCocoaTk():
81
+ patchlevel = root.tk.call('info', 'patchlevel')
82
+ if patchlevel not in ('8.5.7', '8.5.9'):
83
+ return False
84
+ return ("WARNING: The version of Tcl/Tk ({0}) in use may"
85
+ " be unstable.\n"
86
+ "Visit http://www.python.org/download/mac/tcltk/"
87
+ " for current information.".format(patchlevel))
88
+ else:
89
+ return False
90
+
91
+
92
+ def readSystemPreferences():
93
+ """
94
+ Fetch the macOS system preferences.
95
+ """
96
+ if platform != 'darwin':
97
+ return None
98
+
99
+ plist_path = expanduser('~/Library/Preferences/.GlobalPreferences.plist')
100
+ try:
101
+ with open(plist_path, 'rb') as plist_file:
102
+ return plistlib.load(plist_file)
103
+ except OSError:
104
+ return None
105
+
106
+
107
+ def preferTabsPreferenceWarning():
108
+ """
109
+ Warn if "Prefer tabs when opening documents" is set to "Always".
110
+ """
111
+ if platform != 'darwin':
112
+ return None
113
+
114
+ prefs = readSystemPreferences()
115
+ if prefs and prefs.get('AppleWindowTabbingMode') == 'always':
116
+ return (
117
+ 'WARNING: The system preference "Prefer tabs when opening'
118
+ ' documents" is set to "Always". This will cause various problems'
119
+ ' with IDLE. For the best experience, change this setting when'
120
+ ' running IDLE (via System Preferences -> Dock).'
121
+ )
122
+ return None
123
+
124
+
125
+ ## Fix the menu and related functions.
126
+
127
+ def addOpenEventSupport(root, flist):
128
+ """
129
+ This ensures that the application will respond to open AppleEvents, which
130
+ makes is feasible to use IDLE as the default application for python files.
131
+ """
132
+ def doOpenFile(*args):
133
+ for fn in args:
134
+ flist.open(fn)
135
+
136
+ # The command below is a hook in aquatk that is called whenever the app
137
+ # receives a file open event. The callback can have multiple arguments,
138
+ # one for every file that should be opened.
139
+ root.createcommand("::tk::mac::OpenDocument", doOpenFile)
140
+
141
+ def hideTkConsole(root):
142
+ try:
143
+ root.tk.call('console', 'hide')
144
+ except tkinter.TclError:
145
+ # Some versions of the Tk framework don't have a console object
146
+ pass
147
+
148
+ def overrideRootMenu(root, flist):
149
+ """
150
+ Replace the Tk root menu by something that is more appropriate for
151
+ IDLE with an Aqua Tk.
152
+ """
153
+ # The menu that is attached to the Tk root (".") is also used by AquaTk for
154
+ # all windows that don't specify a menu of their own. The default menubar
155
+ # contains a number of menus, none of which are appropriate for IDLE. The
156
+ # Most annoying of those is an 'About Tck/Tk...' menu in the application
157
+ # menu.
158
+ #
159
+ # This function replaces the default menubar by a mostly empty one, it
160
+ # should only contain the correct application menu and the window menu.
161
+ #
162
+ # Due to a (mis-)feature of TkAqua the user will also see an empty Help
163
+ # menu.
164
+ from tkinter import Menu
165
+ from idlelib import mainmenu
166
+ from idlelib import window
167
+
168
+ closeItem = mainmenu.menudefs[0][1][-2]
169
+
170
+ # Remove the last 3 items of the file menu: a separator, close window and
171
+ # quit. Close window will be reinserted just above the save item, where
172
+ # it should be according to the HIG. Quit is in the application menu.
173
+ del mainmenu.menudefs[0][1][-3:]
174
+ mainmenu.menudefs[0][1].insert(6, closeItem)
175
+
176
+ # Remove the 'About' entry from the help menu, it is in the application
177
+ # menu
178
+ del mainmenu.menudefs[-1][1][0:2]
179
+ # Remove the 'Configure Idle' entry from the options menu, it is in the
180
+ # application menu as 'Preferences'
181
+ del mainmenu.menudefs[-3][1][0:2]
182
+ menubar = Menu(root)
183
+ root.configure(menu=menubar)
184
+ menudict = {}
185
+
186
+ menudict['window'] = menu = Menu(menubar, name='window', tearoff=0)
187
+ menubar.add_cascade(label='Window', menu=menu, underline=0)
188
+
189
+ def postwindowsmenu(menu=menu):
190
+ end = menu.index('end')
191
+ if end is None:
192
+ end = -1
193
+
194
+ if end > 0:
195
+ menu.delete(0, end)
196
+ window.add_windows_to_menu(menu)
197
+ window.register_callback(postwindowsmenu)
198
+
199
+ def about_dialog(event=None):
200
+ "Handle Help 'About IDLE' event."
201
+ # Synchronize with editor.EditorWindow.about_dialog.
202
+ from idlelib import help_about
203
+ help_about.AboutDialog(root)
204
+
205
+ def config_dialog(event=None):
206
+ "Handle Options 'Configure IDLE' event."
207
+ # Synchronize with editor.EditorWindow.config_dialog.
208
+ from idlelib import configdialog
209
+
210
+ # Ensure that the root object has an instance_dict attribute,
211
+ # mirrors code in EditorWindow (although that sets the attribute
212
+ # on an EditorWindow instance that is then passed as the first
213
+ # argument to ConfigDialog)
214
+ root.instance_dict = flist.inversedict
215
+ configdialog.ConfigDialog(root, 'Settings')
216
+
217
+ def help_dialog(event=None):
218
+ "Handle Help 'IDLE Help' event."
219
+ # Synchronize with editor.EditorWindow.help_dialog.
220
+ from idlelib import help
221
+ help.show_idlehelp(root)
222
+
223
+ root.bind('<<about-idle>>', about_dialog)
224
+ root.bind('<<open-config-dialog>>', config_dialog)
225
+ root.createcommand('::tk::mac::ShowPreferences', config_dialog)
226
+ if flist:
227
+ root.bind('<<close-all-windows>>', flist.close_all_callback)
228
+
229
+ # The binding above doesn't reliably work on all versions of Tk
230
+ # on macOS. Adding command definition below does seem to do the
231
+ # right thing for now.
232
+ root.createcommand('exit', flist.close_all_callback)
233
+
234
+ if isCarbonTk():
235
+ # for Carbon AquaTk, replace the default Tk apple menu
236
+ menudict['application'] = menu = Menu(menubar, name='apple',
237
+ tearoff=0)
238
+ menubar.add_cascade(label='IDLE', menu=menu)
239
+ mainmenu.menudefs.insert(0,
240
+ ('application', [
241
+ ('About IDLE', '<<about-idle>>'),
242
+ None,
243
+ ]))
244
+ if isCocoaTk():
245
+ # replace default About dialog with About IDLE one
246
+ root.createcommand('tkAboutDialog', about_dialog)
247
+ # replace default "Help" item in Help menu
248
+ root.createcommand('::tk::mac::ShowHelp', help_dialog)
249
+ # remove redundant "IDLE Help" from menu
250
+ del mainmenu.menudefs[-1][1][0]
251
+
252
+ def fixb2context(root):
253
+ '''Removed bad AquaTk Button-2 (right) and Paste bindings.
254
+
255
+ They prevent context menu access and seem to be gone in AquaTk8.6.
256
+ See issue #24801.
257
+ '''
258
+ root.unbind_class('Text', '<B2>')
259
+ root.unbind_class('Text', '<B2-Motion>')
260
+ root.unbind_class('Text', '<<PasteSelection>>')
261
+
262
+ def setupApp(root, flist):
263
+ """
264
+ Perform initial OS X customizations if needed.
265
+ Called from pyshell.main() after initial calls to Tk()
266
+
267
+ There are currently three major versions of Tk in use on OS X:
268
+ 1. Aqua Cocoa Tk (native default since OS X 10.6)
269
+ 2. Aqua Carbon Tk (original native, 32-bit only, deprecated)
270
+ 3. X11 (supported by some third-party distributors, deprecated)
271
+ There are various differences among the three that affect IDLE
272
+ behavior, primarily with menus, mouse key events, and accelerators.
273
+ Some one-time customizations are performed here.
274
+ Others are dynamically tested throughout idlelib by calls to the
275
+ isAquaTk(), isCarbonTk(), isCocoaTk(), isXQuartz() functions which
276
+ are initialized here as well.
277
+ """
278
+ if isAquaTk():
279
+ hideTkConsole(root)
280
+ overrideRootMenu(root, flist)
281
+ addOpenEventSupport(root, flist)
282
+ fixb2context(root)
283
+
284
+
285
+ if __name__ == '__main__':
286
+ from unittest import main
287
+ main('idlelib.idle_test.test_macosx', verbosity=2)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/multicall.py ADDED
@@ -0,0 +1,448 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MultiCall - a class which inherits its methods from a Tkinter widget (Text, for
3
+ example), but enables multiple calls of functions per virtual event - all
4
+ matching events will be called, not only the most specific one. This is done
5
+ by wrapping the event functions - event_add, event_delete and event_info.
6
+ MultiCall recognizes only a subset of legal event sequences. Sequences which
7
+ are not recognized are treated by the original Tk handling mechanism. A
8
+ more-specific event will be called before a less-specific event.
9
+
10
+ The recognized sequences are complete one-event sequences (no emacs-style
11
+ Ctrl-X Ctrl-C, no shortcuts like <3>), for all types of events.
12
+ Key/Button Press/Release events can have modifiers.
13
+ The recognized modifiers are Shift, Control, Option and Command for Mac, and
14
+ Control, Alt, Shift, Meta/M for other platforms.
15
+
16
+ For all events which were handled by MultiCall, a new member is added to the
17
+ event instance passed to the binded functions - mc_type. This is one of the
18
+ event type constants defined in this module (such as MC_KEYPRESS).
19
+ For Key/Button events (which are handled by MultiCall and may receive
20
+ modifiers), another member is added - mc_state. This member gives the state
21
+ of the recognized modifiers, as a combination of the modifier constants
22
+ also defined in this module (for example, MC_SHIFT).
23
+ Using these members is absolutely portable.
24
+
25
+ The order by which events are called is defined by these rules:
26
+ 1. A more-specific event will be called before a less-specific event.
27
+ 2. A recently-binded event will be called before a previously-binded event,
28
+ unless this conflicts with the first rule.
29
+ Each function will be called at most once for each event.
30
+ """
31
+ import re
32
+ import sys
33
+
34
+ import tkinter
35
+
36
+ # the event type constants, which define the meaning of mc_type
37
+ MC_KEYPRESS=0; MC_KEYRELEASE=1; MC_BUTTONPRESS=2; MC_BUTTONRELEASE=3;
38
+ MC_ACTIVATE=4; MC_CIRCULATE=5; MC_COLORMAP=6; MC_CONFIGURE=7;
39
+ MC_DEACTIVATE=8; MC_DESTROY=9; MC_ENTER=10; MC_EXPOSE=11; MC_FOCUSIN=12;
40
+ MC_FOCUSOUT=13; MC_GRAVITY=14; MC_LEAVE=15; MC_MAP=16; MC_MOTION=17;
41
+ MC_MOUSEWHEEL=18; MC_PROPERTY=19; MC_REPARENT=20; MC_UNMAP=21; MC_VISIBILITY=22;
42
+ # the modifier state constants, which define the meaning of mc_state
43
+ MC_SHIFT = 1<<0; MC_CONTROL = 1<<2; MC_ALT = 1<<3; MC_META = 1<<5
44
+ MC_OPTION = 1<<6; MC_COMMAND = 1<<7
45
+
46
+ # define the list of modifiers, to be used in complex event types.
47
+ if sys.platform == "darwin":
48
+ _modifiers = (("Shift",), ("Control",), ("Option",), ("Command",))
49
+ _modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND)
50
+ else:
51
+ _modifiers = (("Control",), ("Alt",), ("Shift",), ("Meta", "M"))
52
+ _modifier_masks = (MC_CONTROL, MC_ALT, MC_SHIFT, MC_META)
53
+
54
+ # a dictionary to map a modifier name into its number
55
+ _modifier_names = dict([(name, number)
56
+ for number in range(len(_modifiers))
57
+ for name in _modifiers[number]])
58
+
59
+ # In 3.4, if no shell window is ever open, the underlying Tk widget is
60
+ # destroyed before .__del__ methods here are called. The following
61
+ # is used to selectively ignore shutdown exceptions to avoid
62
+ # 'Exception ignored' messages. See http://bugs.python.org/issue20167
63
+ APPLICATION_GONE = "application has been destroyed"
64
+
65
+ # A binder is a class which binds functions to one type of event. It has two
66
+ # methods: bind and unbind, which get a function and a parsed sequence, as
67
+ # returned by _parse_sequence(). There are two types of binders:
68
+ # _SimpleBinder handles event types with no modifiers and no detail.
69
+ # No Python functions are called when no events are binded.
70
+ # _ComplexBinder handles event types with modifiers and a detail.
71
+ # A Python function is called each time an event is generated.
72
+
73
+ class _SimpleBinder:
74
+ def __init__(self, type, widget, widgetinst):
75
+ self.type = type
76
+ self.sequence = '<'+_types[type][0]+'>'
77
+ self.widget = widget
78
+ self.widgetinst = widgetinst
79
+ self.bindedfuncs = []
80
+ self.handlerid = None
81
+
82
+ def bind(self, triplet, func):
83
+ if not self.handlerid:
84
+ def handler(event, l = self.bindedfuncs, mc_type = self.type):
85
+ event.mc_type = mc_type
86
+ wascalled = {}
87
+ for i in range(len(l)-1, -1, -1):
88
+ func = l[i]
89
+ if func not in wascalled:
90
+ wascalled[func] = True
91
+ r = func(event)
92
+ if r:
93
+ return r
94
+ self.handlerid = self.widget.bind(self.widgetinst,
95
+ self.sequence, handler)
96
+ self.bindedfuncs.append(func)
97
+
98
+ def unbind(self, triplet, func):
99
+ self.bindedfuncs.remove(func)
100
+ if not self.bindedfuncs:
101
+ self.widget.unbind(self.widgetinst, self.sequence, self.handlerid)
102
+ self.handlerid = None
103
+
104
+ def __del__(self):
105
+ if self.handlerid:
106
+ try:
107
+ self.widget.unbind(self.widgetinst, self.sequence,
108
+ self.handlerid)
109
+ except tkinter.TclError as e:
110
+ if not APPLICATION_GONE in e.args[0]:
111
+ raise
112
+
113
+ # An int in range(1 << len(_modifiers)) represents a combination of modifiers
114
+ # (if the least significant bit is on, _modifiers[0] is on, and so on).
115
+ # _state_subsets gives for each combination of modifiers, or *state*,
116
+ # a list of the states which are a subset of it. This list is ordered by the
117
+ # number of modifiers is the state - the most specific state comes first.
118
+ _states = range(1 << len(_modifiers))
119
+ _state_names = [''.join(m[0]+'-'
120
+ for i, m in enumerate(_modifiers)
121
+ if (1 << i) & s)
122
+ for s in _states]
123
+
124
+ def expand_substates(states):
125
+ '''For each item of states return a list containing all combinations of
126
+ that item with individual bits reset, sorted by the number of set bits.
127
+ '''
128
+ def nbits(n):
129
+ "number of bits set in n base 2"
130
+ nb = 0
131
+ while n:
132
+ n, rem = divmod(n, 2)
133
+ nb += rem
134
+ return nb
135
+ statelist = []
136
+ for state in states:
137
+ substates = list(set(state & x for x in states))
138
+ substates.sort(key=nbits, reverse=True)
139
+ statelist.append(substates)
140
+ return statelist
141
+
142
+ _state_subsets = expand_substates(_states)
143
+
144
+ # _state_codes gives for each state, the portable code to be passed as mc_state
145
+ _state_codes = []
146
+ for s in _states:
147
+ r = 0
148
+ for i in range(len(_modifiers)):
149
+ if (1 << i) & s:
150
+ r |= _modifier_masks[i]
151
+ _state_codes.append(r)
152
+
153
+ class _ComplexBinder:
154
+ # This class binds many functions, and only unbinds them when it is deleted.
155
+ # self.handlerids is the list of seqs and ids of binded handler functions.
156
+ # The binded functions sit in a dictionary of lists of lists, which maps
157
+ # a detail (or None) and a state into a list of functions.
158
+ # When a new detail is discovered, handlers for all the possible states
159
+ # are binded.
160
+
161
+ def __create_handler(self, lists, mc_type, mc_state):
162
+ def handler(event, lists = lists,
163
+ mc_type = mc_type, mc_state = mc_state,
164
+ ishandlerrunning = self.ishandlerrunning,
165
+ doafterhandler = self.doafterhandler):
166
+ ishandlerrunning[:] = [True]
167
+ event.mc_type = mc_type
168
+ event.mc_state = mc_state
169
+ wascalled = {}
170
+ r = None
171
+ for l in lists:
172
+ for i in range(len(l)-1, -1, -1):
173
+ func = l[i]
174
+ if func not in wascalled:
175
+ wascalled[func] = True
176
+ r = l[i](event)
177
+ if r:
178
+ break
179
+ if r:
180
+ break
181
+ ishandlerrunning[:] = []
182
+ # Call all functions in doafterhandler and remove them from list
183
+ for f in doafterhandler:
184
+ f()
185
+ doafterhandler[:] = []
186
+ if r:
187
+ return r
188
+ return handler
189
+
190
+ def __init__(self, type, widget, widgetinst):
191
+ self.type = type
192
+ self.typename = _types[type][0]
193
+ self.widget = widget
194
+ self.widgetinst = widgetinst
195
+ self.bindedfuncs = {None: [[] for s in _states]}
196
+ self.handlerids = []
197
+ # we don't want to change the lists of functions while a handler is
198
+ # running - it will mess up the loop and anyway, we usually want the
199
+ # change to happen from the next event. So we have a list of functions
200
+ # for the handler to run after it finishes calling the binded functions.
201
+ # It calls them only once.
202
+ # ishandlerrunning is a list. An empty one means no, otherwise - yes.
203
+ # this is done so that it would be mutable.
204
+ self.ishandlerrunning = []
205
+ self.doafterhandler = []
206
+ for s in _states:
207
+ lists = [self.bindedfuncs[None][i] for i in _state_subsets[s]]
208
+ handler = self.__create_handler(lists, type, _state_codes[s])
209
+ seq = '<'+_state_names[s]+self.typename+'>'
210
+ self.handlerids.append((seq, self.widget.bind(self.widgetinst,
211
+ seq, handler)))
212
+
213
+ def bind(self, triplet, func):
214
+ if triplet[2] not in self.bindedfuncs:
215
+ self.bindedfuncs[triplet[2]] = [[] for s in _states]
216
+ for s in _states:
217
+ lists = [ self.bindedfuncs[detail][i]
218
+ for detail in (triplet[2], None)
219
+ for i in _state_subsets[s] ]
220
+ handler = self.__create_handler(lists, self.type,
221
+ _state_codes[s])
222
+ seq = "<%s%s-%s>"% (_state_names[s], self.typename, triplet[2])
223
+ self.handlerids.append((seq, self.widget.bind(self.widgetinst,
224
+ seq, handler)))
225
+ doit = lambda: self.bindedfuncs[triplet[2]][triplet[0]].append(func)
226
+ if not self.ishandlerrunning:
227
+ doit()
228
+ else:
229
+ self.doafterhandler.append(doit)
230
+
231
+ def unbind(self, triplet, func):
232
+ doit = lambda: self.bindedfuncs[triplet[2]][triplet[0]].remove(func)
233
+ if not self.ishandlerrunning:
234
+ doit()
235
+ else:
236
+ self.doafterhandler.append(doit)
237
+
238
+ def __del__(self):
239
+ for seq, id in self.handlerids:
240
+ try:
241
+ self.widget.unbind(self.widgetinst, seq, id)
242
+ except tkinter.TclError as e:
243
+ if not APPLICATION_GONE in e.args[0]:
244
+ raise
245
+
246
+ # define the list of event types to be handled by MultiEvent. the order is
247
+ # compatible with the definition of event type constants.
248
+ _types = (
249
+ ("KeyPress", "Key"), ("KeyRelease",), ("ButtonPress", "Button"),
250
+ ("ButtonRelease",), ("Activate",), ("Circulate",), ("Colormap",),
251
+ ("Configure",), ("Deactivate",), ("Destroy",), ("Enter",), ("Expose",),
252
+ ("FocusIn",), ("FocusOut",), ("Gravity",), ("Leave",), ("Map",),
253
+ ("Motion",), ("MouseWheel",), ("Property",), ("Reparent",), ("Unmap",),
254
+ ("Visibility",),
255
+ )
256
+
257
+ # which binder should be used for every event type?
258
+ _binder_classes = (_ComplexBinder,) * 4 + (_SimpleBinder,) * (len(_types)-4)
259
+
260
+ # A dictionary to map a type name into its number
261
+ _type_names = dict([(name, number)
262
+ for number in range(len(_types))
263
+ for name in _types[number]])
264
+
265
+ _keysym_re = re.compile(r"^\w+$")
266
+ _button_re = re.compile(r"^[1-5]$")
267
+ def _parse_sequence(sequence):
268
+ """Get a string which should describe an event sequence. If it is
269
+ successfully parsed as one, return a tuple containing the state (as an int),
270
+ the event type (as an index of _types), and the detail - None if none, or a
271
+ string if there is one. If the parsing is unsuccessful, return None.
272
+ """
273
+ if not sequence or sequence[0] != '<' or sequence[-1] != '>':
274
+ return None
275
+ words = sequence[1:-1].split('-')
276
+ modifiers = 0
277
+ while words and words[0] in _modifier_names:
278
+ modifiers |= 1 << _modifier_names[words[0]]
279
+ del words[0]
280
+ if words and words[0] in _type_names:
281
+ type = _type_names[words[0]]
282
+ del words[0]
283
+ else:
284
+ return None
285
+ if _binder_classes[type] is _SimpleBinder:
286
+ if modifiers or words:
287
+ return None
288
+ else:
289
+ detail = None
290
+ else:
291
+ # _ComplexBinder
292
+ if type in [_type_names[s] for s in ("KeyPress", "KeyRelease")]:
293
+ type_re = _keysym_re
294
+ else:
295
+ type_re = _button_re
296
+
297
+ if not words:
298
+ detail = None
299
+ elif len(words) == 1 and type_re.match(words[0]):
300
+ detail = words[0]
301
+ else:
302
+ return None
303
+
304
+ return modifiers, type, detail
305
+
306
+ def _triplet_to_sequence(triplet):
307
+ if triplet[2]:
308
+ return '<'+_state_names[triplet[0]]+_types[triplet[1]][0]+'-'+ \
309
+ triplet[2]+'>'
310
+ else:
311
+ return '<'+_state_names[triplet[0]]+_types[triplet[1]][0]+'>'
312
+
313
+ _multicall_dict = {}
314
+ def MultiCallCreator(widget):
315
+ """Return a MultiCall class which inherits its methods from the
316
+ given widget class (for example, Tkinter.Text). This is used
317
+ instead of a templating mechanism.
318
+ """
319
+ if widget in _multicall_dict:
320
+ return _multicall_dict[widget]
321
+
322
+ class MultiCall (widget):
323
+ assert issubclass(widget, tkinter.Misc)
324
+
325
+ def __init__(self, *args, **kwargs):
326
+ widget.__init__(self, *args, **kwargs)
327
+ # a dictionary which maps a virtual event to a tuple with:
328
+ # 0. the function binded
329
+ # 1. a list of triplets - the sequences it is binded to
330
+ self.__eventinfo = {}
331
+ self.__binders = [_binder_classes[i](i, widget, self)
332
+ for i in range(len(_types))]
333
+
334
+ def bind(self, sequence=None, func=None, add=None):
335
+ #print("bind(%s, %s, %s)" % (sequence, func, add),
336
+ # file=sys.__stderr__)
337
+ if type(sequence) is str and len(sequence) > 2 and \
338
+ sequence[:2] == "<<" and sequence[-2:] == ">>":
339
+ if sequence in self.__eventinfo:
340
+ ei = self.__eventinfo[sequence]
341
+ if ei[0] is not None:
342
+ for triplet in ei[1]:
343
+ self.__binders[triplet[1]].unbind(triplet, ei[0])
344
+ ei[0] = func
345
+ if ei[0] is not None:
346
+ for triplet in ei[1]:
347
+ self.__binders[triplet[1]].bind(triplet, func)
348
+ else:
349
+ self.__eventinfo[sequence] = [func, []]
350
+ return widget.bind(self, sequence, func, add)
351
+
352
+ def unbind(self, sequence, funcid=None):
353
+ if type(sequence) is str and len(sequence) > 2 and \
354
+ sequence[:2] == "<<" and sequence[-2:] == ">>" and \
355
+ sequence in self.__eventinfo:
356
+ func, triplets = self.__eventinfo[sequence]
357
+ if func is not None:
358
+ for triplet in triplets:
359
+ self.__binders[triplet[1]].unbind(triplet, func)
360
+ self.__eventinfo[sequence][0] = None
361
+ return widget.unbind(self, sequence, funcid)
362
+
363
+ def event_add(self, virtual, *sequences):
364
+ #print("event_add(%s, %s)" % (repr(virtual), repr(sequences)),
365
+ # file=sys.__stderr__)
366
+ if virtual not in self.__eventinfo:
367
+ self.__eventinfo[virtual] = [None, []]
368
+
369
+ func, triplets = self.__eventinfo[virtual]
370
+ for seq in sequences:
371
+ triplet = _parse_sequence(seq)
372
+ if triplet is None:
373
+ #print("Tkinter event_add(%s)" % seq, file=sys.__stderr__)
374
+ widget.event_add(self, virtual, seq)
375
+ else:
376
+ if func is not None:
377
+ self.__binders[triplet[1]].bind(triplet, func)
378
+ triplets.append(triplet)
379
+
380
+ def event_delete(self, virtual, *sequences):
381
+ if virtual not in self.__eventinfo:
382
+ return
383
+ func, triplets = self.__eventinfo[virtual]
384
+ for seq in sequences:
385
+ triplet = _parse_sequence(seq)
386
+ if triplet is None:
387
+ #print("Tkinter event_delete: %s" % seq, file=sys.__stderr__)
388
+ widget.event_delete(self, virtual, seq)
389
+ else:
390
+ if func is not None:
391
+ self.__binders[triplet[1]].unbind(triplet, func)
392
+ triplets.remove(triplet)
393
+
394
+ def event_info(self, virtual=None):
395
+ if virtual is None or virtual not in self.__eventinfo:
396
+ return widget.event_info(self, virtual)
397
+ else:
398
+ return tuple(map(_triplet_to_sequence,
399
+ self.__eventinfo[virtual][1])) + \
400
+ widget.event_info(self, virtual)
401
+
402
+ def __del__(self):
403
+ for virtual in self.__eventinfo:
404
+ func, triplets = self.__eventinfo[virtual]
405
+ if func:
406
+ for triplet in triplets:
407
+ try:
408
+ self.__binders[triplet[1]].unbind(triplet, func)
409
+ except tkinter.TclError as e:
410
+ if not APPLICATION_GONE in e.args[0]:
411
+ raise
412
+
413
+ _multicall_dict[widget] = MultiCall
414
+ return MultiCall
415
+
416
+
417
+ def _multi_call(parent): # htest #
418
+ top = tkinter.Toplevel(parent)
419
+ top.title("Test MultiCall")
420
+ x, y = map(int, parent.geometry().split('+')[1:])
421
+ top.geometry("+%d+%d" % (x, y + 175))
422
+ text = MultiCallCreator(tkinter.Text)(top)
423
+ text.pack()
424
+ def bindseq(seq, n=[0]):
425
+ def handler(event):
426
+ print(seq)
427
+ text.bind("<<handler%d>>"%n[0], handler)
428
+ text.event_add("<<handler%d>>"%n[0], seq)
429
+ n[0] += 1
430
+ bindseq("<Key>")
431
+ bindseq("<Control-Key>")
432
+ bindseq("<Alt-Key-a>")
433
+ bindseq("<Control-Key-a>")
434
+ bindseq("<Alt-Control-Key-a>")
435
+ bindseq("<Key-b>")
436
+ bindseq("<Control-Button-1>")
437
+ bindseq("<Button-2>")
438
+ bindseq("<Alt-Button-1>")
439
+ bindseq("<FocusOut>")
440
+ bindseq("<Enter>")
441
+ bindseq("<Leave>")
442
+
443
+ if __name__ == "__main__":
444
+ from unittest import main
445
+ main('idlelib.idle_test.test_mainmenu', verbosity=2, exit=False)
446
+
447
+ from idlelib.idle_test.htest import run
448
+ run(_multi_call)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/outwin.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Editor window that can serve as an output file.
2
+ """
3
+
4
+ import re
5
+
6
+ from tkinter import messagebox
7
+
8
+ from idlelib.editor import EditorWindow
9
+
10
+
11
+ file_line_pats = [
12
+ # order of patterns matters
13
+ r'file "([^"]*)", line (\d+)',
14
+ r'([^\s]+)\((\d+)\)',
15
+ r'^(\s*\S.*?):\s*(\d+):', # Win filename, maybe starting with spaces
16
+ r'([^\s]+):\s*(\d+):', # filename or path, ltrim
17
+ r'^\s*(\S.*?):\s*(\d+):', # Win abs path with embedded spaces, ltrim
18
+ ]
19
+
20
+ file_line_progs = None
21
+
22
+
23
+ def compile_progs():
24
+ "Compile the patterns for matching to file name and line number."
25
+ global file_line_progs
26
+ file_line_progs = [re.compile(pat, re.IGNORECASE)
27
+ for pat in file_line_pats]
28
+
29
+
30
+ def file_line_helper(line):
31
+ """Extract file name and line number from line of text.
32
+
33
+ Check if line of text contains one of the file/line patterns.
34
+ If it does and if the file and line are valid, return
35
+ a tuple of the file name and line number. If it doesn't match
36
+ or if the file or line is invalid, return None.
37
+ """
38
+ if not file_line_progs:
39
+ compile_progs()
40
+ for prog in file_line_progs:
41
+ match = prog.search(line)
42
+ if match:
43
+ filename, lineno = match.group(1, 2)
44
+ try:
45
+ f = open(filename, "r")
46
+ f.close()
47
+ break
48
+ except OSError:
49
+ continue
50
+ else:
51
+ return None
52
+ try:
53
+ return filename, int(lineno)
54
+ except TypeError:
55
+ return None
56
+
57
+
58
+ class OutputWindow(EditorWindow):
59
+ """An editor window that can serve as an output file.
60
+
61
+ Also the future base class for the Python shell window.
62
+ This class has no input facilities.
63
+
64
+ Adds binding to open a file at a line to the text widget.
65
+ """
66
+
67
+ # Our own right-button menu
68
+ rmenu_specs = [
69
+ ("Cut", "<<cut>>", "rmenu_check_cut"),
70
+ ("Copy", "<<copy>>", "rmenu_check_copy"),
71
+ ("Paste", "<<paste>>", "rmenu_check_paste"),
72
+ (None, None, None),
73
+ ("Go to file/line", "<<goto-file-line>>", None),
74
+ ]
75
+
76
+ allow_code_context = False
77
+
78
+ def __init__(self, *args):
79
+ EditorWindow.__init__(self, *args)
80
+ self.text.bind("<<goto-file-line>>", self.goto_file_line)
81
+
82
+ # Customize EditorWindow
83
+ def ispythonsource(self, filename):
84
+ "Python source is only part of output: do not colorize."
85
+ return False
86
+
87
+ def short_title(self):
88
+ "Customize EditorWindow title."
89
+ return "Output"
90
+
91
+ def maybesave(self):
92
+ "Customize EditorWindow to not display save file messagebox."
93
+ return 'yes' if self.get_saved() else 'no'
94
+
95
+ # Act as output file
96
+ def write(self, s, tags=(), mark="insert"):
97
+ """Write text to text widget.
98
+
99
+ The text is inserted at the given index with the provided
100
+ tags. The text widget is then scrolled to make it visible
101
+ and updated to display it, giving the effect of seeing each
102
+ line as it is added.
103
+
104
+ Args:
105
+ s: Text to insert into text widget.
106
+ tags: Tuple of tag strings to apply on the insert.
107
+ mark: Index for the insert.
108
+
109
+ Return:
110
+ Length of text inserted.
111
+ """
112
+ assert isinstance(s, str)
113
+ self.text.insert(mark, s, tags)
114
+ self.text.see(mark)
115
+ self.text.update()
116
+ return len(s)
117
+
118
+ def writelines(self, lines):
119
+ "Write each item in lines iterable."
120
+ for line in lines:
121
+ self.write(line)
122
+
123
+ def flush(self):
124
+ "No flushing needed as write() directly writes to widget."
125
+ pass
126
+
127
+ def showerror(self, *args, **kwargs):
128
+ messagebox.showerror(*args, **kwargs)
129
+
130
+ def goto_file_line(self, event=None):
131
+ """Handle request to open file/line.
132
+
133
+ If the selected or previous line in the output window
134
+ contains a file name and line number, then open that file
135
+ name in a new window and position on the line number.
136
+
137
+ Otherwise, display an error messagebox.
138
+ """
139
+ line = self.text.get("insert linestart", "insert lineend")
140
+ result = file_line_helper(line)
141
+ if not result:
142
+ # Try the previous line. This is handy e.g. in tracebacks,
143
+ # where you tend to right-click on the displayed source line
144
+ line = self.text.get("insert -1line linestart",
145
+ "insert -1line lineend")
146
+ result = file_line_helper(line)
147
+ if not result:
148
+ self.showerror(
149
+ "No special line",
150
+ "The line you point at doesn't look like "
151
+ "a valid file name followed by a line number.",
152
+ parent=self.text)
153
+ return
154
+ filename, lineno = result
155
+ self.flist.gotofileline(filename, lineno)
156
+
157
+
158
+ # These classes are currently not used but might come in handy
159
+ class OnDemandOutputWindow:
160
+
161
+ tagdefs = {
162
+ # XXX Should use IdlePrefs.ColorPrefs
163
+ "stdout": {"foreground": "blue"},
164
+ "stderr": {"foreground": "#007700"},
165
+ }
166
+
167
+ def __init__(self, flist):
168
+ self.flist = flist
169
+ self.owin = None
170
+
171
+ def write(self, s, tags, mark):
172
+ if not self.owin:
173
+ self.setup()
174
+ self.owin.write(s, tags, mark)
175
+
176
+ def setup(self):
177
+ self.owin = owin = OutputWindow(self.flist)
178
+ text = owin.text
179
+ for tag, cnf in self.tagdefs.items():
180
+ if cnf:
181
+ text.tag_configure(tag, **cnf)
182
+ text.tag_raise('sel')
183
+ self.write = self.owin.write
184
+
185
+ if __name__ == '__main__':
186
+ from unittest import main
187
+ main('idlelib.idle_test.test_outwin', verbosity=2, exit=False)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/parenmatch.py ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ParenMatch -- for parenthesis matching.
2
+
3
+ When you hit a right paren, the cursor should move briefly to the left
4
+ paren. Paren here is used generically; the matching applies to
5
+ parentheses, square brackets, and curly braces.
6
+ """
7
+ from idlelib.hyperparser import HyperParser
8
+ from idlelib.config import idleConf
9
+
10
+ _openers = {')':'(',']':'[','}':'{'}
11
+ CHECK_DELAY = 100 # milliseconds
12
+
13
+ class ParenMatch:
14
+ """Highlight matching openers and closers, (), [], and {}.
15
+
16
+ There are three supported styles of paren matching. When a right
17
+ paren (opener) is typed:
18
+
19
+ opener -- highlight the matching left paren (closer);
20
+ parens -- highlight the left and right parens (opener and closer);
21
+ expression -- highlight the entire expression from opener to closer.
22
+ (For back compatibility, 'default' is a synonym for 'opener').
23
+
24
+ Flash-delay is the maximum milliseconds the highlighting remains.
25
+ Any cursor movement (key press or click) before that removes the
26
+ highlight. If flash-delay is 0, there is no maximum.
27
+
28
+ TODO:
29
+ - Augment bell() with mismatch warning in status window.
30
+ - Highlight when cursor is moved to the right of a closer.
31
+ This might be too expensive to check.
32
+ """
33
+
34
+ RESTORE_VIRTUAL_EVENT_NAME = "<<parenmatch-check-restore>>"
35
+ # We want the restore event be called before the usual return and
36
+ # backspace events.
37
+ RESTORE_SEQUENCES = ("<KeyPress>", "<ButtonPress>",
38
+ "<Key-Return>", "<Key-BackSpace>")
39
+
40
+ def __init__(self, editwin):
41
+ self.editwin = editwin
42
+ self.text = editwin.text
43
+ # Bind the check-restore event to the function restore_event,
44
+ # so that we can then use activate_restore (which calls event_add)
45
+ # and deactivate_restore (which calls event_delete).
46
+ editwin.text.bind(self.RESTORE_VIRTUAL_EVENT_NAME,
47
+ self.restore_event)
48
+ self.counter = 0
49
+ self.is_restore_active = 0
50
+
51
+ @classmethod
52
+ def reload(cls):
53
+ cls.STYLE = idleConf.GetOption(
54
+ 'extensions','ParenMatch','style', default='opener')
55
+ cls.FLASH_DELAY = idleConf.GetOption(
56
+ 'extensions','ParenMatch','flash-delay', type='int',default=500)
57
+ cls.BELL = idleConf.GetOption(
58
+ 'extensions','ParenMatch','bell', type='bool', default=1)
59
+ cls.HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(),
60
+ 'hilite')
61
+
62
+ def activate_restore(self):
63
+ "Activate mechanism to restore text from highlighting."
64
+ if not self.is_restore_active:
65
+ for seq in self.RESTORE_SEQUENCES:
66
+ self.text.event_add(self.RESTORE_VIRTUAL_EVENT_NAME, seq)
67
+ self.is_restore_active = True
68
+
69
+ def deactivate_restore(self):
70
+ "Remove restore event bindings."
71
+ if self.is_restore_active:
72
+ for seq in self.RESTORE_SEQUENCES:
73
+ self.text.event_delete(self.RESTORE_VIRTUAL_EVENT_NAME, seq)
74
+ self.is_restore_active = False
75
+
76
+ def flash_paren_event(self, event):
77
+ "Handle editor 'show surrounding parens' event (menu or shortcut)."
78
+ indices = (HyperParser(self.editwin, "insert")
79
+ .get_surrounding_brackets())
80
+ self.finish_paren_event(indices)
81
+ return "break"
82
+
83
+ def paren_closed_event(self, event):
84
+ "Handle user input of closer."
85
+ # If user bound non-closer to <<paren-closed>>, quit.
86
+ closer = self.text.get("insert-1c")
87
+ if closer not in _openers:
88
+ return
89
+ hp = HyperParser(self.editwin, "insert-1c")
90
+ if not hp.is_in_code():
91
+ return
92
+ indices = hp.get_surrounding_brackets(_openers[closer], True)
93
+ self.finish_paren_event(indices)
94
+ return # Allow calltips to see ')'
95
+
96
+ def finish_paren_event(self, indices):
97
+ if indices is None and self.BELL:
98
+ self.text.bell()
99
+ return
100
+ self.activate_restore()
101
+ # self.create_tag(indices)
102
+ self.tagfuncs.get(self.STYLE, self.create_tag_expression)(self, indices)
103
+ # self.set_timeout()
104
+ (self.set_timeout_last if self.FLASH_DELAY else
105
+ self.set_timeout_none)()
106
+
107
+ def restore_event(self, event=None):
108
+ "Remove effect of doing match."
109
+ self.text.tag_delete("paren")
110
+ self.deactivate_restore()
111
+ self.counter += 1 # disable the last timer, if there is one.
112
+
113
+ def handle_restore_timer(self, timer_count):
114
+ if timer_count == self.counter:
115
+ self.restore_event()
116
+
117
+ # any one of the create_tag_XXX methods can be used depending on
118
+ # the style
119
+
120
+ def create_tag_opener(self, indices):
121
+ """Highlight the single paren that matches"""
122
+ self.text.tag_add("paren", indices[0])
123
+ self.text.tag_config("paren", self.HILITE_CONFIG)
124
+
125
+ def create_tag_parens(self, indices):
126
+ """Highlight the left and right parens"""
127
+ if self.text.get(indices[1]) in (')', ']', '}'):
128
+ rightindex = indices[1]+"+1c"
129
+ else:
130
+ rightindex = indices[1]
131
+ self.text.tag_add("paren", indices[0], indices[0]+"+1c", rightindex+"-1c", rightindex)
132
+ self.text.tag_config("paren", self.HILITE_CONFIG)
133
+
134
+ def create_tag_expression(self, indices):
135
+ """Highlight the entire expression"""
136
+ if self.text.get(indices[1]) in (')', ']', '}'):
137
+ rightindex = indices[1]+"+1c"
138
+ else:
139
+ rightindex = indices[1]
140
+ self.text.tag_add("paren", indices[0], rightindex)
141
+ self.text.tag_config("paren", self.HILITE_CONFIG)
142
+
143
+ tagfuncs = {
144
+ 'opener': create_tag_opener,
145
+ 'default': create_tag_opener,
146
+ 'parens': create_tag_parens,
147
+ 'expression': create_tag_expression,
148
+ }
149
+
150
+ # any one of the set_timeout_XXX methods can be used depending on
151
+ # the style
152
+
153
+ def set_timeout_none(self):
154
+ """Highlight will remain until user input turns it off
155
+ or the insert has moved"""
156
+ # After CHECK_DELAY, call a function which disables the "paren" tag
157
+ # if the event is for the most recent timer and the insert has changed,
158
+ # or schedules another call for itself.
159
+ self.counter += 1
160
+ def callme(callme, self=self, c=self.counter,
161
+ index=self.text.index("insert")):
162
+ if index != self.text.index("insert"):
163
+ self.handle_restore_timer(c)
164
+ else:
165
+ self.editwin.text_frame.after(CHECK_DELAY, callme, callme)
166
+ self.editwin.text_frame.after(CHECK_DELAY, callme, callme)
167
+
168
+ def set_timeout_last(self):
169
+ """The last highlight created will be removed after FLASH_DELAY millisecs"""
170
+ # associate a counter with an event; only disable the "paren"
171
+ # tag if the event is for the most recent timer.
172
+ self.counter += 1
173
+ self.editwin.text_frame.after(
174
+ self.FLASH_DELAY,
175
+ lambda self=self, c=self.counter: self.handle_restore_timer(c))
176
+
177
+
178
+ ParenMatch.reload()
179
+
180
+
181
+ if __name__ == '__main__':
182
+ from unittest import main
183
+ main('idlelib.idle_test.test_parenmatch', verbosity=2)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/pathbrowser.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib.machinery
2
+ import os
3
+ import sys
4
+
5
+ from idlelib.browser import ModuleBrowser, ModuleBrowserTreeItem
6
+ from idlelib.tree import TreeItem
7
+
8
+
9
+ class PathBrowser(ModuleBrowser):
10
+
11
+ def __init__(self, master, *, _htest=False, _utest=False):
12
+ """
13
+ _htest - bool, change box location when running htest
14
+ """
15
+ self.master = master
16
+ self._htest = _htest
17
+ self._utest = _utest
18
+ self.init()
19
+
20
+ def settitle(self):
21
+ "Set window titles."
22
+ self.top.wm_title("Path Browser")
23
+ self.top.wm_iconname("Path Browser")
24
+
25
+ def rootnode(self):
26
+ return PathBrowserTreeItem()
27
+
28
+
29
+ class PathBrowserTreeItem(TreeItem):
30
+
31
+ def GetText(self):
32
+ return "sys.path"
33
+
34
+ def GetSubList(self):
35
+ sublist = []
36
+ for dir in sys.path:
37
+ item = DirBrowserTreeItem(dir)
38
+ sublist.append(item)
39
+ return sublist
40
+
41
+
42
+ class DirBrowserTreeItem(TreeItem):
43
+
44
+ def __init__(self, dir, packages=[]):
45
+ self.dir = dir
46
+ self.packages = packages
47
+
48
+ def GetText(self):
49
+ if not self.packages:
50
+ return self.dir
51
+ else:
52
+ return self.packages[-1] + ": package"
53
+
54
+ def GetSubList(self):
55
+ try:
56
+ names = os.listdir(self.dir or os.curdir)
57
+ except OSError:
58
+ return []
59
+ packages = []
60
+ for name in names:
61
+ file = os.path.join(self.dir, name)
62
+ if self.ispackagedir(file):
63
+ nn = os.path.normcase(name)
64
+ packages.append((nn, name, file))
65
+ packages.sort()
66
+ sublist = []
67
+ for nn, name, file in packages:
68
+ item = DirBrowserTreeItem(file, self.packages + [name])
69
+ sublist.append(item)
70
+ for nn, name in self.listmodules(names):
71
+ item = ModuleBrowserTreeItem(os.path.join(self.dir, name))
72
+ sublist.append(item)
73
+ return sublist
74
+
75
+ def ispackagedir(self, file):
76
+ " Return true for directories that are packages."
77
+ if not os.path.isdir(file):
78
+ return False
79
+ init = os.path.join(file, "__init__.py")
80
+ return os.path.exists(init)
81
+
82
+ def listmodules(self, allnames):
83
+ modules = {}
84
+ suffixes = importlib.machinery.EXTENSION_SUFFIXES[:]
85
+ suffixes += importlib.machinery.SOURCE_SUFFIXES
86
+ suffixes += importlib.machinery.BYTECODE_SUFFIXES
87
+ sorted = []
88
+ for suff in suffixes:
89
+ i = -len(suff)
90
+ for name in allnames[:]:
91
+ normed_name = os.path.normcase(name)
92
+ if normed_name[i:] == suff:
93
+ mod_name = name[:i]
94
+ if mod_name not in modules:
95
+ modules[mod_name] = None
96
+ sorted.append((normed_name, name))
97
+ allnames.remove(name)
98
+ sorted.sort()
99
+ return sorted
100
+
101
+
102
+ def _path_browser(parent): # htest #
103
+ PathBrowser(parent, _htest=True)
104
+ parent.mainloop()
105
+
106
+ if __name__ == "__main__":
107
+ from unittest import main
108
+ main('idlelib.idle_test.test_pathbrowser', verbosity=2, exit=False)
109
+
110
+ from idlelib.idle_test.htest import run
111
+ run(_path_browser)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/pyparse.py ADDED
@@ -0,0 +1,593 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Define partial Python code Parser used by editor and hyperparser.
2
+
3
+ Instances of ParseMap are used with str.translate.
4
+
5
+ The following bound search and match functions are defined:
6
+ _synchre - start of popular statement;
7
+ _junkre - whitespace or comment line;
8
+ _match_stringre: string, possibly without closer;
9
+ _itemre - line that may have bracket structure start;
10
+ _closere - line that must be followed by dedent.
11
+ _chew_ordinaryre - non-special characters.
12
+ """
13
+ import re
14
+
15
+ # Reason last statement is continued (or C_NONE if it's not).
16
+ (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE,
17
+ C_STRING_NEXT_LINES, C_BRACKET) = range(5)
18
+
19
+ # Find what looks like the start of a popular statement.
20
+
21
+ _synchre = re.compile(r"""
22
+ ^
23
+ [ \t]*
24
+ (?: while
25
+ | else
26
+ | def
27
+ | return
28
+ | assert
29
+ | break
30
+ | class
31
+ | continue
32
+ | elif
33
+ | try
34
+ | except
35
+ | raise
36
+ | import
37
+ | yield
38
+ )
39
+ \b
40
+ """, re.VERBOSE | re.MULTILINE).search
41
+
42
+ # Match blank line or non-indenting comment line.
43
+
44
+ _junkre = re.compile(r"""
45
+ [ \t]*
46
+ (?: \# \S .* )?
47
+ \n
48
+ """, re.VERBOSE).match
49
+
50
+ # Match any flavor of string; the terminating quote is optional
51
+ # so that we're robust in the face of incomplete program text.
52
+
53
+ _match_stringre = re.compile(r"""
54
+ \""" [^"\\]* (?:
55
+ (?: \\. | "(?!"") )
56
+ [^"\\]*
57
+ )*
58
+ (?: \""" )?
59
+
60
+ | " [^"\\\n]* (?: \\. [^"\\\n]* )* "?
61
+
62
+ | ''' [^'\\]* (?:
63
+ (?: \\. | '(?!'') )
64
+ [^'\\]*
65
+ )*
66
+ (?: ''' )?
67
+
68
+ | ' [^'\\\n]* (?: \\. [^'\\\n]* )* '?
69
+ """, re.VERBOSE | re.DOTALL).match
70
+
71
+ # Match a line that starts with something interesting;
72
+ # used to find the first item of a bracket structure.
73
+
74
+ _itemre = re.compile(r"""
75
+ [ \t]*
76
+ [^\s#\\] # if we match, m.end()-1 is the interesting char
77
+ """, re.VERBOSE).match
78
+
79
+ # Match start of statements that should be followed by a dedent.
80
+
81
+ _closere = re.compile(r"""
82
+ \s*
83
+ (?: return
84
+ | break
85
+ | continue
86
+ | raise
87
+ | pass
88
+ )
89
+ \b
90
+ """, re.VERBOSE).match
91
+
92
+ # Chew up non-special chars as quickly as possible. If match is
93
+ # successful, m.end() less 1 is the index of the last boring char
94
+ # matched. If match is unsuccessful, the string starts with an
95
+ # interesting char.
96
+
97
+ _chew_ordinaryre = re.compile(r"""
98
+ [^[\](){}#'"\\]+
99
+ """, re.VERBOSE).match
100
+
101
+
102
+ class ParseMap(dict):
103
+ r"""Dict subclass that maps anything not in dict to 'x'.
104
+
105
+ This is designed to be used with str.translate in study1.
106
+ Anything not specifically mapped otherwise becomes 'x'.
107
+ Example: replace everything except whitespace with 'x'.
108
+
109
+ >>> keepwhite = ParseMap((ord(c), ord(c)) for c in ' \t\n\r')
110
+ >>> "a + b\tc\nd".translate(keepwhite)
111
+ 'x x x\tx\nx'
112
+ """
113
+ # Calling this triples access time; see bpo-32940
114
+ def __missing__(self, key):
115
+ return 120 # ord('x')
116
+
117
+
118
+ # Map all ascii to 120 to avoid __missing__ call, then replace some.
119
+ trans = ParseMap.fromkeys(range(128), 120)
120
+ trans.update((ord(c), ord('(')) for c in "({[") # open brackets => '(';
121
+ trans.update((ord(c), ord(')')) for c in ")}]") # close brackets => ')'.
122
+ trans.update((ord(c), ord(c)) for c in "\"'\\\n#") # Keep these.
123
+
124
+
125
+ class Parser:
126
+
127
+ def __init__(self, indentwidth, tabwidth):
128
+ self.indentwidth = indentwidth
129
+ self.tabwidth = tabwidth
130
+
131
+ def set_code(self, s):
132
+ assert len(s) == 0 or s[-1] == '\n'
133
+ self.code = s
134
+ self.study_level = 0
135
+
136
+ def find_good_parse_start(self, is_char_in_string):
137
+ """
138
+ Return index of a good place to begin parsing, as close to the
139
+ end of the string as possible. This will be the start of some
140
+ popular stmt like "if" or "def". Return None if none found:
141
+ the caller should pass more prior context then, if possible, or
142
+ if not (the entire program text up until the point of interest
143
+ has already been tried) pass 0 to set_lo().
144
+
145
+ This will be reliable iff given a reliable is_char_in_string()
146
+ function, meaning that when it says "no", it's absolutely
147
+ guaranteed that the char is not in a string.
148
+ """
149
+ code, pos = self.code, None
150
+
151
+ # Peek back from the end for a good place to start,
152
+ # but don't try too often; pos will be left None, or
153
+ # bumped to a legitimate synch point.
154
+ limit = len(code)
155
+ for tries in range(5):
156
+ i = code.rfind(":\n", 0, limit)
157
+ if i < 0:
158
+ break
159
+ i = code.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0)
160
+ m = _synchre(code, i, limit)
161
+ if m and not is_char_in_string(m.start()):
162
+ pos = m.start()
163
+ break
164
+ limit = i
165
+ if pos is None:
166
+ # Nothing looks like a block-opener, or stuff does
167
+ # but is_char_in_string keeps returning true; most likely
168
+ # we're in or near a giant string, the colorizer hasn't
169
+ # caught up enough to be helpful, or there simply *aren't*
170
+ # any interesting stmts. In any of these cases we're
171
+ # going to have to parse the whole thing to be sure, so
172
+ # give it one last try from the start, but stop wasting
173
+ # time here regardless of the outcome.
174
+ m = _synchre(code)
175
+ if m and not is_char_in_string(m.start()):
176
+ pos = m.start()
177
+ return pos
178
+
179
+ # Peeking back worked; look forward until _synchre no longer
180
+ # matches.
181
+ i = pos + 1
182
+ while 1:
183
+ m = _synchre(code, i)
184
+ if m:
185
+ s, i = m.span()
186
+ if not is_char_in_string(s):
187
+ pos = s
188
+ else:
189
+ break
190
+ return pos
191
+
192
+ def set_lo(self, lo):
193
+ """ Throw away the start of the string.
194
+
195
+ Intended to be called with the result of find_good_parse_start().
196
+ """
197
+ assert lo == 0 or self.code[lo-1] == '\n'
198
+ if lo > 0:
199
+ self.code = self.code[lo:]
200
+
201
+ def _study1(self):
202
+ """Find the line numbers of non-continuation lines.
203
+
204
+ As quickly as humanly possible <wink>, find the line numbers (0-
205
+ based) of the non-continuation lines.
206
+ Creates self.{goodlines, continuation}.
207
+ """
208
+ if self.study_level >= 1:
209
+ return
210
+ self.study_level = 1
211
+
212
+ # Map all uninteresting characters to "x", all open brackets
213
+ # to "(", all close brackets to ")", then collapse runs of
214
+ # uninteresting characters. This can cut the number of chars
215
+ # by a factor of 10-40, and so greatly speed the following loop.
216
+ code = self.code
217
+ code = code.translate(trans)
218
+ code = code.replace('xxxxxxxx', 'x')
219
+ code = code.replace('xxxx', 'x')
220
+ code = code.replace('xx', 'x')
221
+ code = code.replace('xx', 'x')
222
+ code = code.replace('\nx', '\n')
223
+ # Replacing x\n with \n would be incorrect because
224
+ # x may be preceded by a backslash.
225
+
226
+ # March over the squashed version of the program, accumulating
227
+ # the line numbers of non-continued stmts, and determining
228
+ # whether & why the last stmt is a continuation.
229
+ continuation = C_NONE
230
+ level = lno = 0 # level is nesting level; lno is line number
231
+ self.goodlines = goodlines = [0]
232
+ push_good = goodlines.append
233
+ i, n = 0, len(code)
234
+ while i < n:
235
+ ch = code[i]
236
+ i = i+1
237
+
238
+ # cases are checked in decreasing order of frequency
239
+ if ch == 'x':
240
+ continue
241
+
242
+ if ch == '\n':
243
+ lno = lno + 1
244
+ if level == 0:
245
+ push_good(lno)
246
+ # else we're in an unclosed bracket structure
247
+ continue
248
+
249
+ if ch == '(':
250
+ level = level + 1
251
+ continue
252
+
253
+ if ch == ')':
254
+ if level:
255
+ level = level - 1
256
+ # else the program is invalid, but we can't complain
257
+ continue
258
+
259
+ if ch == '"' or ch == "'":
260
+ # consume the string
261
+ quote = ch
262
+ if code[i-1:i+2] == quote * 3:
263
+ quote = quote * 3
264
+ firstlno = lno
265
+ w = len(quote) - 1
266
+ i = i+w
267
+ while i < n:
268
+ ch = code[i]
269
+ i = i+1
270
+
271
+ if ch == 'x':
272
+ continue
273
+
274
+ if code[i-1:i+w] == quote:
275
+ i = i+w
276
+ break
277
+
278
+ if ch == '\n':
279
+ lno = lno + 1
280
+ if w == 0:
281
+ # unterminated single-quoted string
282
+ if level == 0:
283
+ push_good(lno)
284
+ break
285
+ continue
286
+
287
+ if ch == '\\':
288
+ assert i < n
289
+ if code[i] == '\n':
290
+ lno = lno + 1
291
+ i = i+1
292
+ continue
293
+
294
+ # else comment char or paren inside string
295
+
296
+ else:
297
+ # didn't break out of the loop, so we're still
298
+ # inside a string
299
+ if (lno - 1) == firstlno:
300
+ # before the previous \n in code, we were in the first
301
+ # line of the string
302
+ continuation = C_STRING_FIRST_LINE
303
+ else:
304
+ continuation = C_STRING_NEXT_LINES
305
+ continue # with outer loop
306
+
307
+ if ch == '#':
308
+ # consume the comment
309
+ i = code.find('\n', i)
310
+ assert i >= 0
311
+ continue
312
+
313
+ assert ch == '\\'
314
+ assert i < n
315
+ if code[i] == '\n':
316
+ lno = lno + 1
317
+ if i+1 == n:
318
+ continuation = C_BACKSLASH
319
+ i = i+1
320
+
321
+ # The last stmt may be continued for all 3 reasons.
322
+ # String continuation takes precedence over bracket
323
+ # continuation, which beats backslash continuation.
324
+ if (continuation != C_STRING_FIRST_LINE
325
+ and continuation != C_STRING_NEXT_LINES and level > 0):
326
+ continuation = C_BRACKET
327
+ self.continuation = continuation
328
+
329
+ # Push the final line number as a sentinel value, regardless of
330
+ # whether it's continued.
331
+ assert (continuation == C_NONE) == (goodlines[-1] == lno)
332
+ if goodlines[-1] != lno:
333
+ push_good(lno)
334
+
335
+ def get_continuation_type(self):
336
+ self._study1()
337
+ return self.continuation
338
+
339
+ def _study2(self):
340
+ """
341
+ study1 was sufficient to determine the continuation status,
342
+ but doing more requires looking at every character. study2
343
+ does this for the last interesting statement in the block.
344
+ Creates:
345
+ self.stmt_start, stmt_end
346
+ slice indices of last interesting stmt
347
+ self.stmt_bracketing
348
+ the bracketing structure of the last interesting stmt; for
349
+ example, for the statement "say(boo) or die",
350
+ stmt_bracketing will be ((0, 0), (0, 1), (2, 0), (2, 1),
351
+ (4, 0)). Strings and comments are treated as brackets, for
352
+ the matter.
353
+ self.lastch
354
+ last interesting character before optional trailing comment
355
+ self.lastopenbracketpos
356
+ if continuation is C_BRACKET, index of last open bracket
357
+ """
358
+ if self.study_level >= 2:
359
+ return
360
+ self._study1()
361
+ self.study_level = 2
362
+
363
+ # Set p and q to slice indices of last interesting stmt.
364
+ code, goodlines = self.code, self.goodlines
365
+ i = len(goodlines) - 1 # Index of newest line.
366
+ p = len(code) # End of goodlines[i]
367
+ while i:
368
+ assert p
369
+ # Make p be the index of the stmt at line number goodlines[i].
370
+ # Move p back to the stmt at line number goodlines[i-1].
371
+ q = p
372
+ for nothing in range(goodlines[i-1], goodlines[i]):
373
+ # tricky: sets p to 0 if no preceding newline
374
+ p = code.rfind('\n', 0, p-1) + 1
375
+ # The stmt code[p:q] isn't a continuation, but may be blank
376
+ # or a non-indenting comment line.
377
+ if _junkre(code, p):
378
+ i = i-1
379
+ else:
380
+ break
381
+ if i == 0:
382
+ # nothing but junk!
383
+ assert p == 0
384
+ q = p
385
+ self.stmt_start, self.stmt_end = p, q
386
+
387
+ # Analyze this stmt, to find the last open bracket (if any)
388
+ # and last interesting character (if any).
389
+ lastch = ""
390
+ stack = [] # stack of open bracket indices
391
+ push_stack = stack.append
392
+ bracketing = [(p, 0)]
393
+ while p < q:
394
+ # suck up all except ()[]{}'"#\\
395
+ m = _chew_ordinaryre(code, p, q)
396
+ if m:
397
+ # we skipped at least one boring char
398
+ newp = m.end()
399
+ # back up over totally boring whitespace
400
+ i = newp - 1 # index of last boring char
401
+ while i >= p and code[i] in " \t\n":
402
+ i = i-1
403
+ if i >= p:
404
+ lastch = code[i]
405
+ p = newp
406
+ if p >= q:
407
+ break
408
+
409
+ ch = code[p]
410
+
411
+ if ch in "([{":
412
+ push_stack(p)
413
+ bracketing.append((p, len(stack)))
414
+ lastch = ch
415
+ p = p+1
416
+ continue
417
+
418
+ if ch in ")]}":
419
+ if stack:
420
+ del stack[-1]
421
+ lastch = ch
422
+ p = p+1
423
+ bracketing.append((p, len(stack)))
424
+ continue
425
+
426
+ if ch == '"' or ch == "'":
427
+ # consume string
428
+ # Note that study1 did this with a Python loop, but
429
+ # we use a regexp here; the reason is speed in both
430
+ # cases; the string may be huge, but study1 pre-squashed
431
+ # strings to a couple of characters per line. study1
432
+ # also needed to keep track of newlines, and we don't
433
+ # have to.
434
+ bracketing.append((p, len(stack)+1))
435
+ lastch = ch
436
+ p = _match_stringre(code, p, q).end()
437
+ bracketing.append((p, len(stack)))
438
+ continue
439
+
440
+ if ch == '#':
441
+ # consume comment and trailing newline
442
+ bracketing.append((p, len(stack)+1))
443
+ p = code.find('\n', p, q) + 1
444
+ assert p > 0
445
+ bracketing.append((p, len(stack)))
446
+ continue
447
+
448
+ assert ch == '\\'
449
+ p = p+1 # beyond backslash
450
+ assert p < q
451
+ if code[p] != '\n':
452
+ # the program is invalid, but can't complain
453
+ lastch = ch + code[p]
454
+ p = p+1 # beyond escaped char
455
+
456
+ # end while p < q:
457
+
458
+ self.lastch = lastch
459
+ self.lastopenbracketpos = stack[-1] if stack else None
460
+ self.stmt_bracketing = tuple(bracketing)
461
+
462
+ def compute_bracket_indent(self):
463
+ """Return number of spaces the next line should be indented.
464
+
465
+ Line continuation must be C_BRACKET.
466
+ """
467
+ self._study2()
468
+ assert self.continuation == C_BRACKET
469
+ j = self.lastopenbracketpos
470
+ code = self.code
471
+ n = len(code)
472
+ origi = i = code.rfind('\n', 0, j) + 1
473
+ j = j+1 # one beyond open bracket
474
+ # find first list item; set i to start of its line
475
+ while j < n:
476
+ m = _itemre(code, j)
477
+ if m:
478
+ j = m.end() - 1 # index of first interesting char
479
+ extra = 0
480
+ break
481
+ else:
482
+ # this line is junk; advance to next line
483
+ i = j = code.find('\n', j) + 1
484
+ else:
485
+ # nothing interesting follows the bracket;
486
+ # reproduce the bracket line's indentation + a level
487
+ j = i = origi
488
+ while code[j] in " \t":
489
+ j = j+1
490
+ extra = self.indentwidth
491
+ return len(code[i:j].expandtabs(self.tabwidth)) + extra
492
+
493
+ def get_num_lines_in_stmt(self):
494
+ """Return number of physical lines in last stmt.
495
+
496
+ The statement doesn't have to be an interesting statement. This is
497
+ intended to be called when continuation is C_BACKSLASH.
498
+ """
499
+ self._study1()
500
+ goodlines = self.goodlines
501
+ return goodlines[-1] - goodlines[-2]
502
+
503
+ def compute_backslash_indent(self):
504
+ """Return number of spaces the next line should be indented.
505
+
506
+ Line continuation must be C_BACKSLASH. Also assume that the new
507
+ line is the first one following the initial line of the stmt.
508
+ """
509
+ self._study2()
510
+ assert self.continuation == C_BACKSLASH
511
+ code = self.code
512
+ i = self.stmt_start
513
+ while code[i] in " \t":
514
+ i = i+1
515
+ startpos = i
516
+
517
+ # See whether the initial line starts an assignment stmt; i.e.,
518
+ # look for an = operator
519
+ endpos = code.find('\n', startpos) + 1
520
+ found = level = 0
521
+ while i < endpos:
522
+ ch = code[i]
523
+ if ch in "([{":
524
+ level = level + 1
525
+ i = i+1
526
+ elif ch in ")]}":
527
+ if level:
528
+ level = level - 1
529
+ i = i+1
530
+ elif ch == '"' or ch == "'":
531
+ i = _match_stringre(code, i, endpos).end()
532
+ elif ch == '#':
533
+ # This line is unreachable because the # makes a comment of
534
+ # everything after it.
535
+ break
536
+ elif level == 0 and ch == '=' and \
537
+ (i == 0 or code[i-1] not in "=<>!") and \
538
+ code[i+1] != '=':
539
+ found = 1
540
+ break
541
+ else:
542
+ i = i+1
543
+
544
+ if found:
545
+ # found a legit =, but it may be the last interesting
546
+ # thing on the line
547
+ i = i+1 # move beyond the =
548
+ found = re.match(r"\s*\\", code[i:endpos]) is None
549
+
550
+ if not found:
551
+ # oh well ... settle for moving beyond the first chunk
552
+ # of non-whitespace chars
553
+ i = startpos
554
+ while code[i] not in " \t\n":
555
+ i = i+1
556
+
557
+ return len(code[self.stmt_start:i].expandtabs(\
558
+ self.tabwidth)) + 1
559
+
560
+ def get_base_indent_string(self):
561
+ """Return the leading whitespace on the initial line of the last
562
+ interesting stmt.
563
+ """
564
+ self._study2()
565
+ i, n = self.stmt_start, self.stmt_end
566
+ j = i
567
+ code = self.code
568
+ while j < n and code[j] in " \t":
569
+ j = j + 1
570
+ return code[i:j]
571
+
572
+ def is_block_opener(self):
573
+ "Return True if the last interesting statement opens a block."
574
+ self._study2()
575
+ return self.lastch == ':'
576
+
577
+ def is_block_closer(self):
578
+ "Return True if the last interesting statement closes a block."
579
+ self._study2()
580
+ return _closere(self.code, self.stmt_start) is not None
581
+
582
+ def get_last_stmt_bracketing(self):
583
+ """Return bracketing structure of the last interesting statement.
584
+
585
+ The returned tuple is in the format defined in _study2().
586
+ """
587
+ self._study2()
588
+ return self.stmt_bracketing
589
+
590
+
591
+ if __name__ == '__main__':
592
+ from unittest import main
593
+ main('idlelib.idle_test.test_pyparse', verbosity=2)
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/pyshell.py ADDED
@@ -0,0 +1,1579 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #! /usr/bin/env python3
2
+
3
+ import sys
4
+ if __name__ == "__main__":
5
+ sys.modules['idlelib.pyshell'] = sys.modules['__main__']
6
+
7
+ try:
8
+ from tkinter import *
9
+ except ImportError:
10
+ print("** IDLE can't import Tkinter.\n"
11
+ "Your Python may not be configured for Tk. **", file=sys.__stderr__)
12
+ raise SystemExit(1)
13
+
14
+ # Valid arguments for the ...Awareness call below are defined in the following.
15
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx
16
+ if sys.platform == 'win32':
17
+ try:
18
+ import ctypes
19
+ PROCESS_SYSTEM_DPI_AWARE = 1 # Int required.
20
+ ctypes.OleDLL('shcore').SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE)
21
+ except (ImportError, AttributeError, OSError):
22
+ pass
23
+
24
+ from tkinter import messagebox
25
+ if TkVersion < 8.5:
26
+ root = Tk() # otherwise create root in main
27
+ root.withdraw()
28
+ from idlelib.run import fix_scaling
29
+ fix_scaling(root)
30
+ messagebox.showerror("Idle Cannot Start",
31
+ "Idle requires tcl/tk 8.5+, not %s." % TkVersion,
32
+ parent=root)
33
+ raise SystemExit(1)
34
+
35
+ from code import InteractiveInterpreter
36
+ import linecache
37
+ import os
38
+ import os.path
39
+ from platform import python_version
40
+ import re
41
+ import socket
42
+ import subprocess
43
+ from textwrap import TextWrapper
44
+ import threading
45
+ import time
46
+ import tokenize
47
+ import warnings
48
+
49
+ from idlelib.colorizer import ColorDelegator
50
+ from idlelib.config import idleConf
51
+ from idlelib import debugger
52
+ from idlelib import debugger_r
53
+ from idlelib.editor import EditorWindow, fixwordbreaks
54
+ from idlelib.filelist import FileList
55
+ from idlelib.outwin import OutputWindow
56
+ from idlelib import rpc
57
+ from idlelib.run import idle_formatwarning, StdInputFile, StdOutputFile
58
+ from idlelib.undo import UndoDelegator
59
+
60
+ HOST = '127.0.0.1' # python execution server on localhost loopback
61
+ PORT = 0 # someday pass in host, port for remote debug capability
62
+
63
+ # Override warnings module to write to warning_stream. Initialize to send IDLE
64
+ # internal warnings to the console. ScriptBinding.check_syntax() will
65
+ # temporarily redirect the stream to the shell window to display warnings when
66
+ # checking user's code.
67
+ warning_stream = sys.__stderr__ # None, at least on Windows, if no console.
68
+
69
+ def idle_showwarning(
70
+ message, category, filename, lineno, file=None, line=None):
71
+ """Show Idle-format warning (after replacing warnings.showwarning).
72
+
73
+ The differences are the formatter called, the file=None replacement,
74
+ which can be None, the capture of the consequence AttributeError,
75
+ and the output of a hard-coded prompt.
76
+ """
77
+ if file is None:
78
+ file = warning_stream
79
+ try:
80
+ file.write(idle_formatwarning(
81
+ message, category, filename, lineno, line=line))
82
+ file.write(">>> ")
83
+ except (AttributeError, OSError):
84
+ pass # if file (probably __stderr__) is invalid, skip warning.
85
+
86
+ _warnings_showwarning = None
87
+
88
+ def capture_warnings(capture):
89
+ "Replace warning.showwarning with idle_showwarning, or reverse."
90
+
91
+ global _warnings_showwarning
92
+ if capture:
93
+ if _warnings_showwarning is None:
94
+ _warnings_showwarning = warnings.showwarning
95
+ warnings.showwarning = idle_showwarning
96
+ else:
97
+ if _warnings_showwarning is not None:
98
+ warnings.showwarning = _warnings_showwarning
99
+ _warnings_showwarning = None
100
+
101
+ capture_warnings(True)
102
+
103
+ def extended_linecache_checkcache(filename=None,
104
+ orig_checkcache=linecache.checkcache):
105
+ """Extend linecache.checkcache to preserve the <pyshell#...> entries
106
+
107
+ Rather than repeating the linecache code, patch it to save the
108
+ <pyshell#...> entries, call the original linecache.checkcache()
109
+ (skipping them), and then restore the saved entries.
110
+
111
+ orig_checkcache is bound at definition time to the original
112
+ method, allowing it to be patched.
113
+ """
114
+ cache = linecache.cache
115
+ save = {}
116
+ for key in list(cache):
117
+ if key[:1] + key[-1:] == '<>':
118
+ save[key] = cache.pop(key)
119
+ orig_checkcache(filename)
120
+ cache.update(save)
121
+
122
+ # Patch linecache.checkcache():
123
+ linecache.checkcache = extended_linecache_checkcache
124
+
125
+
126
+ class PyShellEditorWindow(EditorWindow):
127
+ "Regular text edit window in IDLE, supports breakpoints"
128
+
129
+ def __init__(self, *args):
130
+ self.breakpoints = []
131
+ EditorWindow.__init__(self, *args)
132
+ self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
133
+ self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
134
+ self.text.bind("<<open-python-shell>>", self.flist.open_shell)
135
+
136
+ #TODO: don't read/write this from/to .idlerc when testing
137
+ self.breakpointPath = os.path.join(
138
+ idleConf.userdir, 'breakpoints.lst')
139
+ # whenever a file is changed, restore breakpoints
140
+ def filename_changed_hook(old_hook=self.io.filename_change_hook,
141
+ self=self):
142
+ self.restore_file_breaks()
143
+ old_hook()
144
+ self.io.set_filename_change_hook(filename_changed_hook)
145
+ if self.io.filename:
146
+ self.restore_file_breaks()
147
+ self.color_breakpoint_text()
148
+
149
+ rmenu_specs = [
150
+ ("Cut", "<<cut>>", "rmenu_check_cut"),
151
+ ("Copy", "<<copy>>", "rmenu_check_copy"),
152
+ ("Paste", "<<paste>>", "rmenu_check_paste"),
153
+ (None, None, None),
154
+ ("Set Breakpoint", "<<set-breakpoint-here>>", None),
155
+ ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
156
+ ]
157
+
158
+ def color_breakpoint_text(self, color=True):
159
+ "Turn colorizing of breakpoint text on or off"
160
+ if self.io is None:
161
+ # possible due to update in restore_file_breaks
162
+ return
163
+ if color:
164
+ theme = idleConf.CurrentTheme()
165
+ cfg = idleConf.GetHighlight(theme, "break")
166
+ else:
167
+ cfg = {'foreground': '', 'background': ''}
168
+ self.text.tag_config('BREAK', cfg)
169
+
170
+ def set_breakpoint(self, lineno):
171
+ text = self.text
172
+ filename = self.io.filename
173
+ text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
174
+ try:
175
+ self.breakpoints.index(lineno)
176
+ except ValueError: # only add if missing, i.e. do once
177
+ self.breakpoints.append(lineno)
178
+ try: # update the subprocess debugger
179
+ debug = self.flist.pyshell.interp.debugger
180
+ debug.set_breakpoint_here(filename, lineno)
181
+ except: # but debugger may not be active right now....
182
+ pass
183
+
184
+ def set_breakpoint_here(self, event=None):
185
+ text = self.text
186
+ filename = self.io.filename
187
+ if not filename:
188
+ text.bell()
189
+ return
190
+ lineno = int(float(text.index("insert")))
191
+ self.set_breakpoint(lineno)
192
+
193
+ def clear_breakpoint_here(self, event=None):
194
+ text = self.text
195
+ filename = self.io.filename
196
+ if not filename:
197
+ text.bell()
198
+ return
199
+ lineno = int(float(text.index("insert")))
200
+ try:
201
+ self.breakpoints.remove(lineno)
202
+ except:
203
+ pass
204
+ text.tag_remove("BREAK", "insert linestart",\
205
+ "insert lineend +1char")
206
+ try:
207
+ debug = self.flist.pyshell.interp.debugger
208
+ debug.clear_breakpoint_here(filename, lineno)
209
+ except:
210
+ pass
211
+
212
+ def clear_file_breaks(self):
213
+ if self.breakpoints:
214
+ text = self.text
215
+ filename = self.io.filename
216
+ if not filename:
217
+ text.bell()
218
+ return
219
+ self.breakpoints = []
220
+ text.tag_remove("BREAK", "1.0", END)
221
+ try:
222
+ debug = self.flist.pyshell.interp.debugger
223
+ debug.clear_file_breaks(filename)
224
+ except:
225
+ pass
226
+
227
+ def store_file_breaks(self):
228
+ "Save breakpoints when file is saved"
229
+ # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
230
+ # be run. The breaks are saved at that time. If we introduce
231
+ # a temporary file save feature the save breaks functionality
232
+ # needs to be re-verified, since the breaks at the time the
233
+ # temp file is created may differ from the breaks at the last
234
+ # permanent save of the file. Currently, a break introduced
235
+ # after a save will be effective, but not persistent.
236
+ # This is necessary to keep the saved breaks synched with the
237
+ # saved file.
238
+ #
239
+ # Breakpoints are set as tagged ranges in the text.
240
+ # Since a modified file has to be saved before it is
241
+ # run, and since self.breakpoints (from which the subprocess
242
+ # debugger is loaded) is updated during the save, the visible
243
+ # breaks stay synched with the subprocess even if one of these
244
+ # unexpected breakpoint deletions occurs.
245
+ breaks = self.breakpoints
246
+ filename = self.io.filename
247
+ try:
248
+ with open(self.breakpointPath, "r") as fp:
249
+ lines = fp.readlines()
250
+ except OSError:
251
+ lines = []
252
+ try:
253
+ with open(self.breakpointPath, "w") as new_file:
254
+ for line in lines:
255
+ if not line.startswith(filename + '='):
256
+ new_file.write(line)
257
+ self.update_breakpoints()
258
+ breaks = self.breakpoints
259
+ if breaks:
260
+ new_file.write(filename + '=' + str(breaks) + '\n')
261
+ except OSError as err:
262
+ if not getattr(self.root, "breakpoint_error_displayed", False):
263
+ self.root.breakpoint_error_displayed = True
264
+ messagebox.showerror(title='IDLE Error',
265
+ message='Unable to update breakpoint list:\n%s'
266
+ % str(err),
267
+ parent=self.text)
268
+
269
+ def restore_file_breaks(self):
270
+ self.text.update() # this enables setting "BREAK" tags to be visible
271
+ if self.io is None:
272
+ # can happen if IDLE closes due to the .update() call
273
+ return
274
+ filename = self.io.filename
275
+ if filename is None:
276
+ return
277
+ if os.path.isfile(self.breakpointPath):
278
+ with open(self.breakpointPath, "r") as fp:
279
+ lines = fp.readlines()
280
+ for line in lines:
281
+ if line.startswith(filename + '='):
282
+ breakpoint_linenumbers = eval(line[len(filename)+1:])
283
+ for breakpoint_linenumber in breakpoint_linenumbers:
284
+ self.set_breakpoint(breakpoint_linenumber)
285
+
286
+ def update_breakpoints(self):
287
+ "Retrieves all the breakpoints in the current window"
288
+ text = self.text
289
+ ranges = text.tag_ranges("BREAK")
290
+ linenumber_list = self.ranges_to_linenumbers(ranges)
291
+ self.breakpoints = linenumber_list
292
+
293
+ def ranges_to_linenumbers(self, ranges):
294
+ lines = []
295
+ for index in range(0, len(ranges), 2):
296
+ lineno = int(float(ranges[index].string))
297
+ end = int(float(ranges[index+1].string))
298
+ while lineno < end:
299
+ lines.append(lineno)
300
+ lineno += 1
301
+ return lines
302
+
303
+ # XXX 13 Dec 2002 KBK Not used currently
304
+ # def saved_change_hook(self):
305
+ # "Extend base method - clear breaks if module is modified"
306
+ # if not self.get_saved():
307
+ # self.clear_file_breaks()
308
+ # EditorWindow.saved_change_hook(self)
309
+
310
+ def _close(self):
311
+ "Extend base method - clear breaks when module is closed"
312
+ self.clear_file_breaks()
313
+ EditorWindow._close(self)
314
+
315
+
316
+ class PyShellFileList(FileList):
317
+ "Extend base class: IDLE supports a shell and breakpoints"
318
+
319
+ # override FileList's class variable, instances return PyShellEditorWindow
320
+ # instead of EditorWindow when new edit windows are created.
321
+ EditorWindow = PyShellEditorWindow
322
+
323
+ pyshell = None
324
+
325
+ def open_shell(self, event=None):
326
+ if self.pyshell:
327
+ self.pyshell.top.wakeup()
328
+ else:
329
+ self.pyshell = PyShell(self)
330
+ if self.pyshell:
331
+ if not self.pyshell.begin():
332
+ return None
333
+ return self.pyshell
334
+
335
+
336
+ class ModifiedColorDelegator(ColorDelegator):
337
+ "Extend base class: colorizer for the shell window itself"
338
+
339
+ def __init__(self):
340
+ ColorDelegator.__init__(self)
341
+ self.LoadTagDefs()
342
+
343
+ def recolorize_main(self):
344
+ self.tag_remove("TODO", "1.0", "iomark")
345
+ self.tag_add("SYNC", "1.0", "iomark")
346
+ ColorDelegator.recolorize_main(self)
347
+
348
+ def LoadTagDefs(self):
349
+ ColorDelegator.LoadTagDefs(self)
350
+ theme = idleConf.CurrentTheme()
351
+ self.tagdefs.update({
352
+ "stdin": {'background':None,'foreground':None},
353
+ "stdout": idleConf.GetHighlight(theme, "stdout"),
354
+ "stderr": idleConf.GetHighlight(theme, "stderr"),
355
+ "console": idleConf.GetHighlight(theme, "console"),
356
+ })
357
+
358
+ def removecolors(self):
359
+ # Don't remove shell color tags before "iomark"
360
+ for tag in self.tagdefs:
361
+ self.tag_remove(tag, "iomark", "end")
362
+
363
+ class ModifiedUndoDelegator(UndoDelegator):
364
+ "Extend base class: forbid insert/delete before the I/O mark"
365
+
366
+ def insert(self, index, chars, tags=None):
367
+ try:
368
+ if self.delegate.compare(index, "<", "iomark"):
369
+ self.delegate.bell()
370
+ return
371
+ except TclError:
372
+ pass
373
+ UndoDelegator.insert(self, index, chars, tags)
374
+
375
+ def delete(self, index1, index2=None):
376
+ try:
377
+ if self.delegate.compare(index1, "<", "iomark"):
378
+ self.delegate.bell()
379
+ return
380
+ except TclError:
381
+ pass
382
+ UndoDelegator.delete(self, index1, index2)
383
+
384
+
385
+ class MyRPCClient(rpc.RPCClient):
386
+
387
+ def handle_EOF(self):
388
+ "Override the base class - just re-raise EOFError"
389
+ raise EOFError
390
+
391
+ def restart_line(width, filename): # See bpo-38141.
392
+ """Return width long restart line formatted with filename.
393
+
394
+ Fill line with balanced '='s, with any extras and at least one at
395
+ the beginning. Do not end with a trailing space.
396
+ """
397
+ tag = f"= RESTART: {filename or 'Shell'} ="
398
+ if width >= len(tag):
399
+ div, mod = divmod((width -len(tag)), 2)
400
+ return f"{(div+mod)*'='}{tag}{div*'='}"
401
+ else:
402
+ return tag[:-2] # Remove ' ='.
403
+
404
+
405
+ class ModifiedInterpreter(InteractiveInterpreter):
406
+
407
+ def __init__(self, tkconsole):
408
+ self.tkconsole = tkconsole
409
+ locals = sys.modules['__main__'].__dict__
410
+ InteractiveInterpreter.__init__(self, locals=locals)
411
+ self.restarting = False
412
+ self.subprocess_arglist = None
413
+ self.port = PORT
414
+ self.original_compiler_flags = self.compile.compiler.flags
415
+
416
+ _afterid = None
417
+ rpcclt = None
418
+ rpcsubproc = None
419
+
420
+ def spawn_subprocess(self):
421
+ if self.subprocess_arglist is None:
422
+ self.subprocess_arglist = self.build_subprocess_arglist()
423
+ self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
424
+
425
+ def build_subprocess_arglist(self):
426
+ assert (self.port!=0), (
427
+ "Socket should have been assigned a port number.")
428
+ w = ['-W' + s for s in sys.warnoptions]
429
+ # Maybe IDLE is installed and is being accessed via sys.path,
430
+ # or maybe it's not installed and the idle.py script is being
431
+ # run from the IDLE source directory.
432
+ del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
433
+ default=False, type='bool')
434
+ command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
435
+ return [sys.executable] + w + ["-c", command, str(self.port)]
436
+
437
+ def start_subprocess(self):
438
+ addr = (HOST, self.port)
439
+ # GUI makes several attempts to acquire socket, listens for connection
440
+ for i in range(3):
441
+ time.sleep(i)
442
+ try:
443
+ self.rpcclt = MyRPCClient(addr)
444
+ break
445
+ except OSError:
446
+ pass
447
+ else:
448
+ self.display_port_binding_error()
449
+ return None
450
+ # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
451
+ self.port = self.rpcclt.listening_sock.getsockname()[1]
452
+ # if PORT was not 0, probably working with a remote execution server
453
+ if PORT != 0:
454
+ # To allow reconnection within the 2MSL wait (cf. Stevens TCP
455
+ # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
456
+ # on Windows since the implementation allows two active sockets on
457
+ # the same address!
458
+ self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
459
+ socket.SO_REUSEADDR, 1)
460
+ self.spawn_subprocess()
461
+ #time.sleep(20) # test to simulate GUI not accepting connection
462
+ # Accept the connection from the Python execution server
463
+ self.rpcclt.listening_sock.settimeout(10)
464
+ try:
465
+ self.rpcclt.accept()
466
+ except socket.timeout:
467
+ self.display_no_subprocess_error()
468
+ return None
469
+ self.rpcclt.register("console", self.tkconsole)
470
+ self.rpcclt.register("stdin", self.tkconsole.stdin)
471
+ self.rpcclt.register("stdout", self.tkconsole.stdout)
472
+ self.rpcclt.register("stderr", self.tkconsole.stderr)
473
+ self.rpcclt.register("flist", self.tkconsole.flist)
474
+ self.rpcclt.register("linecache", linecache)
475
+ self.rpcclt.register("interp", self)
476
+ self.transfer_path(with_cwd=True)
477
+ self.poll_subprocess()
478
+ return self.rpcclt
479
+
480
+ def restart_subprocess(self, with_cwd=False, filename=''):
481
+ if self.restarting:
482
+ return self.rpcclt
483
+ self.restarting = True
484
+ # close only the subprocess debugger
485
+ debug = self.getdebugger()
486
+ if debug:
487
+ try:
488
+ # Only close subprocess debugger, don't unregister gui_adap!
489
+ debugger_r.close_subprocess_debugger(self.rpcclt)
490
+ except:
491
+ pass
492
+ # Kill subprocess, spawn a new one, accept connection.
493
+ self.rpcclt.close()
494
+ self.terminate_subprocess()
495
+ console = self.tkconsole
496
+ was_executing = console.executing
497
+ console.executing = False
498
+ self.spawn_subprocess()
499
+ try:
500
+ self.rpcclt.accept()
501
+ except socket.timeout:
502
+ self.display_no_subprocess_error()
503
+ return None
504
+ self.transfer_path(with_cwd=with_cwd)
505
+ console.stop_readline()
506
+ # annotate restart in shell window and mark it
507
+ console.text.delete("iomark", "end-1c")
508
+ console.write('\n')
509
+ console.write(restart_line(console.width, filename))
510
+ console.text.mark_set("restart", "end-1c")
511
+ console.text.mark_gravity("restart", "left")
512
+ if not filename:
513
+ console.showprompt()
514
+ # restart subprocess debugger
515
+ if debug:
516
+ # Restarted debugger connects to current instance of debug GUI
517
+ debugger_r.restart_subprocess_debugger(self.rpcclt)
518
+ # reload remote debugger breakpoints for all PyShellEditWindows
519
+ debug.load_breakpoints()
520
+ self.compile.compiler.flags = self.original_compiler_flags
521
+ self.restarting = False
522
+ return self.rpcclt
523
+
524
+ def __request_interrupt(self):
525
+ self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
526
+
527
+ def interrupt_subprocess(self):
528
+ threading.Thread(target=self.__request_interrupt).start()
529
+
530
+ def kill_subprocess(self):
531
+ if self._afterid is not None:
532
+ self.tkconsole.text.after_cancel(self._afterid)
533
+ try:
534
+ self.rpcclt.listening_sock.close()
535
+ except AttributeError: # no socket
536
+ pass
537
+ try:
538
+ self.rpcclt.close()
539
+ except AttributeError: # no socket
540
+ pass
541
+ self.terminate_subprocess()
542
+ self.tkconsole.executing = False
543
+ self.rpcclt = None
544
+
545
+ def terminate_subprocess(self):
546
+ "Make sure subprocess is terminated"
547
+ try:
548
+ self.rpcsubproc.kill()
549
+ except OSError:
550
+ # process already terminated
551
+ return
552
+ else:
553
+ try:
554
+ self.rpcsubproc.wait()
555
+ except OSError:
556
+ return
557
+
558
+ def transfer_path(self, with_cwd=False):
559
+ if with_cwd: # Issue 13506
560
+ path = [''] # include Current Working Directory
561
+ path.extend(sys.path)
562
+ else:
563
+ path = sys.path
564
+
565
+ self.runcommand("""if 1:
566
+ import sys as _sys
567
+ _sys.path = %r
568
+ del _sys
569
+ \n""" % (path,))
570
+
571
+ active_seq = None
572
+
573
+ def poll_subprocess(self):
574
+ clt = self.rpcclt
575
+ if clt is None:
576
+ return
577
+ try:
578
+ response = clt.pollresponse(self.active_seq, wait=0.05)
579
+ except (EOFError, OSError, KeyboardInterrupt):
580
+ # lost connection or subprocess terminated itself, restart
581
+ # [the KBI is from rpc.SocketIO.handle_EOF()]
582
+ if self.tkconsole.closing:
583
+ return
584
+ response = None
585
+ self.restart_subprocess()
586
+ if response:
587
+ self.tkconsole.resetoutput()
588
+ self.active_seq = None
589
+ how, what = response
590
+ console = self.tkconsole.console
591
+ if how == "OK":
592
+ if what is not None:
593
+ print(repr(what), file=console)
594
+ elif how == "EXCEPTION":
595
+ if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
596
+ self.remote_stack_viewer()
597
+ elif how == "ERROR":
598
+ errmsg = "pyshell.ModifiedInterpreter: Subprocess ERROR:\n"
599
+ print(errmsg, what, file=sys.__stderr__)
600
+ print(errmsg, what, file=console)
601
+ # we received a response to the currently active seq number:
602
+ try:
603
+ self.tkconsole.endexecuting()
604
+ except AttributeError: # shell may have closed
605
+ pass
606
+ # Reschedule myself
607
+ if not self.tkconsole.closing:
608
+ self._afterid = self.tkconsole.text.after(
609
+ self.tkconsole.pollinterval, self.poll_subprocess)
610
+
611
+ debugger = None
612
+
613
+ def setdebugger(self, debugger):
614
+ self.debugger = debugger
615
+
616
+ def getdebugger(self):
617
+ return self.debugger
618
+
619
+ def open_remote_stack_viewer(self):
620
+ """Initiate the remote stack viewer from a separate thread.
621
+
622
+ This method is called from the subprocess, and by returning from this
623
+ method we allow the subprocess to unblock. After a bit the shell
624
+ requests the subprocess to open the remote stack viewer which returns a
625
+ static object looking at the last exception. It is queried through
626
+ the RPC mechanism.
627
+
628
+ """
629
+ self.tkconsole.text.after(300, self.remote_stack_viewer)
630
+ return
631
+
632
+ def remote_stack_viewer(self):
633
+ from idlelib import debugobj_r
634
+ oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
635
+ if oid is None:
636
+ self.tkconsole.root.bell()
637
+ return
638
+ item = debugobj_r.StubObjectTreeItem(self.rpcclt, oid)
639
+ from idlelib.tree import ScrolledCanvas, TreeNode
640
+ top = Toplevel(self.tkconsole.root)
641
+ theme = idleConf.CurrentTheme()
642
+ background = idleConf.GetHighlight(theme, 'normal')['background']
643
+ sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
644
+ sc.frame.pack(expand=1, fill="both")
645
+ node = TreeNode(sc.canvas, None, item)
646
+ node.expand()
647
+ # XXX Should GC the remote tree when closing the window
648
+
649
+ gid = 0
650
+
651
+ def execsource(self, source):
652
+ "Like runsource() but assumes complete exec source"
653
+ filename = self.stuffsource(source)
654
+ self.execfile(filename, source)
655
+
656
+ def execfile(self, filename, source=None):
657
+ "Execute an existing file"
658
+ if source is None:
659
+ with tokenize.open(filename) as fp:
660
+ source = fp.read()
661
+ if use_subprocess:
662
+ source = (f"__file__ = r'''{os.path.abspath(filename)}'''\n"
663
+ + source + "\ndel __file__")
664
+ try:
665
+ code = compile(source, filename, "exec")
666
+ except (OverflowError, SyntaxError):
667
+ self.tkconsole.resetoutput()
668
+ print('*** Error in script or command!\n'
669
+ 'Traceback (most recent call last):',
670
+ file=self.tkconsole.stderr)
671
+ InteractiveInterpreter.showsyntaxerror(self, filename)
672
+ self.tkconsole.showprompt()
673
+ else:
674
+ self.runcode(code)
675
+
676
+ def runsource(self, source):
677
+ "Extend base class method: Stuff the source in the line cache first"
678
+ filename = self.stuffsource(source)
679
+ # at the moment, InteractiveInterpreter expects str
680
+ assert isinstance(source, str)
681
+ # InteractiveInterpreter.runsource() calls its runcode() method,
682
+ # which is overridden (see below)
683
+ return InteractiveInterpreter.runsource(self, source, filename)
684
+
685
+ def stuffsource(self, source):
686
+ "Stuff source in the filename cache"
687
+ filename = "<pyshell#%d>" % self.gid
688
+ self.gid = self.gid + 1
689
+ lines = source.split("\n")
690
+ linecache.cache[filename] = len(source)+1, 0, lines, filename
691
+ return filename
692
+
693
+ def prepend_syspath(self, filename):
694
+ "Prepend sys.path with file's directory if not already included"
695
+ self.runcommand("""if 1:
696
+ _filename = %r
697
+ import sys as _sys
698
+ from os.path import dirname as _dirname
699
+ _dir = _dirname(_filename)
700
+ if not _dir in _sys.path:
701
+ _sys.path.insert(0, _dir)
702
+ del _filename, _sys, _dirname, _dir
703
+ \n""" % (filename,))
704
+
705
+ def showsyntaxerror(self, filename=None):
706
+ """Override Interactive Interpreter method: Use Colorizing
707
+
708
+ Color the offending position instead of printing it and pointing at it
709
+ with a caret.
710
+
711
+ """
712
+ tkconsole = self.tkconsole
713
+ text = tkconsole.text
714
+ text.tag_remove("ERROR", "1.0", "end")
715
+ type, value, tb = sys.exc_info()
716
+ msg = getattr(value, 'msg', '') or value or "<no detail available>"
717
+ lineno = getattr(value, 'lineno', '') or 1
718
+ offset = getattr(value, 'offset', '') or 0
719
+ if offset == 0:
720
+ lineno += 1 #mark end of offending line
721
+ if lineno == 1:
722
+ pos = "iomark + %d chars" % (offset-1)
723
+ else:
724
+ pos = "iomark linestart + %d lines + %d chars" % \
725
+ (lineno-1, offset-1)
726
+ tkconsole.colorize_syntax_error(text, pos)
727
+ tkconsole.resetoutput()
728
+ self.write("SyntaxError: %s\n" % msg)
729
+ tkconsole.showprompt()
730
+
731
+ def showtraceback(self):
732
+ "Extend base class method to reset output properly"
733
+ self.tkconsole.resetoutput()
734
+ self.checklinecache()
735
+ InteractiveInterpreter.showtraceback(self)
736
+ if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
737
+ self.tkconsole.open_stack_viewer()
738
+
739
+ def checklinecache(self):
740
+ c = linecache.cache
741
+ for key in list(c.keys()):
742
+ if key[:1] + key[-1:] != "<>":
743
+ del c[key]
744
+
745
+ def runcommand(self, code):
746
+ "Run the code without invoking the debugger"
747
+ # The code better not raise an exception!
748
+ if self.tkconsole.executing:
749
+ self.display_executing_dialog()
750
+ return 0
751
+ if self.rpcclt:
752
+ self.rpcclt.remotequeue("exec", "runcode", (code,), {})
753
+ else:
754
+ exec(code, self.locals)
755
+ return 1
756
+
757
+ def runcode(self, code):
758
+ "Override base class method"
759
+ if self.tkconsole.executing:
760
+ self.restart_subprocess()
761
+ self.checklinecache()
762
+ debugger = self.debugger
763
+ try:
764
+ self.tkconsole.beginexecuting()
765
+ if not debugger and self.rpcclt is not None:
766
+ self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
767
+ (code,), {})
768
+ elif debugger:
769
+ debugger.run(code, self.locals)
770
+ else:
771
+ exec(code, self.locals)
772
+ except SystemExit:
773
+ if not self.tkconsole.closing:
774
+ if messagebox.askyesno(
775
+ "Exit?",
776
+ "Do you want to exit altogether?",
777
+ default="yes",
778
+ parent=self.tkconsole.text):
779
+ raise
780
+ else:
781
+ self.showtraceback()
782
+ else:
783
+ raise
784
+ except:
785
+ if use_subprocess:
786
+ print("IDLE internal error in runcode()",
787
+ file=self.tkconsole.stderr)
788
+ self.showtraceback()
789
+ self.tkconsole.endexecuting()
790
+ else:
791
+ if self.tkconsole.canceled:
792
+ self.tkconsole.canceled = False
793
+ print("KeyboardInterrupt", file=self.tkconsole.stderr)
794
+ else:
795
+ self.showtraceback()
796
+ finally:
797
+ if not use_subprocess:
798
+ try:
799
+ self.tkconsole.endexecuting()
800
+ except AttributeError: # shell may have closed
801
+ pass
802
+
803
+ def write(self, s):
804
+ "Override base class method"
805
+ return self.tkconsole.stderr.write(s)
806
+
807
+ def display_port_binding_error(self):
808
+ messagebox.showerror(
809
+ "Port Binding Error",
810
+ "IDLE can't bind to a TCP/IP port, which is necessary to "
811
+ "communicate with its Python execution server. This might be "
812
+ "because no networking is installed on this computer. "
813
+ "Run IDLE with the -n command line switch to start without a "
814
+ "subprocess and refer to Help/IDLE Help 'Running without a "
815
+ "subprocess' for further details.",
816
+ parent=self.tkconsole.text)
817
+
818
+ def display_no_subprocess_error(self):
819
+ messagebox.showerror(
820
+ "Subprocess Connection Error",
821
+ "IDLE's subprocess didn't make connection.\n"
822
+ "See the 'Startup failure' section of the IDLE doc, online at\n"
823
+ "https://docs.python.org/3/library/idle.html#startup-failure",
824
+ parent=self.tkconsole.text)
825
+
826
+ def display_executing_dialog(self):
827
+ messagebox.showerror(
828
+ "Already executing",
829
+ "The Python Shell window is already executing a command; "
830
+ "please wait until it is finished.",
831
+ parent=self.tkconsole.text)
832
+
833
+
834
+ class PyShell(OutputWindow):
835
+
836
+ shell_title = "IDLE Shell " + python_version()
837
+
838
+ # Override classes
839
+ ColorDelegator = ModifiedColorDelegator
840
+ UndoDelegator = ModifiedUndoDelegator
841
+
842
+ # Override menus
843
+ menu_specs = [
844
+ ("file", "_File"),
845
+ ("edit", "_Edit"),
846
+ ("debug", "_Debug"),
847
+ ("options", "_Options"),
848
+ ("window", "_Window"),
849
+ ("help", "_Help"),
850
+ ]
851
+
852
+ # Extend right-click context menu
853
+ rmenu_specs = OutputWindow.rmenu_specs + [
854
+ ("Squeeze", "<<squeeze-current-text>>"),
855
+ ]
856
+
857
+ allow_line_numbers = False
858
+
859
+ # New classes
860
+ from idlelib.history import History
861
+
862
+ def __init__(self, flist=None):
863
+ if use_subprocess:
864
+ ms = self.menu_specs
865
+ if ms[2][0] != "shell":
866
+ ms.insert(2, ("shell", "She_ll"))
867
+ self.interp = ModifiedInterpreter(self)
868
+ if flist is None:
869
+ root = Tk()
870
+ fixwordbreaks(root)
871
+ root.withdraw()
872
+ flist = PyShellFileList(root)
873
+
874
+ OutputWindow.__init__(self, flist, None, None)
875
+
876
+ self.usetabs = True
877
+ # indentwidth must be 8 when using tabs. See note in EditorWindow:
878
+ self.indentwidth = 8
879
+
880
+ self.sys_ps1 = sys.ps1 if hasattr(sys, 'ps1') else '>>> '
881
+ self.prompt_last_line = self.sys_ps1.split('\n')[-1]
882
+ self.prompt = self.sys_ps1 # Changes when debug active
883
+
884
+ text = self.text
885
+ text.configure(wrap="char")
886
+ text.bind("<<newline-and-indent>>", self.enter_callback)
887
+ text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
888
+ text.bind("<<interrupt-execution>>", self.cancel_callback)
889
+ text.bind("<<end-of-file>>", self.eof_callback)
890
+ text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
891
+ text.bind("<<toggle-debugger>>", self.toggle_debugger)
892
+ text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
893
+ if use_subprocess:
894
+ text.bind("<<view-restart>>", self.view_restart_mark)
895
+ text.bind("<<restart-shell>>", self.restart_shell)
896
+ squeezer = self.Squeezer(self)
897
+ text.bind("<<squeeze-current-text>>",
898
+ squeezer.squeeze_current_text_event)
899
+
900
+ self.save_stdout = sys.stdout
901
+ self.save_stderr = sys.stderr
902
+ self.save_stdin = sys.stdin
903
+ from idlelib import iomenu
904
+ self.stdin = StdInputFile(self, "stdin",
905
+ iomenu.encoding, iomenu.errors)
906
+ self.stdout = StdOutputFile(self, "stdout",
907
+ iomenu.encoding, iomenu.errors)
908
+ self.stderr = StdOutputFile(self, "stderr",
909
+ iomenu.encoding, "backslashreplace")
910
+ self.console = StdOutputFile(self, "console",
911
+ iomenu.encoding, iomenu.errors)
912
+ if not use_subprocess:
913
+ sys.stdout = self.stdout
914
+ sys.stderr = self.stderr
915
+ sys.stdin = self.stdin
916
+ try:
917
+ # page help() text to shell.
918
+ import pydoc # import must be done here to capture i/o rebinding.
919
+ # XXX KBK 27Dec07 use text viewer someday, but must work w/o subproc
920
+ pydoc.pager = pydoc.plainpager
921
+ except:
922
+ sys.stderr = sys.__stderr__
923
+ raise
924
+ #
925
+ self.history = self.History(self.text)
926
+ #
927
+ self.pollinterval = 50 # millisec
928
+
929
+ def get_standard_extension_names(self):
930
+ return idleConf.GetExtensions(shell_only=True)
931
+
932
+ reading = False
933
+ executing = False
934
+ canceled = False
935
+ endoffile = False
936
+ closing = False
937
+ _stop_readline_flag = False
938
+
939
+ def set_warning_stream(self, stream):
940
+ global warning_stream
941
+ warning_stream = stream
942
+
943
+ def get_warning_stream(self):
944
+ return warning_stream
945
+
946
+ def toggle_debugger(self, event=None):
947
+ if self.executing:
948
+ messagebox.showerror("Don't debug now",
949
+ "You can only toggle the debugger when idle",
950
+ parent=self.text)
951
+ self.set_debugger_indicator()
952
+ return "break"
953
+ else:
954
+ db = self.interp.getdebugger()
955
+ if db:
956
+ self.close_debugger()
957
+ else:
958
+ self.open_debugger()
959
+
960
+ def set_debugger_indicator(self):
961
+ db = self.interp.getdebugger()
962
+ self.setvar("<<toggle-debugger>>", not not db)
963
+
964
+ def toggle_jit_stack_viewer(self, event=None):
965
+ pass # All we need is the variable
966
+
967
+ def close_debugger(self):
968
+ db = self.interp.getdebugger()
969
+ if db:
970
+ self.interp.setdebugger(None)
971
+ db.close()
972
+ if self.interp.rpcclt:
973
+ debugger_r.close_remote_debugger(self.interp.rpcclt)
974
+ self.resetoutput()
975
+ self.console.write("[DEBUG OFF]\n")
976
+ self.prompt = self.sys_ps1
977
+ self.showprompt()
978
+ self.set_debugger_indicator()
979
+
980
+ def open_debugger(self):
981
+ if self.interp.rpcclt:
982
+ dbg_gui = debugger_r.start_remote_debugger(self.interp.rpcclt,
983
+ self)
984
+ else:
985
+ dbg_gui = debugger.Debugger(self)
986
+ self.interp.setdebugger(dbg_gui)
987
+ dbg_gui.load_breakpoints()
988
+ self.prompt = "[DEBUG ON]\n" + self.sys_ps1
989
+ self.showprompt()
990
+ self.set_debugger_indicator()
991
+
992
+ def debug_menu_postcommand(self):
993
+ state = 'disabled' if self.executing else 'normal'
994
+ self.update_menu_state('debug', '*tack*iewer', state)
995
+
996
+ def beginexecuting(self):
997
+ "Helper for ModifiedInterpreter"
998
+ self.resetoutput()
999
+ self.executing = True
1000
+
1001
+ def endexecuting(self):
1002
+ "Helper for ModifiedInterpreter"
1003
+ self.executing = False
1004
+ self.canceled = False
1005
+ self.showprompt()
1006
+
1007
+ def close(self):
1008
+ "Extend EditorWindow.close()"
1009
+ if self.executing:
1010
+ response = messagebox.askokcancel(
1011
+ "Kill?",
1012
+ "Your program is still running!\n Do you want to kill it?",
1013
+ default="ok",
1014
+ parent=self.text)
1015
+ if response is False:
1016
+ return "cancel"
1017
+ self.stop_readline()
1018
+ self.canceled = True
1019
+ self.closing = True
1020
+ return EditorWindow.close(self)
1021
+
1022
+ def _close(self):
1023
+ "Extend EditorWindow._close(), shut down debugger and execution server"
1024
+ self.close_debugger()
1025
+ if use_subprocess:
1026
+ self.interp.kill_subprocess()
1027
+ # Restore std streams
1028
+ sys.stdout = self.save_stdout
1029
+ sys.stderr = self.save_stderr
1030
+ sys.stdin = self.save_stdin
1031
+ # Break cycles
1032
+ self.interp = None
1033
+ self.console = None
1034
+ self.flist.pyshell = None
1035
+ self.history = None
1036
+ EditorWindow._close(self)
1037
+
1038
+ def ispythonsource(self, filename):
1039
+ "Override EditorWindow method: never remove the colorizer"
1040
+ return True
1041
+
1042
+ def short_title(self):
1043
+ return self.shell_title
1044
+
1045
+ COPYRIGHT = \
1046
+ 'Type "help", "copyright", "credits" or "license()" for more information.'
1047
+
1048
+ def begin(self):
1049
+ self.text.mark_set("iomark", "insert")
1050
+ self.resetoutput()
1051
+ if use_subprocess:
1052
+ nosub = ''
1053
+ client = self.interp.start_subprocess()
1054
+ if not client:
1055
+ self.close()
1056
+ return False
1057
+ else:
1058
+ nosub = ("==== No Subprocess ====\n\n" +
1059
+ "WARNING: Running IDLE without a Subprocess is deprecated\n" +
1060
+ "and will be removed in a later version. See Help/IDLE Help\n" +
1061
+ "for details.\n\n")
1062
+ sys.displayhook = rpc.displayhook
1063
+
1064
+ self.write("Python %s on %s\n%s\n%s" %
1065
+ (sys.version, sys.platform, self.COPYRIGHT, nosub))
1066
+ self.text.focus_force()
1067
+ self.showprompt()
1068
+ # User code should use separate default Tk root window
1069
+ import tkinter
1070
+ tkinter._support_default_root = True
1071
+ tkinter._default_root = None
1072
+ return True
1073
+
1074
+ def stop_readline(self):
1075
+ if not self.reading: # no nested mainloop to exit.
1076
+ return
1077
+ self._stop_readline_flag = True
1078
+ self.top.quit()
1079
+
1080
+ def readline(self):
1081
+ save = self.reading
1082
+ try:
1083
+ self.reading = True
1084
+ self.top.mainloop() # nested mainloop()
1085
+ finally:
1086
+ self.reading = save
1087
+ if self._stop_readline_flag:
1088
+ self._stop_readline_flag = False
1089
+ return ""
1090
+ line = self.text.get("iomark", "end-1c")
1091
+ if len(line) == 0: # may be EOF if we quit our mainloop with Ctrl-C
1092
+ line = "\n"
1093
+ self.resetoutput()
1094
+ if self.canceled:
1095
+ self.canceled = False
1096
+ if not use_subprocess:
1097
+ raise KeyboardInterrupt
1098
+ if self.endoffile:
1099
+ self.endoffile = False
1100
+ line = ""
1101
+ return line
1102
+
1103
+ def isatty(self):
1104
+ return True
1105
+
1106
+ def cancel_callback(self, event=None):
1107
+ try:
1108
+ if self.text.compare("sel.first", "!=", "sel.last"):
1109
+ return # Active selection -- always use default binding
1110
+ except:
1111
+ pass
1112
+ if not (self.executing or self.reading):
1113
+ self.resetoutput()
1114
+ self.interp.write("KeyboardInterrupt\n")
1115
+ self.showprompt()
1116
+ return "break"
1117
+ self.endoffile = False
1118
+ self.canceled = True
1119
+ if (self.executing and self.interp.rpcclt):
1120
+ if self.interp.getdebugger():
1121
+ self.interp.restart_subprocess()
1122
+ else:
1123
+ self.interp.interrupt_subprocess()
1124
+ if self.reading:
1125
+ self.top.quit() # exit the nested mainloop() in readline()
1126
+ return "break"
1127
+
1128
+ def eof_callback(self, event):
1129
+ if self.executing and not self.reading:
1130
+ return # Let the default binding (delete next char) take over
1131
+ if not (self.text.compare("iomark", "==", "insert") and
1132
+ self.text.compare("insert", "==", "end-1c")):
1133
+ return # Let the default binding (delete next char) take over
1134
+ if not self.executing:
1135
+ self.resetoutput()
1136
+ self.close()
1137
+ else:
1138
+ self.canceled = False
1139
+ self.endoffile = True
1140
+ self.top.quit()
1141
+ return "break"
1142
+
1143
+ def linefeed_callback(self, event):
1144
+ # Insert a linefeed without entering anything (still autoindented)
1145
+ if self.reading:
1146
+ self.text.insert("insert", "\n")
1147
+ self.text.see("insert")
1148
+ else:
1149
+ self.newline_and_indent_event(event)
1150
+ return "break"
1151
+
1152
+ def enter_callback(self, event):
1153
+ if self.executing and not self.reading:
1154
+ return # Let the default binding (insert '\n') take over
1155
+ # If some text is selected, recall the selection
1156
+ # (but only if this before the I/O mark)
1157
+ try:
1158
+ sel = self.text.get("sel.first", "sel.last")
1159
+ if sel:
1160
+ if self.text.compare("sel.last", "<=", "iomark"):
1161
+ self.recall(sel, event)
1162
+ return "break"
1163
+ except:
1164
+ pass
1165
+ # If we're strictly before the line containing iomark, recall
1166
+ # the current line, less a leading prompt, less leading or
1167
+ # trailing whitespace
1168
+ if self.text.compare("insert", "<", "iomark linestart"):
1169
+ # Check if there's a relevant stdin range -- if so, use it
1170
+ prev = self.text.tag_prevrange("stdin", "insert")
1171
+ if prev and self.text.compare("insert", "<", prev[1]):
1172
+ self.recall(self.text.get(prev[0], prev[1]), event)
1173
+ return "break"
1174
+ next = self.text.tag_nextrange("stdin", "insert")
1175
+ if next and self.text.compare("insert lineend", ">=", next[0]):
1176
+ self.recall(self.text.get(next[0], next[1]), event)
1177
+ return "break"
1178
+ # No stdin mark -- just get the current line, less any prompt
1179
+ indices = self.text.tag_nextrange("console", "insert linestart")
1180
+ if indices and \
1181
+ self.text.compare(indices[0], "<=", "insert linestart"):
1182
+ self.recall(self.text.get(indices[1], "insert lineend"), event)
1183
+ else:
1184
+ self.recall(self.text.get("insert linestart", "insert lineend"), event)
1185
+ return "break"
1186
+ # If we're between the beginning of the line and the iomark, i.e.
1187
+ # in the prompt area, move to the end of the prompt
1188
+ if self.text.compare("insert", "<", "iomark"):
1189
+ self.text.mark_set("insert", "iomark")
1190
+ # If we're in the current input and there's only whitespace
1191
+ # beyond the cursor, erase that whitespace first
1192
+ s = self.text.get("insert", "end-1c")
1193
+ if s and not s.strip():
1194
+ self.text.delete("insert", "end-1c")
1195
+ # If we're in the current input before its last line,
1196
+ # insert a newline right at the insert point
1197
+ if self.text.compare("insert", "<", "end-1c linestart"):
1198
+ self.newline_and_indent_event(event)
1199
+ return "break"
1200
+ # We're in the last line; append a newline and submit it
1201
+ self.text.mark_set("insert", "end-1c")
1202
+ if self.reading:
1203
+ self.text.insert("insert", "\n")
1204
+ self.text.see("insert")
1205
+ else:
1206
+ self.newline_and_indent_event(event)
1207
+ self.text.tag_add("stdin", "iomark", "end-1c")
1208
+ self.text.update_idletasks()
1209
+ if self.reading:
1210
+ self.top.quit() # Break out of recursive mainloop()
1211
+ else:
1212
+ self.runit()
1213
+ return "break"
1214
+
1215
+ def recall(self, s, event):
1216
+ # remove leading and trailing empty or whitespace lines
1217
+ s = re.sub(r'^\s*\n', '' , s)
1218
+ s = re.sub(r'\n\s*$', '', s)
1219
+ lines = s.split('\n')
1220
+ self.text.undo_block_start()
1221
+ try:
1222
+ self.text.tag_remove("sel", "1.0", "end")
1223
+ self.text.mark_set("insert", "end-1c")
1224
+ prefix = self.text.get("insert linestart", "insert")
1225
+ if prefix.rstrip().endswith(':'):
1226
+ self.newline_and_indent_event(event)
1227
+ prefix = self.text.get("insert linestart", "insert")
1228
+ self.text.insert("insert", lines[0].strip())
1229
+ if len(lines) > 1:
1230
+ orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1231
+ new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
1232
+ for line in lines[1:]:
1233
+ if line.startswith(orig_base_indent):
1234
+ # replace orig base indentation with new indentation
1235
+ line = new_base_indent + line[len(orig_base_indent):]
1236
+ self.text.insert('insert', '\n'+line.rstrip())
1237
+ finally:
1238
+ self.text.see("insert")
1239
+ self.text.undo_block_stop()
1240
+
1241
+ def runit(self):
1242
+ line = self.text.get("iomark", "end-1c")
1243
+ # Strip off last newline and surrounding whitespace.
1244
+ # (To allow you to hit return twice to end a statement.)
1245
+ i = len(line)
1246
+ while i > 0 and line[i-1] in " \t":
1247
+ i = i-1
1248
+ if i > 0 and line[i-1] == "\n":
1249
+ i = i-1
1250
+ while i > 0 and line[i-1] in " \t":
1251
+ i = i-1
1252
+ line = line[:i]
1253
+ self.interp.runsource(line)
1254
+
1255
+ def open_stack_viewer(self, event=None):
1256
+ if self.interp.rpcclt:
1257
+ return self.interp.remote_stack_viewer()
1258
+ try:
1259
+ sys.last_traceback
1260
+ except:
1261
+ messagebox.showerror("No stack trace",
1262
+ "There is no stack trace yet.\n"
1263
+ "(sys.last_traceback is not defined)",
1264
+ parent=self.text)
1265
+ return
1266
+ from idlelib.stackviewer import StackBrowser
1267
+ StackBrowser(self.root, self.flist)
1268
+
1269
+ def view_restart_mark(self, event=None):
1270
+ self.text.see("iomark")
1271
+ self.text.see("restart")
1272
+
1273
+ def restart_shell(self, event=None):
1274
+ "Callback for Run/Restart Shell Cntl-F6"
1275
+ self.interp.restart_subprocess(with_cwd=True)
1276
+
1277
+ def showprompt(self):
1278
+ self.resetoutput()
1279
+ self.console.write(self.prompt)
1280
+ self.text.mark_set("insert", "end-1c")
1281
+ self.set_line_and_column()
1282
+ self.io.reset_undo()
1283
+
1284
+ def show_warning(self, msg):
1285
+ width = self.interp.tkconsole.width
1286
+ wrapper = TextWrapper(width=width, tabsize=8, expand_tabs=True)
1287
+ wrapped_msg = '\n'.join(wrapper.wrap(msg))
1288
+ if not wrapped_msg.endswith('\n'):
1289
+ wrapped_msg += '\n'
1290
+ self.per.bottom.insert("iomark linestart", wrapped_msg, "stderr")
1291
+
1292
+ def resetoutput(self):
1293
+ source = self.text.get("iomark", "end-1c")
1294
+ if self.history:
1295
+ self.history.store(source)
1296
+ if self.text.get("end-2c") != "\n":
1297
+ self.text.insert("end-1c", "\n")
1298
+ self.text.mark_set("iomark", "end-1c")
1299
+ self.set_line_and_column()
1300
+ self.ctip.remove_calltip_window()
1301
+
1302
+ def write(self, s, tags=()):
1303
+ try:
1304
+ self.text.mark_gravity("iomark", "right")
1305
+ count = OutputWindow.write(self, s, tags, "iomark")
1306
+ self.text.mark_gravity("iomark", "left")
1307
+ except:
1308
+ raise ###pass # ### 11Aug07 KBK if we are expecting exceptions
1309
+ # let's find out what they are and be specific.
1310
+ if self.canceled:
1311
+ self.canceled = False
1312
+ if not use_subprocess:
1313
+ raise KeyboardInterrupt
1314
+ return count
1315
+
1316
+ def rmenu_check_cut(self):
1317
+ try:
1318
+ if self.text.compare('sel.first', '<', 'iomark'):
1319
+ return 'disabled'
1320
+ except TclError: # no selection, so the index 'sel.first' doesn't exist
1321
+ return 'disabled'
1322
+ return super().rmenu_check_cut()
1323
+
1324
+ def rmenu_check_paste(self):
1325
+ if self.text.compare('insert','<','iomark'):
1326
+ return 'disabled'
1327
+ return super().rmenu_check_paste()
1328
+
1329
+
1330
+ def fix_x11_paste(root):
1331
+ "Make paste replace selection on x11. See issue #5124."
1332
+ if root._windowingsystem == 'x11':
1333
+ for cls in 'Text', 'Entry', 'Spinbox':
1334
+ root.bind_class(
1335
+ cls,
1336
+ '<<Paste>>',
1337
+ 'catch {%W delete sel.first sel.last}\n' +
1338
+ root.bind_class(cls, '<<Paste>>'))
1339
+
1340
+
1341
+ usage_msg = """\
1342
+
1343
+ USAGE: idle [-deins] [-t title] [file]*
1344
+ idle [-dns] [-t title] (-c cmd | -r file) [arg]*
1345
+ idle [-dns] [-t title] - [arg]*
1346
+
1347
+ -h print this help message and exit
1348
+ -n run IDLE without a subprocess (DEPRECATED,
1349
+ see Help/IDLE Help for details)
1350
+
1351
+ The following options will override the IDLE 'settings' configuration:
1352
+
1353
+ -e open an edit window
1354
+ -i open a shell window
1355
+
1356
+ The following options imply -i and will open a shell:
1357
+
1358
+ -c cmd run the command in a shell, or
1359
+ -r file run script from file
1360
+
1361
+ -d enable the debugger
1362
+ -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1363
+ -t title set title of shell window
1364
+
1365
+ A default edit window will be bypassed when -c, -r, or - are used.
1366
+
1367
+ [arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1368
+
1369
+ Examples:
1370
+
1371
+ idle
1372
+ Open an edit window or shell depending on IDLE's configuration.
1373
+
1374
+ idle foo.py foobar.py
1375
+ Edit the files, also open a shell if configured to start with shell.
1376
+
1377
+ idle -est "Baz" foo.py
1378
+ Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1379
+ window with the title "Baz".
1380
+
1381
+ idle -c "import sys; print(sys.argv)" "foo"
1382
+ Open a shell window and run the command, passing "-c" in sys.argv[0]
1383
+ and "foo" in sys.argv[1].
1384
+
1385
+ idle -d -s -r foo.py "Hello World"
1386
+ Open a shell window, run a startup script, enable the debugger, and
1387
+ run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1388
+ sys.argv[1].
1389
+
1390
+ echo "import sys; print(sys.argv)" | idle - "foobar"
1391
+ Open a shell window, run the script piped in, passing '' in sys.argv[0]
1392
+ and "foobar" in sys.argv[1].
1393
+ """
1394
+
1395
+ def main():
1396
+ import getopt
1397
+ from platform import system
1398
+ from idlelib import testing # bool value
1399
+ from idlelib import macosx
1400
+
1401
+ global flist, root, use_subprocess
1402
+
1403
+ capture_warnings(True)
1404
+ use_subprocess = True
1405
+ enable_shell = False
1406
+ enable_edit = False
1407
+ debug = False
1408
+ cmd = None
1409
+ script = None
1410
+ startup = False
1411
+ try:
1412
+ opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
1413
+ except getopt.error as msg:
1414
+ print("Error: %s\n%s" % (msg, usage_msg), file=sys.stderr)
1415
+ sys.exit(2)
1416
+ for o, a in opts:
1417
+ if o == '-c':
1418
+ cmd = a
1419
+ enable_shell = True
1420
+ if o == '-d':
1421
+ debug = True
1422
+ enable_shell = True
1423
+ if o == '-e':
1424
+ enable_edit = True
1425
+ if o == '-h':
1426
+ sys.stdout.write(usage_msg)
1427
+ sys.exit()
1428
+ if o == '-i':
1429
+ enable_shell = True
1430
+ if o == '-n':
1431
+ print(" Warning: running IDLE without a subprocess is deprecated.",
1432
+ file=sys.stderr)
1433
+ use_subprocess = False
1434
+ if o == '-r':
1435
+ script = a
1436
+ if os.path.isfile(script):
1437
+ pass
1438
+ else:
1439
+ print("No script file: ", script)
1440
+ sys.exit()
1441
+ enable_shell = True
1442
+ if o == '-s':
1443
+ startup = True
1444
+ enable_shell = True
1445
+ if o == '-t':
1446
+ PyShell.shell_title = a
1447
+ enable_shell = True
1448
+ if args and args[0] == '-':
1449
+ cmd = sys.stdin.read()
1450
+ enable_shell = True
1451
+ # process sys.argv and sys.path:
1452
+ for i in range(len(sys.path)):
1453
+ sys.path[i] = os.path.abspath(sys.path[i])
1454
+ if args and args[0] == '-':
1455
+ sys.argv = [''] + args[1:]
1456
+ elif cmd:
1457
+ sys.argv = ['-c'] + args
1458
+ elif script:
1459
+ sys.argv = [script] + args
1460
+ elif args:
1461
+ enable_edit = True
1462
+ pathx = []
1463
+ for filename in args:
1464
+ pathx.append(os.path.dirname(filename))
1465
+ for dir in pathx:
1466
+ dir = os.path.abspath(dir)
1467
+ if not dir in sys.path:
1468
+ sys.path.insert(0, dir)
1469
+ else:
1470
+ dir = os.getcwd()
1471
+ if dir not in sys.path:
1472
+ sys.path.insert(0, dir)
1473
+ # check the IDLE settings configuration (but command line overrides)
1474
+ edit_start = idleConf.GetOption('main', 'General',
1475
+ 'editor-on-startup', type='bool')
1476
+ enable_edit = enable_edit or edit_start
1477
+ enable_shell = enable_shell or not enable_edit
1478
+
1479
+ # Setup root. Don't break user code run in IDLE process.
1480
+ # Don't change environment when testing.
1481
+ if use_subprocess and not testing:
1482
+ NoDefaultRoot()
1483
+ root = Tk(className="Idle")
1484
+ root.withdraw()
1485
+ from idlelib.run import fix_scaling
1486
+ fix_scaling(root)
1487
+
1488
+ # set application icon
1489
+ icondir = os.path.join(os.path.dirname(__file__), 'Icons')
1490
+ if system() == 'Windows':
1491
+ iconfile = os.path.join(icondir, 'idle.ico')
1492
+ root.wm_iconbitmap(default=iconfile)
1493
+ elif not macosx.isAquaTk():
1494
+ if TkVersion >= 8.6:
1495
+ ext = '.png'
1496
+ sizes = (16, 32, 48, 256)
1497
+ else:
1498
+ ext = '.gif'
1499
+ sizes = (16, 32, 48)
1500
+ iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
1501
+ for size in sizes]
1502
+ icons = [PhotoImage(master=root, file=iconfile)
1503
+ for iconfile in iconfiles]
1504
+ root.wm_iconphoto(True, *icons)
1505
+
1506
+ # start editor and/or shell windows:
1507
+ fixwordbreaks(root)
1508
+ fix_x11_paste(root)
1509
+ flist = PyShellFileList(root)
1510
+ macosx.setupApp(root, flist)
1511
+
1512
+ if enable_edit:
1513
+ if not (cmd or script):
1514
+ for filename in args[:]:
1515
+ if flist.open(filename) is None:
1516
+ # filename is a directory actually, disconsider it
1517
+ args.remove(filename)
1518
+ if not args:
1519
+ flist.new()
1520
+
1521
+ if enable_shell:
1522
+ shell = flist.open_shell()
1523
+ if not shell:
1524
+ return # couldn't open shell
1525
+ if macosx.isAquaTk() and flist.dict:
1526
+ # On OSX: when the user has double-clicked on a file that causes
1527
+ # IDLE to be launched the shell window will open just in front of
1528
+ # the file she wants to see. Lower the interpreter window when
1529
+ # there are open files.
1530
+ shell.top.lower()
1531
+ else:
1532
+ shell = flist.pyshell
1533
+
1534
+ # Handle remaining options. If any of these are set, enable_shell
1535
+ # was set also, so shell must be true to reach here.
1536
+ if debug:
1537
+ shell.open_debugger()
1538
+ if startup:
1539
+ filename = os.environ.get("IDLESTARTUP") or \
1540
+ os.environ.get("PYTHONSTARTUP")
1541
+ if filename and os.path.isfile(filename):
1542
+ shell.interp.execfile(filename)
1543
+ if cmd or script:
1544
+ shell.interp.runcommand("""if 1:
1545
+ import sys as _sys
1546
+ _sys.argv = %r
1547
+ del _sys
1548
+ \n""" % (sys.argv,))
1549
+ if cmd:
1550
+ shell.interp.execsource(cmd)
1551
+ elif script:
1552
+ shell.interp.prepend_syspath(script)
1553
+ shell.interp.execfile(script)
1554
+ elif shell:
1555
+ # If there is a shell window and no cmd or script in progress,
1556
+ # check for problematic issues and print warning message(s) in
1557
+ # the IDLE shell window; this is less intrusive than always
1558
+ # opening a separate window.
1559
+
1560
+ # Warn if using a problematic OS X Tk version.
1561
+ tkversionwarning = macosx.tkVersionWarning(root)
1562
+ if tkversionwarning:
1563
+ shell.show_warning(tkversionwarning)
1564
+
1565
+ # Warn if the "Prefer tabs when opening documents" system
1566
+ # preference is set to "Always".
1567
+ prefer_tabs_preference_warning = macosx.preferTabsPreferenceWarning()
1568
+ if prefer_tabs_preference_warning:
1569
+ shell.show_warning(prefer_tabs_preference_warning)
1570
+
1571
+ while flist.inversedict: # keep IDLE running while files are open.
1572
+ root.mainloop()
1573
+ root.destroy()
1574
+ capture_warnings(False)
1575
+
1576
+ if __name__ == "__main__":
1577
+ main()
1578
+
1579
+ capture_warnings(False) # Make sure turned off; see issue 18081