prasb commited on
Commit
174519a
·
verified ·
1 Parent(s): 454ced8

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 +2 -0
  2. my_container_sandbox/workspace/anaconda3/lib/python3.8/curses/__init__.py +113 -0
  3. my_container_sandbox/workspace/anaconda3/lib/python3.8/curses/ascii.py +99 -0
  4. my_container_sandbox/workspace/anaconda3/lib/python3.8/curses/has_key.py +192 -0
  5. my_container_sandbox/workspace/anaconda3/lib/python3.8/curses/panel.py +6 -0
  6. my_container_sandbox/workspace/anaconda3/lib/python3.8/dbm/__init__.py +189 -0
  7. my_container_sandbox/workspace/anaconda3/lib/python3.8/dbm/dumb.py +316 -0
  8. my_container_sandbox/workspace/anaconda3/lib/python3.8/dbm/gnu.py +3 -0
  9. my_container_sandbox/workspace/anaconda3/lib/python3.8/dbm/ndbm.py +3 -0
  10. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/__init__.py +62 -0
  11. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/_encoded_words.py +233 -0
  12. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/_header_value_parser.py +0 -0
  13. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/_parseaddr.py +551 -0
  14. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/_policybase.py +374 -0
  15. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/architecture.rst +216 -0
  16. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/base64mime.py +119 -0
  17. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/charset.py +404 -0
  18. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/contentmanager.py +250 -0
  19. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/encoders.py +69 -0
  20. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/errors.py +110 -0
  21. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/feedparser.py +536 -0
  22. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/generator.py +512 -0
  23. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/header.py +578 -0
  24. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/headerregistry.py +607 -0
  25. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/iterators.py +71 -0
  26. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/message.py +1173 -0
  27. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/parser.py +131 -0
  28. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/policy.py +224 -0
  29. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/quoprimime.py +299 -0
  30. my_container_sandbox/workspace/anaconda3/lib/python3.8/email/utils.py +376 -0
  31. my_container_sandbox/workspace/anaconda3/lib/python3.8/json/__init__.py +370 -0
  32. my_container_sandbox/workspace/anaconda3/lib/python3.8/json/decoder.py +356 -0
  33. my_container_sandbox/workspace/anaconda3/lib/python3.8/json/encoder.py +442 -0
  34. my_container_sandbox/workspace/anaconda3/lib/python3.8/json/scanner.py +73 -0
  35. my_container_sandbox/workspace/anaconda3/lib/python3.8/json/tool.py +58 -0
  36. my_container_sandbox/workspace/anaconda3/lib/python3.8/sqlite3/dbapi2.py +89 -0
  37. my_container_sandbox/workspace/anaconda3/lib/python3.8/test/__init__.py +1 -0
  38. my_container_sandbox/workspace/anaconda3/lib/python3.8/test/test_script_helper.py +125 -0
  39. my_container_sandbox/workspace/anaconda3/lib/python3.8/test/test_support.py +689 -0
  40. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/__init__.py +14 -0
  41. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/__main__.py +386 -0
  42. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/bytedesign.py +161 -0
  43. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/chaos.py +59 -0
  44. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/clock.py +132 -0
  45. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/colormixer.py +58 -0
  46. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/forest.py +108 -0
  47. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/lindenmayer.py +119 -0
  48. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/minimal_hanoi.py +79 -0
  49. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/paint.py +54 -0
  50. my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/peace.py +61 -0
.gitattributes CHANGED
@@ -170,3 +170,5 @@ my_container_sandbox/workspace/anaconda3/pkgs/libgomp-11.2.0-h1234567_1.conda fi
170
  my_container_sandbox/workspace/anaconda3/pkgs/tzdata-2021a-h52ac0ba_0.conda filter=lfs diff=lfs merge=lfs -text
171
  my_container_sandbox/workspace/anaconda3/pkgs/ca-certificates-2024.2.2-hbcca054_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
 
 
 
170
  my_container_sandbox/workspace/anaconda3/pkgs/tzdata-2021a-h52ac0ba_0.conda filter=lfs diff=lfs merge=lfs -text
171
  my_container_sandbox/workspace/anaconda3/pkgs/ca-certificates-2024.2.2-hbcca054_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
my_container_sandbox/workspace/anaconda3/lib/python3.8/curses/__init__.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """curses
2
+
3
+ The main package for curses support for Python. Normally used by importing
4
+ the package, and perhaps a particular module inside it.
5
+
6
+ import curses
7
+ from curses import textpad
8
+ curses.initscr()
9
+ ...
10
+
11
+ """
12
+
13
+ from _curses import *
14
+ import os as _os
15
+ import sys as _sys
16
+
17
+ # Some constants, most notably the ACS_* ones, are only added to the C
18
+ # _curses module's dictionary after initscr() is called. (Some
19
+ # versions of SGI's curses don't define values for those constants
20
+ # until initscr() has been called.) This wrapper function calls the
21
+ # underlying C initscr(), and then copies the constants from the
22
+ # _curses module to the curses package's dictionary. Don't do 'from
23
+ # curses import *' if you'll be needing the ACS_* constants.
24
+
25
+ def initscr():
26
+ import _curses, curses
27
+ # we call setupterm() here because it raises an error
28
+ # instead of calling exit() in error cases.
29
+ setupterm(term=_os.environ.get("TERM", "unknown"),
30
+ fd=_sys.__stdout__.fileno())
31
+ stdscr = _curses.initscr()
32
+ for key, value in _curses.__dict__.items():
33
+ if key[0:4] == 'ACS_' or key in ('LINES', 'COLS'):
34
+ setattr(curses, key, value)
35
+
36
+ return stdscr
37
+
38
+ # This is a similar wrapper for start_color(), which adds the COLORS and
39
+ # COLOR_PAIRS variables which are only available after start_color() is
40
+ # called.
41
+
42
+ def start_color():
43
+ import _curses, curses
44
+ retval = _curses.start_color()
45
+ if hasattr(_curses, 'COLORS'):
46
+ curses.COLORS = _curses.COLORS
47
+ if hasattr(_curses, 'COLOR_PAIRS'):
48
+ curses.COLOR_PAIRS = _curses.COLOR_PAIRS
49
+ return retval
50
+
51
+ # Import Python has_key() implementation if _curses doesn't contain has_key()
52
+
53
+ try:
54
+ has_key
55
+ except NameError:
56
+ from .has_key import has_key
57
+
58
+ # Wrapper for the entire curses-based application. Runs a function which
59
+ # should be the rest of your curses-based application. If the application
60
+ # raises an exception, wrapper() will restore the terminal to a sane state so
61
+ # you can read the resulting traceback.
62
+
63
+ def wrapper(*args, **kwds):
64
+ """Wrapper function that initializes curses and calls another function,
65
+ restoring normal keyboard/screen behavior on error.
66
+ The callable object 'func' is then passed the main window 'stdscr'
67
+ as its first argument, followed by any other arguments passed to
68
+ wrapper().
69
+ """
70
+
71
+ if args:
72
+ func, *args = args
73
+ elif 'func' in kwds:
74
+ func = kwds.pop('func')
75
+ import warnings
76
+ warnings.warn("Passing 'func' as keyword argument is deprecated",
77
+ DeprecationWarning, stacklevel=2)
78
+ else:
79
+ raise TypeError('wrapper expected at least 1 positional argument, '
80
+ 'got %d' % len(args))
81
+
82
+ try:
83
+ # Initialize curses
84
+ stdscr = initscr()
85
+
86
+ # Turn off echoing of keys, and enter cbreak mode,
87
+ # where no buffering is performed on keyboard input
88
+ noecho()
89
+ cbreak()
90
+
91
+ # In keypad mode, escape sequences for special keys
92
+ # (like the cursor keys) will be interpreted and
93
+ # a special value like curses.KEY_LEFT will be returned
94
+ stdscr.keypad(1)
95
+
96
+ # Start color, too. Harmless if the terminal doesn't have
97
+ # color; user can test with has_color() later on. The try/catch
98
+ # works around a minor bit of over-conscientiousness in the curses
99
+ # module -- the error return from C start_color() is ignorable.
100
+ try:
101
+ start_color()
102
+ except:
103
+ pass
104
+
105
+ return func(stdscr, *args, **kwds)
106
+ finally:
107
+ # Set everything back to normal
108
+ if 'stdscr' in locals():
109
+ stdscr.keypad(0)
110
+ echo()
111
+ nocbreak()
112
+ endwin()
113
+ wrapper.__text_signature__ = '(func, /, *args, **kwds)'
my_container_sandbox/workspace/anaconda3/lib/python3.8/curses/ascii.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Constants and membership tests for ASCII characters"""
2
+
3
+ NUL = 0x00 # ^@
4
+ SOH = 0x01 # ^A
5
+ STX = 0x02 # ^B
6
+ ETX = 0x03 # ^C
7
+ EOT = 0x04 # ^D
8
+ ENQ = 0x05 # ^E
9
+ ACK = 0x06 # ^F
10
+ BEL = 0x07 # ^G
11
+ BS = 0x08 # ^H
12
+ TAB = 0x09 # ^I
13
+ HT = 0x09 # ^I
14
+ LF = 0x0a # ^J
15
+ NL = 0x0a # ^J
16
+ VT = 0x0b # ^K
17
+ FF = 0x0c # ^L
18
+ CR = 0x0d # ^M
19
+ SO = 0x0e # ^N
20
+ SI = 0x0f # ^O
21
+ DLE = 0x10 # ^P
22
+ DC1 = 0x11 # ^Q
23
+ DC2 = 0x12 # ^R
24
+ DC3 = 0x13 # ^S
25
+ DC4 = 0x14 # ^T
26
+ NAK = 0x15 # ^U
27
+ SYN = 0x16 # ^V
28
+ ETB = 0x17 # ^W
29
+ CAN = 0x18 # ^X
30
+ EM = 0x19 # ^Y
31
+ SUB = 0x1a # ^Z
32
+ ESC = 0x1b # ^[
33
+ FS = 0x1c # ^\
34
+ GS = 0x1d # ^]
35
+ RS = 0x1e # ^^
36
+ US = 0x1f # ^_
37
+ SP = 0x20 # space
38
+ DEL = 0x7f # delete
39
+
40
+ controlnames = [
41
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
42
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
43
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
44
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
45
+ "SP"
46
+ ]
47
+
48
+ def _ctoi(c):
49
+ if type(c) == type(""):
50
+ return ord(c)
51
+ else:
52
+ return c
53
+
54
+ def isalnum(c): return isalpha(c) or isdigit(c)
55
+ def isalpha(c): return isupper(c) or islower(c)
56
+ def isascii(c): return 0 <= _ctoi(c) <= 127 # ?
57
+ def isblank(c): return _ctoi(c) in (9, 32)
58
+ def iscntrl(c): return 0 <= _ctoi(c) <= 31 or _ctoi(c) == 127
59
+ def isdigit(c): return 48 <= _ctoi(c) <= 57
60
+ def isgraph(c): return 33 <= _ctoi(c) <= 126
61
+ def islower(c): return 97 <= _ctoi(c) <= 122
62
+ def isprint(c): return 32 <= _ctoi(c) <= 126
63
+ def ispunct(c): return isgraph(c) and not isalnum(c)
64
+ def isspace(c): return _ctoi(c) in (9, 10, 11, 12, 13, 32)
65
+ def isupper(c): return 65 <= _ctoi(c) <= 90
66
+ def isxdigit(c): return isdigit(c) or \
67
+ (65 <= _ctoi(c) <= 70) or (97 <= _ctoi(c) <= 102)
68
+ def isctrl(c): return 0 <= _ctoi(c) < 32
69
+ def ismeta(c): return _ctoi(c) > 127
70
+
71
+ def ascii(c):
72
+ if type(c) == type(""):
73
+ return chr(_ctoi(c) & 0x7f)
74
+ else:
75
+ return _ctoi(c) & 0x7f
76
+
77
+ def ctrl(c):
78
+ if type(c) == type(""):
79
+ return chr(_ctoi(c) & 0x1f)
80
+ else:
81
+ return _ctoi(c) & 0x1f
82
+
83
+ def alt(c):
84
+ if type(c) == type(""):
85
+ return chr(_ctoi(c) | 0x80)
86
+ else:
87
+ return _ctoi(c) | 0x80
88
+
89
+ def unctrl(c):
90
+ bits = _ctoi(c)
91
+ if bits == 0x7f:
92
+ rep = "^?"
93
+ elif isprint(bits & 0x7f):
94
+ rep = chr(bits & 0x7f)
95
+ else:
96
+ rep = "^" + chr(((bits & 0x7f) | 0x20) + 0x20)
97
+ if bits & 0x80:
98
+ return "!" + rep
99
+ return rep
my_container_sandbox/workspace/anaconda3/lib/python3.8/curses/has_key.py ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #
3
+ # Emulation of has_key() function for platforms that don't use ncurses
4
+ #
5
+
6
+ import _curses
7
+
8
+ # Table mapping curses keys to the terminfo capability name
9
+
10
+ _capability_names = {
11
+ _curses.KEY_A1: 'ka1',
12
+ _curses.KEY_A3: 'ka3',
13
+ _curses.KEY_B2: 'kb2',
14
+ _curses.KEY_BACKSPACE: 'kbs',
15
+ _curses.KEY_BEG: 'kbeg',
16
+ _curses.KEY_BTAB: 'kcbt',
17
+ _curses.KEY_C1: 'kc1',
18
+ _curses.KEY_C3: 'kc3',
19
+ _curses.KEY_CANCEL: 'kcan',
20
+ _curses.KEY_CATAB: 'ktbc',
21
+ _curses.KEY_CLEAR: 'kclr',
22
+ _curses.KEY_CLOSE: 'kclo',
23
+ _curses.KEY_COMMAND: 'kcmd',
24
+ _curses.KEY_COPY: 'kcpy',
25
+ _curses.KEY_CREATE: 'kcrt',
26
+ _curses.KEY_CTAB: 'kctab',
27
+ _curses.KEY_DC: 'kdch1',
28
+ _curses.KEY_DL: 'kdl1',
29
+ _curses.KEY_DOWN: 'kcud1',
30
+ _curses.KEY_EIC: 'krmir',
31
+ _curses.KEY_END: 'kend',
32
+ _curses.KEY_ENTER: 'kent',
33
+ _curses.KEY_EOL: 'kel',
34
+ _curses.KEY_EOS: 'ked',
35
+ _curses.KEY_EXIT: 'kext',
36
+ _curses.KEY_F0: 'kf0',
37
+ _curses.KEY_F1: 'kf1',
38
+ _curses.KEY_F10: 'kf10',
39
+ _curses.KEY_F11: 'kf11',
40
+ _curses.KEY_F12: 'kf12',
41
+ _curses.KEY_F13: 'kf13',
42
+ _curses.KEY_F14: 'kf14',
43
+ _curses.KEY_F15: 'kf15',
44
+ _curses.KEY_F16: 'kf16',
45
+ _curses.KEY_F17: 'kf17',
46
+ _curses.KEY_F18: 'kf18',
47
+ _curses.KEY_F19: 'kf19',
48
+ _curses.KEY_F2: 'kf2',
49
+ _curses.KEY_F20: 'kf20',
50
+ _curses.KEY_F21: 'kf21',
51
+ _curses.KEY_F22: 'kf22',
52
+ _curses.KEY_F23: 'kf23',
53
+ _curses.KEY_F24: 'kf24',
54
+ _curses.KEY_F25: 'kf25',
55
+ _curses.KEY_F26: 'kf26',
56
+ _curses.KEY_F27: 'kf27',
57
+ _curses.KEY_F28: 'kf28',
58
+ _curses.KEY_F29: 'kf29',
59
+ _curses.KEY_F3: 'kf3',
60
+ _curses.KEY_F30: 'kf30',
61
+ _curses.KEY_F31: 'kf31',
62
+ _curses.KEY_F32: 'kf32',
63
+ _curses.KEY_F33: 'kf33',
64
+ _curses.KEY_F34: 'kf34',
65
+ _curses.KEY_F35: 'kf35',
66
+ _curses.KEY_F36: 'kf36',
67
+ _curses.KEY_F37: 'kf37',
68
+ _curses.KEY_F38: 'kf38',
69
+ _curses.KEY_F39: 'kf39',
70
+ _curses.KEY_F4: 'kf4',
71
+ _curses.KEY_F40: 'kf40',
72
+ _curses.KEY_F41: 'kf41',
73
+ _curses.KEY_F42: 'kf42',
74
+ _curses.KEY_F43: 'kf43',
75
+ _curses.KEY_F44: 'kf44',
76
+ _curses.KEY_F45: 'kf45',
77
+ _curses.KEY_F46: 'kf46',
78
+ _curses.KEY_F47: 'kf47',
79
+ _curses.KEY_F48: 'kf48',
80
+ _curses.KEY_F49: 'kf49',
81
+ _curses.KEY_F5: 'kf5',
82
+ _curses.KEY_F50: 'kf50',
83
+ _curses.KEY_F51: 'kf51',
84
+ _curses.KEY_F52: 'kf52',
85
+ _curses.KEY_F53: 'kf53',
86
+ _curses.KEY_F54: 'kf54',
87
+ _curses.KEY_F55: 'kf55',
88
+ _curses.KEY_F56: 'kf56',
89
+ _curses.KEY_F57: 'kf57',
90
+ _curses.KEY_F58: 'kf58',
91
+ _curses.KEY_F59: 'kf59',
92
+ _curses.KEY_F6: 'kf6',
93
+ _curses.KEY_F60: 'kf60',
94
+ _curses.KEY_F61: 'kf61',
95
+ _curses.KEY_F62: 'kf62',
96
+ _curses.KEY_F63: 'kf63',
97
+ _curses.KEY_F7: 'kf7',
98
+ _curses.KEY_F8: 'kf8',
99
+ _curses.KEY_F9: 'kf9',
100
+ _curses.KEY_FIND: 'kfnd',
101
+ _curses.KEY_HELP: 'khlp',
102
+ _curses.KEY_HOME: 'khome',
103
+ _curses.KEY_IC: 'kich1',
104
+ _curses.KEY_IL: 'kil1',
105
+ _curses.KEY_LEFT: 'kcub1',
106
+ _curses.KEY_LL: 'kll',
107
+ _curses.KEY_MARK: 'kmrk',
108
+ _curses.KEY_MESSAGE: 'kmsg',
109
+ _curses.KEY_MOVE: 'kmov',
110
+ _curses.KEY_NEXT: 'knxt',
111
+ _curses.KEY_NPAGE: 'knp',
112
+ _curses.KEY_OPEN: 'kopn',
113
+ _curses.KEY_OPTIONS: 'kopt',
114
+ _curses.KEY_PPAGE: 'kpp',
115
+ _curses.KEY_PREVIOUS: 'kprv',
116
+ _curses.KEY_PRINT: 'kprt',
117
+ _curses.KEY_REDO: 'krdo',
118
+ _curses.KEY_REFERENCE: 'kref',
119
+ _curses.KEY_REFRESH: 'krfr',
120
+ _curses.KEY_REPLACE: 'krpl',
121
+ _curses.KEY_RESTART: 'krst',
122
+ _curses.KEY_RESUME: 'kres',
123
+ _curses.KEY_RIGHT: 'kcuf1',
124
+ _curses.KEY_SAVE: 'ksav',
125
+ _curses.KEY_SBEG: 'kBEG',
126
+ _curses.KEY_SCANCEL: 'kCAN',
127
+ _curses.KEY_SCOMMAND: 'kCMD',
128
+ _curses.KEY_SCOPY: 'kCPY',
129
+ _curses.KEY_SCREATE: 'kCRT',
130
+ _curses.KEY_SDC: 'kDC',
131
+ _curses.KEY_SDL: 'kDL',
132
+ _curses.KEY_SELECT: 'kslt',
133
+ _curses.KEY_SEND: 'kEND',
134
+ _curses.KEY_SEOL: 'kEOL',
135
+ _curses.KEY_SEXIT: 'kEXT',
136
+ _curses.KEY_SF: 'kind',
137
+ _curses.KEY_SFIND: 'kFND',
138
+ _curses.KEY_SHELP: 'kHLP',
139
+ _curses.KEY_SHOME: 'kHOM',
140
+ _curses.KEY_SIC: 'kIC',
141
+ _curses.KEY_SLEFT: 'kLFT',
142
+ _curses.KEY_SMESSAGE: 'kMSG',
143
+ _curses.KEY_SMOVE: 'kMOV',
144
+ _curses.KEY_SNEXT: 'kNXT',
145
+ _curses.KEY_SOPTIONS: 'kOPT',
146
+ _curses.KEY_SPREVIOUS: 'kPRV',
147
+ _curses.KEY_SPRINT: 'kPRT',
148
+ _curses.KEY_SR: 'kri',
149
+ _curses.KEY_SREDO: 'kRDO',
150
+ _curses.KEY_SREPLACE: 'kRPL',
151
+ _curses.KEY_SRIGHT: 'kRIT',
152
+ _curses.KEY_SRSUME: 'kRES',
153
+ _curses.KEY_SSAVE: 'kSAV',
154
+ _curses.KEY_SSUSPEND: 'kSPD',
155
+ _curses.KEY_STAB: 'khts',
156
+ _curses.KEY_SUNDO: 'kUND',
157
+ _curses.KEY_SUSPEND: 'kspd',
158
+ _curses.KEY_UNDO: 'kund',
159
+ _curses.KEY_UP: 'kcuu1'
160
+ }
161
+
162
+ def has_key(ch):
163
+ if isinstance(ch, str):
164
+ ch = ord(ch)
165
+
166
+ # Figure out the correct capability name for the keycode.
167
+ capability_name = _capability_names.get(ch)
168
+ if capability_name is None:
169
+ return False
170
+
171
+ #Check the current terminal description for that capability;
172
+ #if present, return true, else return false.
173
+ if _curses.tigetstr( capability_name ):
174
+ return True
175
+ else:
176
+ return False
177
+
178
+ if __name__ == '__main__':
179
+ # Compare the output of this implementation and the ncurses has_key,
180
+ # on platforms where has_key is already available
181
+ try:
182
+ L = []
183
+ _curses.initscr()
184
+ for key in _capability_names.keys():
185
+ system = _curses.has_key(key)
186
+ python = has_key(key)
187
+ if system != python:
188
+ L.append( 'Mismatch for key %s, system=%i, Python=%i'
189
+ % (_curses.keyname( key ), system, python) )
190
+ finally:
191
+ _curses.endwin()
192
+ for i in L: print(i)
my_container_sandbox/workspace/anaconda3/lib/python3.8/curses/panel.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ """curses.panel
2
+
3
+ Module for using panels with curses.
4
+ """
5
+
6
+ from _curses_panel import *
my_container_sandbox/workspace/anaconda3/lib/python3.8/dbm/__init__.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generic interface to all dbm clones.
2
+
3
+ Use
4
+
5
+ import dbm
6
+ d = dbm.open(file, 'w', 0o666)
7
+
8
+ The returned object is a dbm.gnu, dbm.ndbm or dbm.dumb object, dependent on the
9
+ type of database being opened (determined by the whichdb function) in the case
10
+ of an existing dbm. If the dbm does not exist and the create or new flag ('c'
11
+ or 'n') was specified, the dbm type will be determined by the availability of
12
+ the modules (tested in the above order).
13
+
14
+ It has the following interface (key and data are strings):
15
+
16
+ d[key] = data # store data at key (may override data at
17
+ # existing key)
18
+ data = d[key] # retrieve data at key (raise KeyError if no
19
+ # such key)
20
+ del d[key] # delete data stored at key (raises KeyError
21
+ # if no such key)
22
+ flag = key in d # true if the key exists
23
+ list = d.keys() # return a list of all existing keys (slow!)
24
+
25
+ Future versions may change the order in which implementations are
26
+ tested for existence, and add interfaces to other dbm-like
27
+ implementations.
28
+ """
29
+
30
+ __all__ = ['open', 'whichdb', 'error']
31
+
32
+ import io
33
+ import os
34
+ import struct
35
+ import sys
36
+
37
+
38
+ class error(Exception):
39
+ pass
40
+
41
+ _names = ['dbm.gnu', 'dbm.ndbm', 'dbm.dumb']
42
+ _defaultmod = None
43
+ _modules = {}
44
+
45
+ error = (error, OSError)
46
+
47
+ try:
48
+ from dbm import ndbm
49
+ except ImportError:
50
+ ndbm = None
51
+
52
+
53
+ def open(file, flag='r', mode=0o666):
54
+ """Open or create database at path given by *file*.
55
+
56
+ Optional argument *flag* can be 'r' (default) for read-only access, 'w'
57
+ for read-write access of an existing database, 'c' for read-write access
58
+ to a new or existing database, and 'n' for read-write access to a new
59
+ database.
60
+
61
+ Note: 'r' and 'w' fail if the database doesn't exist; 'c' creates it
62
+ only if it doesn't exist; and 'n' always creates a new database.
63
+ """
64
+ global _defaultmod
65
+ if _defaultmod is None:
66
+ for name in _names:
67
+ try:
68
+ mod = __import__(name, fromlist=['open'])
69
+ except ImportError:
70
+ continue
71
+ if not _defaultmod:
72
+ _defaultmod = mod
73
+ _modules[name] = mod
74
+ if not _defaultmod:
75
+ raise ImportError("no dbm clone found; tried %s" % _names)
76
+
77
+ # guess the type of an existing database, if not creating a new one
78
+ result = whichdb(file) if 'n' not in flag else None
79
+ if result is None:
80
+ # db doesn't exist or 'n' flag was specified to create a new db
81
+ if 'c' in flag or 'n' in flag:
82
+ # file doesn't exist and the new flag was used so use default type
83
+ mod = _defaultmod
84
+ else:
85
+ raise error[0]("db file doesn't exist; "
86
+ "use 'c' or 'n' flag to create a new db")
87
+ elif result == "":
88
+ # db type cannot be determined
89
+ raise error[0]("db type could not be determined")
90
+ elif result not in _modules:
91
+ raise error[0]("db type is {0}, but the module is not "
92
+ "available".format(result))
93
+ else:
94
+ mod = _modules[result]
95
+ return mod.open(file, flag, mode)
96
+
97
+
98
+ def whichdb(filename):
99
+ """Guess which db package to use to open a db file.
100
+
101
+ Return values:
102
+
103
+ - None if the database file can't be read;
104
+ - empty string if the file can be read but can't be recognized
105
+ - the name of the dbm submodule (e.g. "ndbm" or "gnu") if recognized.
106
+
107
+ Importing the given module may still fail, and opening the
108
+ database using that module may still fail.
109
+ """
110
+
111
+ # Check for ndbm first -- this has a .pag and a .dir file
112
+ try:
113
+ f = io.open(filename + ".pag", "rb")
114
+ f.close()
115
+ f = io.open(filename + ".dir", "rb")
116
+ f.close()
117
+ return "dbm.ndbm"
118
+ except OSError:
119
+ # some dbm emulations based on Berkeley DB generate a .db file
120
+ # some do not, but they should be caught by the bsd checks
121
+ try:
122
+ f = io.open(filename + ".db", "rb")
123
+ f.close()
124
+ # guarantee we can actually open the file using dbm
125
+ # kind of overkill, but since we are dealing with emulations
126
+ # it seems like a prudent step
127
+ if ndbm is not None:
128
+ d = ndbm.open(filename)
129
+ d.close()
130
+ return "dbm.ndbm"
131
+ except OSError:
132
+ pass
133
+
134
+ # Check for dumbdbm next -- this has a .dir and a .dat file
135
+ try:
136
+ # First check for presence of files
137
+ os.stat(filename + ".dat")
138
+ size = os.stat(filename + ".dir").st_size
139
+ # dumbdbm files with no keys are empty
140
+ if size == 0:
141
+ return "dbm.dumb"
142
+ f = io.open(filename + ".dir", "rb")
143
+ try:
144
+ if f.read(1) in (b"'", b'"'):
145
+ return "dbm.dumb"
146
+ finally:
147
+ f.close()
148
+ except OSError:
149
+ pass
150
+
151
+ # See if the file exists, return None if not
152
+ try:
153
+ f = io.open(filename, "rb")
154
+ except OSError:
155
+ return None
156
+
157
+ with f:
158
+ # Read the start of the file -- the magic number
159
+ s16 = f.read(16)
160
+ s = s16[0:4]
161
+
162
+ # Return "" if not at least 4 bytes
163
+ if len(s) != 4:
164
+ return ""
165
+
166
+ # Convert to 4-byte int in native byte order -- return "" if impossible
167
+ try:
168
+ (magic,) = struct.unpack("=l", s)
169
+ except struct.error:
170
+ return ""
171
+
172
+ # Check for GNU dbm
173
+ if magic in (0x13579ace, 0x13579acd, 0x13579acf):
174
+ return "dbm.gnu"
175
+
176
+ # Later versions of Berkeley db hash file have a 12-byte pad in
177
+ # front of the file type
178
+ try:
179
+ (magic,) = struct.unpack("=l", s16[-4:])
180
+ except struct.error:
181
+ return ""
182
+
183
+ # Unknown
184
+ return ""
185
+
186
+
187
+ if __name__ == "__main__":
188
+ for filename in sys.argv[1:]:
189
+ print(whichdb(filename) or "UNKNOWN", filename)
my_container_sandbox/workspace/anaconda3/lib/python3.8/dbm/dumb.py ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A dumb and slow but simple dbm clone.
2
+
3
+ For database spam, spam.dir contains the index (a text file),
4
+ spam.bak *may* contain a backup of the index (also a text file),
5
+ while spam.dat contains the data (a binary file).
6
+
7
+ XXX TO DO:
8
+
9
+ - seems to contain a bug when updating...
10
+
11
+ - reclaim free space (currently, space once occupied by deleted or expanded
12
+ items is never reused)
13
+
14
+ - support concurrent access (currently, if two processes take turns making
15
+ updates, they can mess up the index)
16
+
17
+ - support efficient access to large databases (currently, the whole index
18
+ is read when the database is opened, and some updates rewrite the whole index)
19
+
20
+ - support opening for read-only (flag = 'm')
21
+
22
+ """
23
+
24
+ import ast as _ast
25
+ import io as _io
26
+ import os as _os
27
+ import collections.abc
28
+
29
+ __all__ = ["error", "open"]
30
+
31
+ _BLOCKSIZE = 512
32
+
33
+ error = OSError
34
+
35
+ class _Database(collections.abc.MutableMapping):
36
+
37
+ # The on-disk directory and data files can remain in mutually
38
+ # inconsistent states for an arbitrarily long time (see comments
39
+ # at the end of __setitem__). This is only repaired when _commit()
40
+ # gets called. One place _commit() gets called is from __del__(),
41
+ # and if that occurs at program shutdown time, module globals may
42
+ # already have gotten rebound to None. Since it's crucial that
43
+ # _commit() finish successfully, we can't ignore shutdown races
44
+ # here, and _commit() must not reference any globals.
45
+ _os = _os # for _commit()
46
+ _io = _io # for _commit()
47
+
48
+ def __init__(self, filebasename, mode, flag='c'):
49
+ self._mode = mode
50
+ self._readonly = (flag == 'r')
51
+
52
+ # The directory file is a text file. Each line looks like
53
+ # "%r, (%d, %d)\n" % (key, pos, siz)
54
+ # where key is the string key, pos is the offset into the dat
55
+ # file of the associated value's first byte, and siz is the number
56
+ # of bytes in the associated value.
57
+ self._dirfile = filebasename + '.dir'
58
+
59
+ # The data file is a binary file pointed into by the directory
60
+ # file, and holds the values associated with keys. Each value
61
+ # begins at a _BLOCKSIZE-aligned byte offset, and is a raw
62
+ # binary 8-bit string value.
63
+ self._datfile = filebasename + '.dat'
64
+ self._bakfile = filebasename + '.bak'
65
+
66
+ # The index is an in-memory dict, mirroring the directory file.
67
+ self._index = None # maps keys to (pos, siz) pairs
68
+
69
+ # Handle the creation
70
+ self._create(flag)
71
+ self._update(flag)
72
+
73
+ def _create(self, flag):
74
+ if flag == 'n':
75
+ for filename in (self._datfile, self._bakfile, self._dirfile):
76
+ try:
77
+ _os.remove(filename)
78
+ except OSError:
79
+ pass
80
+ # Mod by Jack: create data file if needed
81
+ try:
82
+ f = _io.open(self._datfile, 'r', encoding="Latin-1")
83
+ except OSError:
84
+ if flag not in ('c', 'n'):
85
+ raise
86
+ with _io.open(self._datfile, 'w', encoding="Latin-1") as f:
87
+ self._chmod(self._datfile)
88
+ else:
89
+ f.close()
90
+
91
+ # Read directory file into the in-memory index dict.
92
+ def _update(self, flag):
93
+ self._modified = False
94
+ self._index = {}
95
+ try:
96
+ f = _io.open(self._dirfile, 'r', encoding="Latin-1")
97
+ except OSError:
98
+ if flag not in ('c', 'n'):
99
+ raise
100
+ self._modified = True
101
+ else:
102
+ with f:
103
+ for line in f:
104
+ line = line.rstrip()
105
+ key, pos_and_siz_pair = _ast.literal_eval(line)
106
+ key = key.encode('Latin-1')
107
+ self._index[key] = pos_and_siz_pair
108
+
109
+ # Write the index dict to the directory file. The original directory
110
+ # file (if any) is renamed with a .bak extension first. If a .bak
111
+ # file currently exists, it's deleted.
112
+ def _commit(self):
113
+ # CAUTION: It's vital that _commit() succeed, and _commit() can
114
+ # be called from __del__(). Therefore we must never reference a
115
+ # global in this routine.
116
+ if self._index is None or not self._modified:
117
+ return # nothing to do
118
+
119
+ try:
120
+ self._os.unlink(self._bakfile)
121
+ except OSError:
122
+ pass
123
+
124
+ try:
125
+ self._os.rename(self._dirfile, self._bakfile)
126
+ except OSError:
127
+ pass
128
+
129
+ with self._io.open(self._dirfile, 'w', encoding="Latin-1") as f:
130
+ self._chmod(self._dirfile)
131
+ for key, pos_and_siz_pair in self._index.items():
132
+ # Use Latin-1 since it has no qualms with any value in any
133
+ # position; UTF-8, though, does care sometimes.
134
+ entry = "%r, %r\n" % (key.decode('Latin-1'), pos_and_siz_pair)
135
+ f.write(entry)
136
+
137
+ sync = _commit
138
+
139
+ def _verify_open(self):
140
+ if self._index is None:
141
+ raise error('DBM object has already been closed')
142
+
143
+ def __getitem__(self, key):
144
+ if isinstance(key, str):
145
+ key = key.encode('utf-8')
146
+ self._verify_open()
147
+ pos, siz = self._index[key] # may raise KeyError
148
+ with _io.open(self._datfile, 'rb') as f:
149
+ f.seek(pos)
150
+ dat = f.read(siz)
151
+ return dat
152
+
153
+ # Append val to the data file, starting at a _BLOCKSIZE-aligned
154
+ # offset. The data file is first padded with NUL bytes (if needed)
155
+ # to get to an aligned offset. Return pair
156
+ # (starting offset of val, len(val))
157
+ def _addval(self, val):
158
+ with _io.open(self._datfile, 'rb+') as f:
159
+ f.seek(0, 2)
160
+ pos = int(f.tell())
161
+ npos = ((pos + _BLOCKSIZE - 1) // _BLOCKSIZE) * _BLOCKSIZE
162
+ f.write(b'\0'*(npos-pos))
163
+ pos = npos
164
+ f.write(val)
165
+ return (pos, len(val))
166
+
167
+ # Write val to the data file, starting at offset pos. The caller
168
+ # is responsible for ensuring that there's enough room starting at
169
+ # pos to hold val, without overwriting some other value. Return
170
+ # pair (pos, len(val)).
171
+ def _setval(self, pos, val):
172
+ with _io.open(self._datfile, 'rb+') as f:
173
+ f.seek(pos)
174
+ f.write(val)
175
+ return (pos, len(val))
176
+
177
+ # key is a new key whose associated value starts in the data file
178
+ # at offset pos and with length siz. Add an index record to
179
+ # the in-memory index dict, and append one to the directory file.
180
+ def _addkey(self, key, pos_and_siz_pair):
181
+ self._index[key] = pos_and_siz_pair
182
+ with _io.open(self._dirfile, 'a', encoding="Latin-1") as f:
183
+ self._chmod(self._dirfile)
184
+ f.write("%r, %r\n" % (key.decode("Latin-1"), pos_and_siz_pair))
185
+
186
+ def __setitem__(self, key, val):
187
+ if self._readonly:
188
+ raise error('The database is opened for reading only')
189
+ if isinstance(key, str):
190
+ key = key.encode('utf-8')
191
+ elif not isinstance(key, (bytes, bytearray)):
192
+ raise TypeError("keys must be bytes or strings")
193
+ if isinstance(val, str):
194
+ val = val.encode('utf-8')
195
+ elif not isinstance(val, (bytes, bytearray)):
196
+ raise TypeError("values must be bytes or strings")
197
+ self._verify_open()
198
+ self._modified = True
199
+ if key not in self._index:
200
+ self._addkey(key, self._addval(val))
201
+ else:
202
+ # See whether the new value is small enough to fit in the
203
+ # (padded) space currently occupied by the old value.
204
+ pos, siz = self._index[key]
205
+ oldblocks = (siz + _BLOCKSIZE - 1) // _BLOCKSIZE
206
+ newblocks = (len(val) + _BLOCKSIZE - 1) // _BLOCKSIZE
207
+ if newblocks <= oldblocks:
208
+ self._index[key] = self._setval(pos, val)
209
+ else:
210
+ # The new value doesn't fit in the (padded) space used
211
+ # by the old value. The blocks used by the old value are
212
+ # forever lost.
213
+ self._index[key] = self._addval(val)
214
+
215
+ # Note that _index may be out of synch with the directory
216
+ # file now: _setval() and _addval() don't update the directory
217
+ # file. This also means that the on-disk directory and data
218
+ # files are in a mutually inconsistent state, and they'll
219
+ # remain that way until _commit() is called. Note that this
220
+ # is a disaster (for the database) if the program crashes
221
+ # (so that _commit() never gets called).
222
+
223
+ def __delitem__(self, key):
224
+ if self._readonly:
225
+ raise error('The database is opened for reading only')
226
+ if isinstance(key, str):
227
+ key = key.encode('utf-8')
228
+ self._verify_open()
229
+ self._modified = True
230
+ # The blocks used by the associated value are lost.
231
+ del self._index[key]
232
+ # XXX It's unclear why we do a _commit() here (the code always
233
+ # XXX has, so I'm not changing it). __setitem__ doesn't try to
234
+ # XXX keep the directory file in synch. Why should we? Or
235
+ # XXX why shouldn't __setitem__?
236
+ self._commit()
237
+
238
+ def keys(self):
239
+ try:
240
+ return list(self._index)
241
+ except TypeError:
242
+ raise error('DBM object has already been closed') from None
243
+
244
+ def items(self):
245
+ self._verify_open()
246
+ return [(key, self[key]) for key in self._index.keys()]
247
+
248
+ def __contains__(self, key):
249
+ if isinstance(key, str):
250
+ key = key.encode('utf-8')
251
+ try:
252
+ return key in self._index
253
+ except TypeError:
254
+ if self._index is None:
255
+ raise error('DBM object has already been closed') from None
256
+ else:
257
+ raise
258
+
259
+ def iterkeys(self):
260
+ try:
261
+ return iter(self._index)
262
+ except TypeError:
263
+ raise error('DBM object has already been closed') from None
264
+ __iter__ = iterkeys
265
+
266
+ def __len__(self):
267
+ try:
268
+ return len(self._index)
269
+ except TypeError:
270
+ raise error('DBM object has already been closed') from None
271
+
272
+ def close(self):
273
+ try:
274
+ self._commit()
275
+ finally:
276
+ self._index = self._datfile = self._dirfile = self._bakfile = None
277
+
278
+ __del__ = close
279
+
280
+ def _chmod(self, file):
281
+ self._os.chmod(file, self._mode)
282
+
283
+ def __enter__(self):
284
+ return self
285
+
286
+ def __exit__(self, *args):
287
+ self.close()
288
+
289
+
290
+ def open(file, flag='c', mode=0o666):
291
+ """Open the database file, filename, and return corresponding object.
292
+
293
+ The flag argument, used to control how the database is opened in the
294
+ other DBM implementations, supports only the semantics of 'c' and 'n'
295
+ values. Other values will default to the semantics of 'c' value:
296
+ the database will always opened for update and will be created if it
297
+ does not exist.
298
+
299
+ The optional mode argument is the UNIX mode of the file, used only when
300
+ the database has to be created. It defaults to octal code 0o666 (and
301
+ will be modified by the prevailing umask).
302
+
303
+ """
304
+
305
+ # Modify mode depending on the umask
306
+ try:
307
+ um = _os.umask(0)
308
+ _os.umask(um)
309
+ except AttributeError:
310
+ pass
311
+ else:
312
+ # Turn off any bits that are set in the umask
313
+ mode = mode & (~um)
314
+ if flag not in ('r', 'w', 'c', 'n'):
315
+ raise ValueError("Flag must be one of 'r', 'w', 'c', or 'n'")
316
+ return _Database(file, mode, flag=flag)
my_container_sandbox/workspace/anaconda3/lib/python3.8/dbm/gnu.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ """Provide the _gdbm module as a dbm submodule."""
2
+
3
+ from _gdbm import *
my_container_sandbox/workspace/anaconda3/lib/python3.8/dbm/ndbm.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ """Provide the _dbm module as a dbm submodule."""
2
+
3
+ from _dbm import *
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/__init__.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2007 Python Software Foundation
2
+ # Author: Barry Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ """A package for parsing, handling, and generating email messages."""
6
+
7
+ __all__ = [
8
+ 'base64mime',
9
+ 'charset',
10
+ 'encoders',
11
+ 'errors',
12
+ 'feedparser',
13
+ 'generator',
14
+ 'header',
15
+ 'iterators',
16
+ 'message',
17
+ 'message_from_file',
18
+ 'message_from_binary_file',
19
+ 'message_from_string',
20
+ 'message_from_bytes',
21
+ 'mime',
22
+ 'parser',
23
+ 'quoprimime',
24
+ 'utils',
25
+ ]
26
+
27
+
28
+
29
+ # Some convenience routines. Don't import Parser and Message as side-effects
30
+ # of importing email since those cascadingly import most of the rest of the
31
+ # email package.
32
+ def message_from_string(s, *args, **kws):
33
+ """Parse a string into a Message object model.
34
+
35
+ Optional _class and strict are passed to the Parser constructor.
36
+ """
37
+ from email.parser import Parser
38
+ return Parser(*args, **kws).parsestr(s)
39
+
40
+ def message_from_bytes(s, *args, **kws):
41
+ """Parse a bytes string into a Message object model.
42
+
43
+ Optional _class and strict are passed to the Parser constructor.
44
+ """
45
+ from email.parser import BytesParser
46
+ return BytesParser(*args, **kws).parsebytes(s)
47
+
48
+ def message_from_file(fp, *args, **kws):
49
+ """Read a file and parse its contents into a Message object model.
50
+
51
+ Optional _class and strict are passed to the Parser constructor.
52
+ """
53
+ from email.parser import Parser
54
+ return Parser(*args, **kws).parse(fp)
55
+
56
+ def message_from_binary_file(fp, *args, **kws):
57
+ """Read a binary file and parse its contents into a Message object model.
58
+
59
+ Optional _class and strict are passed to the Parser constructor.
60
+ """
61
+ from email.parser import BytesParser
62
+ return BytesParser(*args, **kws).parse(fp)
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/_encoded_words.py ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ Routines for manipulating RFC2047 encoded words.
2
+
3
+ This is currently a package-private API, but will be considered for promotion
4
+ to a public API if there is demand.
5
+
6
+ """
7
+
8
+ # An ecoded word looks like this:
9
+ #
10
+ # =?charset[*lang]?cte?encoded_string?=
11
+ #
12
+ # for more information about charset see the charset module. Here it is one
13
+ # of the preferred MIME charset names (hopefully; you never know when parsing).
14
+ # cte (Content Transfer Encoding) is either 'q' or 'b' (ignoring case). In
15
+ # theory other letters could be used for other encodings, but in practice this
16
+ # (almost?) never happens. There could be a public API for adding entries
17
+ # to the CTE tables, but YAGNI for now. 'q' is Quoted Printable, 'b' is
18
+ # Base64. The meaning of encoded_string should be obvious. 'lang' is optional
19
+ # as indicated by the brackets (they are not part of the syntax) but is almost
20
+ # never encountered in practice.
21
+ #
22
+ # The general interface for a CTE decoder is that it takes the encoded_string
23
+ # as its argument, and returns a tuple (cte_decoded_string, defects). The
24
+ # cte_decoded_string is the original binary that was encoded using the
25
+ # specified cte. 'defects' is a list of MessageDefect instances indicating any
26
+ # problems encountered during conversion. 'charset' and 'lang' are the
27
+ # corresponding strings extracted from the EW, case preserved.
28
+ #
29
+ # The general interface for a CTE encoder is that it takes a binary sequence
30
+ # as input and returns the cte_encoded_string, which is an ascii-only string.
31
+ #
32
+ # Each decoder must also supply a length function that takes the binary
33
+ # sequence as its argument and returns the length of the resulting encoded
34
+ # string.
35
+ #
36
+ # The main API functions for the module are decode, which calls the decoder
37
+ # referenced by the cte specifier, and encode, which adds the appropriate
38
+ # RFC 2047 "chrome" to the encoded string, and can optionally automatically
39
+ # select the shortest possible encoding. See their docstrings below for
40
+ # details.
41
+
42
+ import re
43
+ import base64
44
+ import binascii
45
+ import functools
46
+ from string import ascii_letters, digits
47
+ from email import errors
48
+
49
+ __all__ = ['decode_q',
50
+ 'encode_q',
51
+ 'decode_b',
52
+ 'encode_b',
53
+ 'len_q',
54
+ 'len_b',
55
+ 'decode',
56
+ 'encode',
57
+ ]
58
+
59
+ #
60
+ # Quoted Printable
61
+ #
62
+
63
+ # regex based decoder.
64
+ _q_byte_subber = functools.partial(re.compile(br'=([a-fA-F0-9]{2})').sub,
65
+ lambda m: bytes.fromhex(m.group(1).decode()))
66
+
67
+ def decode_q(encoded):
68
+ encoded = encoded.replace(b'_', b' ')
69
+ return _q_byte_subber(encoded), []
70
+
71
+
72
+ # dict mapping bytes to their encoded form
73
+ class _QByteMap(dict):
74
+
75
+ safe = b'-!*+/' + ascii_letters.encode('ascii') + digits.encode('ascii')
76
+
77
+ def __missing__(self, key):
78
+ if key in self.safe:
79
+ self[key] = chr(key)
80
+ else:
81
+ self[key] = "={:02X}".format(key)
82
+ return self[key]
83
+
84
+ _q_byte_map = _QByteMap()
85
+
86
+ # In headers spaces are mapped to '_'.
87
+ _q_byte_map[ord(' ')] = '_'
88
+
89
+ def encode_q(bstring):
90
+ return ''.join(_q_byte_map[x] for x in bstring)
91
+
92
+ def len_q(bstring):
93
+ return sum(len(_q_byte_map[x]) for x in bstring)
94
+
95
+
96
+ #
97
+ # Base64
98
+ #
99
+
100
+ def decode_b(encoded):
101
+ # First try encoding with validate=True, fixing the padding if needed.
102
+ # This will succeed only if encoded includes no invalid characters.
103
+ pad_err = len(encoded) % 4
104
+ missing_padding = b'==='[:4-pad_err] if pad_err else b''
105
+ try:
106
+ return (
107
+ base64.b64decode(encoded + missing_padding, validate=True),
108
+ [errors.InvalidBase64PaddingDefect()] if pad_err else [],
109
+ )
110
+ except binascii.Error:
111
+ # Since we had correct padding, this is likely an invalid char error.
112
+ #
113
+ # The non-alphabet characters are ignored as far as padding
114
+ # goes, but we don't know how many there are. So try without adding
115
+ # padding to see if it works.
116
+ try:
117
+ return (
118
+ base64.b64decode(encoded, validate=False),
119
+ [errors.InvalidBase64CharactersDefect()],
120
+ )
121
+ except binascii.Error:
122
+ # Add as much padding as could possibly be necessary (extra padding
123
+ # is ignored).
124
+ try:
125
+ return (
126
+ base64.b64decode(encoded + b'==', validate=False),
127
+ [errors.InvalidBase64CharactersDefect(),
128
+ errors.InvalidBase64PaddingDefect()],
129
+ )
130
+ except binascii.Error:
131
+ # This only happens when the encoded string's length is 1 more
132
+ # than a multiple of 4, which is invalid.
133
+ #
134
+ # bpo-27397: Just return the encoded string since there's no
135
+ # way to decode.
136
+ return encoded, [errors.InvalidBase64LengthDefect()]
137
+
138
+ def encode_b(bstring):
139
+ return base64.b64encode(bstring).decode('ascii')
140
+
141
+ def len_b(bstring):
142
+ groups_of_3, leftover = divmod(len(bstring), 3)
143
+ # 4 bytes out for each 3 bytes (or nonzero fraction thereof) in.
144
+ return groups_of_3 * 4 + (4 if leftover else 0)
145
+
146
+
147
+ _cte_decoders = {
148
+ 'q': decode_q,
149
+ 'b': decode_b,
150
+ }
151
+
152
+ def decode(ew):
153
+ """Decode encoded word and return (string, charset, lang, defects) tuple.
154
+
155
+ An RFC 2047/2243 encoded word has the form:
156
+
157
+ =?charset*lang?cte?encoded_string?=
158
+
159
+ where '*lang' may be omitted but the other parts may not be.
160
+
161
+ This function expects exactly such a string (that is, it does not check the
162
+ syntax and may raise errors if the string is not well formed), and returns
163
+ the encoded_string decoded first from its Content Transfer Encoding and
164
+ then from the resulting bytes into unicode using the specified charset. If
165
+ the cte-decoded string does not successfully decode using the specified
166
+ character set, a defect is added to the defects list and the unknown octets
167
+ are replaced by the unicode 'unknown' character \\uFDFF.
168
+
169
+ The specified charset and language are returned. The default for language,
170
+ which is rarely if ever encountered, is the empty string.
171
+
172
+ """
173
+ _, charset, cte, cte_string, _ = ew.split('?')
174
+ charset, _, lang = charset.partition('*')
175
+ cte = cte.lower()
176
+ # Recover the original bytes and do CTE decoding.
177
+ bstring = cte_string.encode('ascii', 'surrogateescape')
178
+ bstring, defects = _cte_decoders[cte](bstring)
179
+ # Turn the CTE decoded bytes into unicode.
180
+ try:
181
+ string = bstring.decode(charset)
182
+ except UnicodeError:
183
+ defects.append(errors.UndecodableBytesDefect("Encoded word "
184
+ "contains bytes not decodable using {} charset".format(charset)))
185
+ string = bstring.decode(charset, 'surrogateescape')
186
+ except LookupError:
187
+ string = bstring.decode('ascii', 'surrogateescape')
188
+ if charset.lower() != 'unknown-8bit':
189
+ defects.append(errors.CharsetError("Unknown charset {} "
190
+ "in encoded word; decoded as unknown bytes".format(charset)))
191
+ return string, charset, lang, defects
192
+
193
+
194
+ _cte_encoders = {
195
+ 'q': encode_q,
196
+ 'b': encode_b,
197
+ }
198
+
199
+ _cte_encode_length = {
200
+ 'q': len_q,
201
+ 'b': len_b,
202
+ }
203
+
204
+ def encode(string, charset='utf-8', encoding=None, lang=''):
205
+ """Encode string using the CTE encoding that produces the shorter result.
206
+
207
+ Produces an RFC 2047/2243 encoded word of the form:
208
+
209
+ =?charset*lang?cte?encoded_string?=
210
+
211
+ where '*lang' is omitted unless the 'lang' parameter is given a value.
212
+ Optional argument charset (defaults to utf-8) specifies the charset to use
213
+ to encode the string to binary before CTE encoding it. Optional argument
214
+ 'encoding' is the cte specifier for the encoding that should be used ('q'
215
+ or 'b'); if it is None (the default) the encoding which produces the
216
+ shortest encoded sequence is used, except that 'q' is preferred if it is up
217
+ to five characters longer. Optional argument 'lang' (default '') gives the
218
+ RFC 2243 language string to specify in the encoded word.
219
+
220
+ """
221
+ if charset == 'unknown-8bit':
222
+ bstring = string.encode('ascii', 'surrogateescape')
223
+ else:
224
+ bstring = string.encode(charset)
225
+ if encoding is None:
226
+ qlen = _cte_encode_length['q'](bstring)
227
+ blen = _cte_encode_length['b'](bstring)
228
+ # Bias toward q. 5 is arbitrary.
229
+ encoding = 'q' if qlen - blen < 5 else 'b'
230
+ encoded = _cte_encoders[encoding](bstring)
231
+ if lang:
232
+ lang = '*' + lang
233
+ return "=?{}{}?{}?{}?=".format(charset, lang, encoding, encoded)
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/_header_value_parser.py ADDED
The diff for this file is too large to render. See raw diff
 
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/_parseaddr.py ADDED
@@ -0,0 +1,551 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2002-2007 Python Software Foundation
2
+ # Contact: email-sig@python.org
3
+
4
+ """Email address parsing code.
5
+
6
+ Lifted directly from rfc822.py. This should eventually be rewritten.
7
+ """
8
+
9
+ __all__ = [
10
+ 'mktime_tz',
11
+ 'parsedate',
12
+ 'parsedate_tz',
13
+ 'quote',
14
+ ]
15
+
16
+ import time, calendar
17
+
18
+ SPACE = ' '
19
+ EMPTYSTRING = ''
20
+ COMMASPACE = ', '
21
+
22
+ # Parse a date field
23
+ _monthnames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul',
24
+ 'aug', 'sep', 'oct', 'nov', 'dec',
25
+ 'january', 'february', 'march', 'april', 'may', 'june', 'july',
26
+ 'august', 'september', 'october', 'november', 'december']
27
+
28
+ _daynames = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
29
+
30
+ # The timezone table does not include the military time zones defined
31
+ # in RFC822, other than Z. According to RFC1123, the description in
32
+ # RFC822 gets the signs wrong, so we can't rely on any such time
33
+ # zones. RFC1123 recommends that numeric timezone indicators be used
34
+ # instead of timezone names.
35
+
36
+ _timezones = {'UT':0, 'UTC':0, 'GMT':0, 'Z':0,
37
+ 'AST': -400, 'ADT': -300, # Atlantic (used in Canada)
38
+ 'EST': -500, 'EDT': -400, # Eastern
39
+ 'CST': -600, 'CDT': -500, # Central
40
+ 'MST': -700, 'MDT': -600, # Mountain
41
+ 'PST': -800, 'PDT': -700 # Pacific
42
+ }
43
+
44
+
45
+ def parsedate_tz(data):
46
+ """Convert a date string to a time tuple.
47
+
48
+ Accounts for military timezones.
49
+ """
50
+ res = _parsedate_tz(data)
51
+ if not res:
52
+ return
53
+ if res[9] is None:
54
+ res[9] = 0
55
+ return tuple(res)
56
+
57
+ def _parsedate_tz(data):
58
+ """Convert date to extended time tuple.
59
+
60
+ The last (additional) element is the time zone offset in seconds, except if
61
+ the timezone was specified as -0000. In that case the last element is
62
+ None. This indicates a UTC timestamp that explicitly declaims knowledge of
63
+ the source timezone, as opposed to a +0000 timestamp that indicates the
64
+ source timezone really was UTC.
65
+
66
+ """
67
+ if not data:
68
+ return
69
+ data = data.split()
70
+ if not data: # This happens for whitespace-only input.
71
+ return None
72
+ # The FWS after the comma after the day-of-week is optional, so search and
73
+ # adjust for this.
74
+ if data[0].endswith(',') or data[0].lower() in _daynames:
75
+ # There's a dayname here. Skip it
76
+ del data[0]
77
+ else:
78
+ i = data[0].rfind(',')
79
+ if i >= 0:
80
+ data[0] = data[0][i+1:]
81
+ if len(data) == 3: # RFC 850 date, deprecated
82
+ stuff = data[0].split('-')
83
+ if len(stuff) == 3:
84
+ data = stuff + data[1:]
85
+ if len(data) == 4:
86
+ s = data[3]
87
+ i = s.find('+')
88
+ if i == -1:
89
+ i = s.find('-')
90
+ if i > 0:
91
+ data[3:] = [s[:i], s[i:]]
92
+ else:
93
+ data.append('') # Dummy tz
94
+ if len(data) < 5:
95
+ return None
96
+ data = data[:5]
97
+ [dd, mm, yy, tm, tz] = data
98
+ mm = mm.lower()
99
+ if mm not in _monthnames:
100
+ dd, mm = mm, dd.lower()
101
+ if mm not in _monthnames:
102
+ return None
103
+ mm = _monthnames.index(mm) + 1
104
+ if mm > 12:
105
+ mm -= 12
106
+ if dd[-1] == ',':
107
+ dd = dd[:-1]
108
+ i = yy.find(':')
109
+ if i > 0:
110
+ yy, tm = tm, yy
111
+ if yy[-1] == ',':
112
+ yy = yy[:-1]
113
+ if not yy[0].isdigit():
114
+ yy, tz = tz, yy
115
+ if tm[-1] == ',':
116
+ tm = tm[:-1]
117
+ tm = tm.split(':')
118
+ if len(tm) == 2:
119
+ [thh, tmm] = tm
120
+ tss = '0'
121
+ elif len(tm) == 3:
122
+ [thh, tmm, tss] = tm
123
+ elif len(tm) == 1 and '.' in tm[0]:
124
+ # Some non-compliant MUAs use '.' to separate time elements.
125
+ tm = tm[0].split('.')
126
+ if len(tm) == 2:
127
+ [thh, tmm] = tm
128
+ tss = 0
129
+ elif len(tm) == 3:
130
+ [thh, tmm, tss] = tm
131
+ else:
132
+ return None
133
+ try:
134
+ yy = int(yy)
135
+ dd = int(dd)
136
+ thh = int(thh)
137
+ tmm = int(tmm)
138
+ tss = int(tss)
139
+ except ValueError:
140
+ return None
141
+ # Check for a yy specified in two-digit format, then convert it to the
142
+ # appropriate four-digit format, according to the POSIX standard. RFC 822
143
+ # calls for a two-digit yy, but RFC 2822 (which obsoletes RFC 822)
144
+ # mandates a 4-digit yy. For more information, see the documentation for
145
+ # the time module.
146
+ if yy < 100:
147
+ # The year is between 1969 and 1999 (inclusive).
148
+ if yy > 68:
149
+ yy += 1900
150
+ # The year is between 2000 and 2068 (inclusive).
151
+ else:
152
+ yy += 2000
153
+ tzoffset = None
154
+ tz = tz.upper()
155
+ if tz in _timezones:
156
+ tzoffset = _timezones[tz]
157
+ else:
158
+ try:
159
+ tzoffset = int(tz)
160
+ except ValueError:
161
+ pass
162
+ if tzoffset==0 and tz.startswith('-'):
163
+ tzoffset = None
164
+ # Convert a timezone offset into seconds ; -0500 -> -18000
165
+ if tzoffset:
166
+ if tzoffset < 0:
167
+ tzsign = -1
168
+ tzoffset = -tzoffset
169
+ else:
170
+ tzsign = 1
171
+ tzoffset = tzsign * ( (tzoffset//100)*3600 + (tzoffset % 100)*60)
172
+ # Daylight Saving Time flag is set to -1, since DST is unknown.
173
+ return [yy, mm, dd, thh, tmm, tss, 0, 1, -1, tzoffset]
174
+
175
+
176
+ def parsedate(data):
177
+ """Convert a time string to a time tuple."""
178
+ t = parsedate_tz(data)
179
+ if isinstance(t, tuple):
180
+ return t[:9]
181
+ else:
182
+ return t
183
+
184
+
185
+ def mktime_tz(data):
186
+ """Turn a 10-tuple as returned by parsedate_tz() into a POSIX timestamp."""
187
+ if data[9] is None:
188
+ # No zone info, so localtime is better assumption than GMT
189
+ return time.mktime(data[:8] + (-1,))
190
+ else:
191
+ t = calendar.timegm(data)
192
+ return t - data[9]
193
+
194
+
195
+ def quote(str):
196
+ """Prepare string to be used in a quoted string.
197
+
198
+ Turns backslash and double quote characters into quoted pairs. These
199
+ are the only characters that need to be quoted inside a quoted string.
200
+ Does not add the surrounding double quotes.
201
+ """
202
+ return str.replace('\\', '\\\\').replace('"', '\\"')
203
+
204
+
205
+ class AddrlistClass:
206
+ """Address parser class by Ben Escoto.
207
+
208
+ To understand what this class does, it helps to have a copy of RFC 2822 in
209
+ front of you.
210
+
211
+ Note: this class interface is deprecated and may be removed in the future.
212
+ Use email.utils.AddressList instead.
213
+ """
214
+
215
+ def __init__(self, field):
216
+ """Initialize a new instance.
217
+
218
+ `field' is an unparsed address header field, containing
219
+ one or more addresses.
220
+ """
221
+ self.specials = '()<>@,:;.\"[]'
222
+ self.pos = 0
223
+ self.LWS = ' \t'
224
+ self.CR = '\r\n'
225
+ self.FWS = self.LWS + self.CR
226
+ self.atomends = self.specials + self.LWS + self.CR
227
+ # Note that RFC 2822 now specifies `.' as obs-phrase, meaning that it
228
+ # is obsolete syntax. RFC 2822 requires that we recognize obsolete
229
+ # syntax, so allow dots in phrases.
230
+ self.phraseends = self.atomends.replace('.', '')
231
+ self.field = field
232
+ self.commentlist = []
233
+
234
+ def gotonext(self):
235
+ """Skip white space and extract comments."""
236
+ wslist = []
237
+ while self.pos < len(self.field):
238
+ if self.field[self.pos] in self.LWS + '\n\r':
239
+ if self.field[self.pos] not in '\n\r':
240
+ wslist.append(self.field[self.pos])
241
+ self.pos += 1
242
+ elif self.field[self.pos] == '(':
243
+ self.commentlist.append(self.getcomment())
244
+ else:
245
+ break
246
+ return EMPTYSTRING.join(wslist)
247
+
248
+ def getaddrlist(self):
249
+ """Parse all addresses.
250
+
251
+ Returns a list containing all of the addresses.
252
+ """
253
+ result = []
254
+ while self.pos < len(self.field):
255
+ ad = self.getaddress()
256
+ if ad:
257
+ result += ad
258
+ else:
259
+ result.append(('', ''))
260
+ return result
261
+
262
+ def getaddress(self):
263
+ """Parse the next address."""
264
+ self.commentlist = []
265
+ self.gotonext()
266
+
267
+ oldpos = self.pos
268
+ oldcl = self.commentlist
269
+ plist = self.getphraselist()
270
+
271
+ self.gotonext()
272
+ returnlist = []
273
+
274
+ if self.pos >= len(self.field):
275
+ # Bad email address technically, no domain.
276
+ if plist:
277
+ returnlist = [(SPACE.join(self.commentlist), plist[0])]
278
+
279
+ elif self.field[self.pos] in '.@':
280
+ # email address is just an addrspec
281
+ # this isn't very efficient since we start over
282
+ self.pos = oldpos
283
+ self.commentlist = oldcl
284
+ addrspec = self.getaddrspec()
285
+ returnlist = [(SPACE.join(self.commentlist), addrspec)]
286
+
287
+ elif self.field[self.pos] == ':':
288
+ # address is a group
289
+ returnlist = []
290
+
291
+ fieldlen = len(self.field)
292
+ self.pos += 1
293
+ while self.pos < len(self.field):
294
+ self.gotonext()
295
+ if self.pos < fieldlen and self.field[self.pos] == ';':
296
+ self.pos += 1
297
+ break
298
+ returnlist = returnlist + self.getaddress()
299
+
300
+ elif self.field[self.pos] == '<':
301
+ # Address is a phrase then a route addr
302
+ routeaddr = self.getrouteaddr()
303
+
304
+ if self.commentlist:
305
+ returnlist = [(SPACE.join(plist) + ' (' +
306
+ ' '.join(self.commentlist) + ')', routeaddr)]
307
+ else:
308
+ returnlist = [(SPACE.join(plist), routeaddr)]
309
+
310
+ else:
311
+ if plist:
312
+ returnlist = [(SPACE.join(self.commentlist), plist[0])]
313
+ elif self.field[self.pos] in self.specials:
314
+ self.pos += 1
315
+
316
+ self.gotonext()
317
+ if self.pos < len(self.field) and self.field[self.pos] == ',':
318
+ self.pos += 1
319
+ return returnlist
320
+
321
+ def getrouteaddr(self):
322
+ """Parse a route address (Return-path value).
323
+
324
+ This method just skips all the route stuff and returns the addrspec.
325
+ """
326
+ if self.field[self.pos] != '<':
327
+ return
328
+
329
+ expectroute = False
330
+ self.pos += 1
331
+ self.gotonext()
332
+ adlist = ''
333
+ while self.pos < len(self.field):
334
+ if expectroute:
335
+ self.getdomain()
336
+ expectroute = False
337
+ elif self.field[self.pos] == '>':
338
+ self.pos += 1
339
+ break
340
+ elif self.field[self.pos] == '@':
341
+ self.pos += 1
342
+ expectroute = True
343
+ elif self.field[self.pos] == ':':
344
+ self.pos += 1
345
+ else:
346
+ adlist = self.getaddrspec()
347
+ self.pos += 1
348
+ break
349
+ self.gotonext()
350
+
351
+ return adlist
352
+
353
+ def getaddrspec(self):
354
+ """Parse an RFC 2822 addr-spec."""
355
+ aslist = []
356
+
357
+ self.gotonext()
358
+ while self.pos < len(self.field):
359
+ preserve_ws = True
360
+ if self.field[self.pos] == '.':
361
+ if aslist and not aslist[-1].strip():
362
+ aslist.pop()
363
+ aslist.append('.')
364
+ self.pos += 1
365
+ preserve_ws = False
366
+ elif self.field[self.pos] == '"':
367
+ aslist.append('"%s"' % quote(self.getquote()))
368
+ elif self.field[self.pos] in self.atomends:
369
+ if aslist and not aslist[-1].strip():
370
+ aslist.pop()
371
+ break
372
+ else:
373
+ aslist.append(self.getatom())
374
+ ws = self.gotonext()
375
+ if preserve_ws and ws:
376
+ aslist.append(ws)
377
+
378
+ if self.pos >= len(self.field) or self.field[self.pos] != '@':
379
+ return EMPTYSTRING.join(aslist)
380
+
381
+ aslist.append('@')
382
+ self.pos += 1
383
+ self.gotonext()
384
+ domain = self.getdomain()
385
+ if not domain:
386
+ # Invalid domain, return an empty address instead of returning a
387
+ # local part to denote failed parsing.
388
+ return EMPTYSTRING
389
+ return EMPTYSTRING.join(aslist) + domain
390
+
391
+ def getdomain(self):
392
+ """Get the complete domain name from an address."""
393
+ sdlist = []
394
+ while self.pos < len(self.field):
395
+ if self.field[self.pos] in self.LWS:
396
+ self.pos += 1
397
+ elif self.field[self.pos] == '(':
398
+ self.commentlist.append(self.getcomment())
399
+ elif self.field[self.pos] == '[':
400
+ sdlist.append(self.getdomainliteral())
401
+ elif self.field[self.pos] == '.':
402
+ self.pos += 1
403
+ sdlist.append('.')
404
+ elif self.field[self.pos] == '@':
405
+ # bpo-34155: Don't parse domains with two `@` like
406
+ # `a@malicious.org@important.com`.
407
+ return EMPTYSTRING
408
+ elif self.field[self.pos] in self.atomends:
409
+ break
410
+ else:
411
+ sdlist.append(self.getatom())
412
+ return EMPTYSTRING.join(sdlist)
413
+
414
+ def getdelimited(self, beginchar, endchars, allowcomments=True):
415
+ """Parse a header fragment delimited by special characters.
416
+
417
+ `beginchar' is the start character for the fragment.
418
+ If self is not looking at an instance of `beginchar' then
419
+ getdelimited returns the empty string.
420
+
421
+ `endchars' is a sequence of allowable end-delimiting characters.
422
+ Parsing stops when one of these is encountered.
423
+
424
+ If `allowcomments' is non-zero, embedded RFC 2822 comments are allowed
425
+ within the parsed fragment.
426
+ """
427
+ if self.field[self.pos] != beginchar:
428
+ return ''
429
+
430
+ slist = ['']
431
+ quote = False
432
+ self.pos += 1
433
+ while self.pos < len(self.field):
434
+ if quote:
435
+ slist.append(self.field[self.pos])
436
+ quote = False
437
+ elif self.field[self.pos] in endchars:
438
+ self.pos += 1
439
+ break
440
+ elif allowcomments and self.field[self.pos] == '(':
441
+ slist.append(self.getcomment())
442
+ continue # have already advanced pos from getcomment
443
+ elif self.field[self.pos] == '\\':
444
+ quote = True
445
+ else:
446
+ slist.append(self.field[self.pos])
447
+ self.pos += 1
448
+
449
+ return EMPTYSTRING.join(slist)
450
+
451
+ def getquote(self):
452
+ """Get a quote-delimited fragment from self's field."""
453
+ return self.getdelimited('"', '"\r', False)
454
+
455
+ def getcomment(self):
456
+ """Get a parenthesis-delimited fragment from self's field."""
457
+ return self.getdelimited('(', ')\r', True)
458
+
459
+ def getdomainliteral(self):
460
+ """Parse an RFC 2822 domain-literal."""
461
+ return '[%s]' % self.getdelimited('[', ']\r', False)
462
+
463
+ def getatom(self, atomends=None):
464
+ """Parse an RFC 2822 atom.
465
+
466
+ Optional atomends specifies a different set of end token delimiters
467
+ (the default is to use self.atomends). This is used e.g. in
468
+ getphraselist() since phrase endings must not include the `.' (which
469
+ is legal in phrases)."""
470
+ atomlist = ['']
471
+ if atomends is None:
472
+ atomends = self.atomends
473
+
474
+ while self.pos < len(self.field):
475
+ if self.field[self.pos] in atomends:
476
+ break
477
+ else:
478
+ atomlist.append(self.field[self.pos])
479
+ self.pos += 1
480
+
481
+ return EMPTYSTRING.join(atomlist)
482
+
483
+ def getphraselist(self):
484
+ """Parse a sequence of RFC 2822 phrases.
485
+
486
+ A phrase is a sequence of words, which are in turn either RFC 2822
487
+ atoms or quoted-strings. Phrases are canonicalized by squeezing all
488
+ runs of continuous whitespace into one space.
489
+ """
490
+ plist = []
491
+
492
+ while self.pos < len(self.field):
493
+ if self.field[self.pos] in self.FWS:
494
+ self.pos += 1
495
+ elif self.field[self.pos] == '"':
496
+ plist.append(self.getquote())
497
+ elif self.field[self.pos] == '(':
498
+ self.commentlist.append(self.getcomment())
499
+ elif self.field[self.pos] in self.phraseends:
500
+ break
501
+ else:
502
+ plist.append(self.getatom(self.phraseends))
503
+
504
+ return plist
505
+
506
+ class AddressList(AddrlistClass):
507
+ """An AddressList encapsulates a list of parsed RFC 2822 addresses."""
508
+ def __init__(self, field):
509
+ AddrlistClass.__init__(self, field)
510
+ if field:
511
+ self.addresslist = self.getaddrlist()
512
+ else:
513
+ self.addresslist = []
514
+
515
+ def __len__(self):
516
+ return len(self.addresslist)
517
+
518
+ def __add__(self, other):
519
+ # Set union
520
+ newaddr = AddressList(None)
521
+ newaddr.addresslist = self.addresslist[:]
522
+ for x in other.addresslist:
523
+ if not x in self.addresslist:
524
+ newaddr.addresslist.append(x)
525
+ return newaddr
526
+
527
+ def __iadd__(self, other):
528
+ # Set union, in-place
529
+ for x in other.addresslist:
530
+ if not x in self.addresslist:
531
+ self.addresslist.append(x)
532
+ return self
533
+
534
+ def __sub__(self, other):
535
+ # Set difference
536
+ newaddr = AddressList(None)
537
+ for x in self.addresslist:
538
+ if not x in other.addresslist:
539
+ newaddr.addresslist.append(x)
540
+ return newaddr
541
+
542
+ def __isub__(self, other):
543
+ # Set difference, in-place
544
+ for x in other.addresslist:
545
+ if x in self.addresslist:
546
+ self.addresslist.remove(x)
547
+ return self
548
+
549
+ def __getitem__(self, index):
550
+ # Make indexing, slices, and 'in' work
551
+ return self.addresslist[index]
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/_policybase.py ADDED
@@ -0,0 +1,374 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Policy framework for the email package.
2
+
3
+ Allows fine grained feature control of how the package parses and emits data.
4
+ """
5
+
6
+ import abc
7
+ from email import header
8
+ from email import charset as _charset
9
+ from email.utils import _has_surrogates
10
+
11
+ __all__ = [
12
+ 'Policy',
13
+ 'Compat32',
14
+ 'compat32',
15
+ ]
16
+
17
+
18
+ class _PolicyBase:
19
+
20
+ """Policy Object basic framework.
21
+
22
+ This class is useless unless subclassed. A subclass should define
23
+ class attributes with defaults for any values that are to be
24
+ managed by the Policy object. The constructor will then allow
25
+ non-default values to be set for these attributes at instance
26
+ creation time. The instance will be callable, taking these same
27
+ attributes keyword arguments, and returning a new instance
28
+ identical to the called instance except for those values changed
29
+ by the keyword arguments. Instances may be added, yielding new
30
+ instances with any non-default values from the right hand
31
+ operand overriding those in the left hand operand. That is,
32
+
33
+ A + B == A(<non-default values of B>)
34
+
35
+ The repr of an instance can be used to reconstruct the object
36
+ if and only if the repr of the values can be used to reconstruct
37
+ those values.
38
+
39
+ """
40
+
41
+ def __init__(self, **kw):
42
+ """Create new Policy, possibly overriding some defaults.
43
+
44
+ See class docstring for a list of overridable attributes.
45
+
46
+ """
47
+ for name, value in kw.items():
48
+ if hasattr(self, name):
49
+ super(_PolicyBase,self).__setattr__(name, value)
50
+ else:
51
+ raise TypeError(
52
+ "{!r} is an invalid keyword argument for {}".format(
53
+ name, self.__class__.__name__))
54
+
55
+ def __repr__(self):
56
+ args = [ "{}={!r}".format(name, value)
57
+ for name, value in self.__dict__.items() ]
58
+ return "{}({})".format(self.__class__.__name__, ', '.join(args))
59
+
60
+ def clone(self, **kw):
61
+ """Return a new instance with specified attributes changed.
62
+
63
+ The new instance has the same attribute values as the current object,
64
+ except for the changes passed in as keyword arguments.
65
+
66
+ """
67
+ newpolicy = self.__class__.__new__(self.__class__)
68
+ for attr, value in self.__dict__.items():
69
+ object.__setattr__(newpolicy, attr, value)
70
+ for attr, value in kw.items():
71
+ if not hasattr(self, attr):
72
+ raise TypeError(
73
+ "{!r} is an invalid keyword argument for {}".format(
74
+ attr, self.__class__.__name__))
75
+ object.__setattr__(newpolicy, attr, value)
76
+ return newpolicy
77
+
78
+ def __setattr__(self, name, value):
79
+ if hasattr(self, name):
80
+ msg = "{!r} object attribute {!r} is read-only"
81
+ else:
82
+ msg = "{!r} object has no attribute {!r}"
83
+ raise AttributeError(msg.format(self.__class__.__name__, name))
84
+
85
+ def __add__(self, other):
86
+ """Non-default values from right operand override those from left.
87
+
88
+ The object returned is a new instance of the subclass.
89
+
90
+ """
91
+ return self.clone(**other.__dict__)
92
+
93
+
94
+ def _append_doc(doc, added_doc):
95
+ doc = doc.rsplit('\n', 1)[0]
96
+ added_doc = added_doc.split('\n', 1)[1]
97
+ return doc + '\n' + added_doc
98
+
99
+ def _extend_docstrings(cls):
100
+ if cls.__doc__ and cls.__doc__.startswith('+'):
101
+ cls.__doc__ = _append_doc(cls.__bases__[0].__doc__, cls.__doc__)
102
+ for name, attr in cls.__dict__.items():
103
+ if attr.__doc__ and attr.__doc__.startswith('+'):
104
+ for c in (c for base in cls.__bases__ for c in base.mro()):
105
+ doc = getattr(getattr(c, name), '__doc__')
106
+ if doc:
107
+ attr.__doc__ = _append_doc(doc, attr.__doc__)
108
+ break
109
+ return cls
110
+
111
+
112
+ class Policy(_PolicyBase, metaclass=abc.ABCMeta):
113
+
114
+ r"""Controls for how messages are interpreted and formatted.
115
+
116
+ Most of the classes and many of the methods in the email package accept
117
+ Policy objects as parameters. A Policy object contains a set of values and
118
+ functions that control how input is interpreted and how output is rendered.
119
+ For example, the parameter 'raise_on_defect' controls whether or not an RFC
120
+ violation results in an error being raised or not, while 'max_line_length'
121
+ controls the maximum length of output lines when a Message is serialized.
122
+
123
+ Any valid attribute may be overridden when a Policy is created by passing
124
+ it as a keyword argument to the constructor. Policy objects are immutable,
125
+ but a new Policy object can be created with only certain values changed by
126
+ calling the Policy instance with keyword arguments. Policy objects can
127
+ also be added, producing a new Policy object in which the non-default
128
+ attributes set in the right hand operand overwrite those specified in the
129
+ left operand.
130
+
131
+ Settable attributes:
132
+
133
+ raise_on_defect -- If true, then defects should be raised as errors.
134
+ Default: False.
135
+
136
+ linesep -- string containing the value to use as separation
137
+ between output lines. Default '\n'.
138
+
139
+ cte_type -- Type of allowed content transfer encodings
140
+
141
+ 7bit -- ASCII only
142
+ 8bit -- Content-Transfer-Encoding: 8bit is allowed
143
+
144
+ Default: 8bit. Also controls the disposition of
145
+ (RFC invalid) binary data in headers; see the
146
+ documentation of the binary_fold method.
147
+
148
+ max_line_length -- maximum length of lines, excluding 'linesep',
149
+ during serialization. None or 0 means no line
150
+ wrapping is done. Default is 78.
151
+
152
+ mangle_from_ -- a flag that, when True escapes From_ lines in the
153
+ body of the message by putting a `>' in front of
154
+ them. This is used when the message is being
155
+ serialized by a generator. Default: True.
156
+
157
+ message_factory -- the class to use to create new message objects.
158
+ If the value is None, the default is Message.
159
+
160
+ """
161
+
162
+ raise_on_defect = False
163
+ linesep = '\n'
164
+ cte_type = '8bit'
165
+ max_line_length = 78
166
+ mangle_from_ = False
167
+ message_factory = None
168
+
169
+ def handle_defect(self, obj, defect):
170
+ """Based on policy, either raise defect or call register_defect.
171
+
172
+ handle_defect(obj, defect)
173
+
174
+ defect should be a Defect subclass, but in any case must be an
175
+ Exception subclass. obj is the object on which the defect should be
176
+ registered if it is not raised. If the raise_on_defect is True, the
177
+ defect is raised as an error, otherwise the object and the defect are
178
+ passed to register_defect.
179
+
180
+ This method is intended to be called by parsers that discover defects.
181
+ The email package parsers always call it with Defect instances.
182
+
183
+ """
184
+ if self.raise_on_defect:
185
+ raise defect
186
+ self.register_defect(obj, defect)
187
+
188
+ def register_defect(self, obj, defect):
189
+ """Record 'defect' on 'obj'.
190
+
191
+ Called by handle_defect if raise_on_defect is False. This method is
192
+ part of the Policy API so that Policy subclasses can implement custom
193
+ defect handling. The default implementation calls the append method of
194
+ the defects attribute of obj. The objects used by the email package by
195
+ default that get passed to this method will always have a defects
196
+ attribute with an append method.
197
+
198
+ """
199
+ obj.defects.append(defect)
200
+
201
+ def header_max_count(self, name):
202
+ """Return the maximum allowed number of headers named 'name'.
203
+
204
+ Called when a header is added to a Message object. If the returned
205
+ value is not 0 or None, and there are already a number of headers with
206
+ the name 'name' equal to the value returned, a ValueError is raised.
207
+
208
+ Because the default behavior of Message's __setitem__ is to append the
209
+ value to the list of headers, it is easy to create duplicate headers
210
+ without realizing it. This method allows certain headers to be limited
211
+ in the number of instances of that header that may be added to a
212
+ Message programmatically. (The limit is not observed by the parser,
213
+ which will faithfully produce as many headers as exist in the message
214
+ being parsed.)
215
+
216
+ The default implementation returns None for all header names.
217
+ """
218
+ return None
219
+
220
+ @abc.abstractmethod
221
+ def header_source_parse(self, sourcelines):
222
+ """Given a list of linesep terminated strings constituting the lines of
223
+ a single header, return the (name, value) tuple that should be stored
224
+ in the model. The input lines should retain their terminating linesep
225
+ characters. The lines passed in by the email package may contain
226
+ surrogateescaped binary data.
227
+ """
228
+ raise NotImplementedError
229
+
230
+ @abc.abstractmethod
231
+ def header_store_parse(self, name, value):
232
+ """Given the header name and the value provided by the application
233
+ program, return the (name, value) that should be stored in the model.
234
+ """
235
+ raise NotImplementedError
236
+
237
+ @abc.abstractmethod
238
+ def header_fetch_parse(self, name, value):
239
+ """Given the header name and the value from the model, return the value
240
+ to be returned to the application program that is requesting that
241
+ header. The value passed in by the email package may contain
242
+ surrogateescaped binary data if the lines were parsed by a BytesParser.
243
+ The returned value should not contain any surrogateescaped data.
244
+
245
+ """
246
+ raise NotImplementedError
247
+
248
+ @abc.abstractmethod
249
+ def fold(self, name, value):
250
+ """Given the header name and the value from the model, return a string
251
+ containing linesep characters that implement the folding of the header
252
+ according to the policy controls. The value passed in by the email
253
+ package may contain surrogateescaped binary data if the lines were
254
+ parsed by a BytesParser. The returned value should not contain any
255
+ surrogateescaped data.
256
+
257
+ """
258
+ raise NotImplementedError
259
+
260
+ @abc.abstractmethod
261
+ def fold_binary(self, name, value):
262
+ """Given the header name and the value from the model, return binary
263
+ data containing linesep characters that implement the folding of the
264
+ header according to the policy controls. The value passed in by the
265
+ email package may contain surrogateescaped binary data.
266
+
267
+ """
268
+ raise NotImplementedError
269
+
270
+
271
+ @_extend_docstrings
272
+ class Compat32(Policy):
273
+
274
+ """+
275
+ This particular policy is the backward compatibility Policy. It
276
+ replicates the behavior of the email package version 5.1.
277
+ """
278
+
279
+ mangle_from_ = True
280
+
281
+ def _sanitize_header(self, name, value):
282
+ # If the header value contains surrogates, return a Header using
283
+ # the unknown-8bit charset to encode the bytes as encoded words.
284
+ if not isinstance(value, str):
285
+ # Assume it is already a header object
286
+ return value
287
+ if _has_surrogates(value):
288
+ return header.Header(value, charset=_charset.UNKNOWN8BIT,
289
+ header_name=name)
290
+ else:
291
+ return value
292
+
293
+ def header_source_parse(self, sourcelines):
294
+ """+
295
+ The name is parsed as everything up to the ':' and returned unmodified.
296
+ The value is determined by stripping leading whitespace off the
297
+ remainder of the first line, joining all subsequent lines together, and
298
+ stripping any trailing carriage return or linefeed characters.
299
+
300
+ """
301
+ name, value = sourcelines[0].split(':', 1)
302
+ value = value.lstrip(' \t') + ''.join(sourcelines[1:])
303
+ return (name, value.rstrip('\r\n'))
304
+
305
+ def header_store_parse(self, name, value):
306
+ """+
307
+ The name and value are returned unmodified.
308
+ """
309
+ return (name, value)
310
+
311
+ def header_fetch_parse(self, name, value):
312
+ """+
313
+ If the value contains binary data, it is converted into a Header object
314
+ using the unknown-8bit charset. Otherwise it is returned unmodified.
315
+ """
316
+ return self._sanitize_header(name, value)
317
+
318
+ def fold(self, name, value):
319
+ """+
320
+ Headers are folded using the Header folding algorithm, which preserves
321
+ existing line breaks in the value, and wraps each resulting line to the
322
+ max_line_length. Non-ASCII binary data are CTE encoded using the
323
+ unknown-8bit charset.
324
+
325
+ """
326
+ return self._fold(name, value, sanitize=True)
327
+
328
+ def fold_binary(self, name, value):
329
+ """+
330
+ Headers are folded using the Header folding algorithm, which preserves
331
+ existing line breaks in the value, and wraps each resulting line to the
332
+ max_line_length. If cte_type is 7bit, non-ascii binary data is CTE
333
+ encoded using the unknown-8bit charset. Otherwise the original source
334
+ header is used, with its existing line breaks and/or binary data.
335
+
336
+ """
337
+ folded = self._fold(name, value, sanitize=self.cte_type=='7bit')
338
+ return folded.encode('ascii', 'surrogateescape')
339
+
340
+ def _fold(self, name, value, sanitize):
341
+ parts = []
342
+ parts.append('%s: ' % name)
343
+ if isinstance(value, str):
344
+ if _has_surrogates(value):
345
+ if sanitize:
346
+ h = header.Header(value,
347
+ charset=_charset.UNKNOWN8BIT,
348
+ header_name=name)
349
+ else:
350
+ # If we have raw 8bit data in a byte string, we have no idea
351
+ # what the encoding is. There is no safe way to split this
352
+ # string. If it's ascii-subset, then we could do a normal
353
+ # ascii split, but if it's multibyte then we could break the
354
+ # string. There's no way to know so the least harm seems to
355
+ # be to not split the string and risk it being too long.
356
+ parts.append(value)
357
+ h = None
358
+ else:
359
+ h = header.Header(value, header_name=name)
360
+ else:
361
+ # Assume it is a Header-like object.
362
+ h = value
363
+ if h is not None:
364
+ # The Header class interprets a value of None for maxlinelen as the
365
+ # default value of 78, as recommended by RFC 2822.
366
+ maxlinelen = 0
367
+ if self.max_line_length is not None:
368
+ maxlinelen = self.max_line_length
369
+ parts.append(h.encode(linesep=self.linesep, maxlinelen=maxlinelen))
370
+ parts.append(self.linesep)
371
+ return ''.join(parts)
372
+
373
+
374
+ compat32 = Compat32()
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/architecture.rst ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :mod:`email` Package Architecture
2
+ =================================
3
+
4
+ Overview
5
+ --------
6
+
7
+ The email package consists of three major components:
8
+
9
+ Model
10
+ An object structure that represents an email message, and provides an
11
+ API for creating, querying, and modifying a message.
12
+
13
+ Parser
14
+ Takes a sequence of characters or bytes and produces a model of the
15
+ email message represented by those characters or bytes.
16
+
17
+ Generator
18
+ Takes a model and turns it into a sequence of characters or bytes. The
19
+ sequence can either be intended for human consumption (a printable
20
+ unicode string) or bytes suitable for transmission over the wire. In
21
+ the latter case all data is properly encoded using the content transfer
22
+ encodings specified by the relevant RFCs.
23
+
24
+ Conceptually the package is organized around the model. The model provides both
25
+ "external" APIs intended for use by application programs using the library,
26
+ and "internal" APIs intended for use by the Parser and Generator components.
27
+ This division is intentionally a bit fuzzy; the API described by this
28
+ documentation is all a public, stable API. This allows for an application
29
+ with special needs to implement its own parser and/or generator.
30
+
31
+ In addition to the three major functional components, there is a third key
32
+ component to the architecture:
33
+
34
+ Policy
35
+ An object that specifies various behavioral settings and carries
36
+ implementations of various behavior-controlling methods.
37
+
38
+ The Policy framework provides a simple and convenient way to control the
39
+ behavior of the library, making it possible for the library to be used in a
40
+ very flexible fashion while leveraging the common code required to parse,
41
+ represent, and generate message-like objects. For example, in addition to the
42
+ default :rfc:`5322` email message policy, we also have a policy that manages
43
+ HTTP headers in a fashion compliant with :rfc:`2616`. Individual policy
44
+ controls, such as the maximum line length produced by the generator, can also
45
+ be controlled individually to meet specialized application requirements.
46
+
47
+
48
+ The Model
49
+ ---------
50
+
51
+ The message model is implemented by the :class:`~email.message.Message` class.
52
+ The model divides a message into the two fundamental parts discussed by the
53
+ RFC: the header section and the body. The `Message` object acts as a
54
+ pseudo-dictionary of named headers. Its dictionary interface provides
55
+ convenient access to individual headers by name. However, all headers are kept
56
+ internally in an ordered list, so that the information about the order of the
57
+ headers in the original message is preserved.
58
+
59
+ The `Message` object also has a `payload` that holds the body. A `payload` can
60
+ be one of two things: data, or a list of `Message` objects. The latter is used
61
+ to represent a multipart MIME message. Lists can be nested arbitrarily deeply
62
+ in order to represent the message, with all terminal leaves having non-list
63
+ data payloads.
64
+
65
+
66
+ Message Lifecycle
67
+ -----------------
68
+
69
+ The general lifecycle of a message is:
70
+
71
+ Creation
72
+ A `Message` object can be created by a Parser, or it can be
73
+ instantiated as an empty message by an application.
74
+
75
+ Manipulation
76
+ The application may examine one or more headers, and/or the
77
+ payload, and it may modify one or more headers and/or
78
+ the payload. This may be done on the top level `Message`
79
+ object, or on any sub-object.
80
+
81
+ Finalization
82
+ The Model is converted into a unicode or binary stream,
83
+ or the model is discarded.
84
+
85
+
86
+
87
+ Header Policy Control During Lifecycle
88
+ --------------------------------------
89
+
90
+ One of the major controls exerted by the Policy is the management of headers
91
+ during the `Message` lifecycle. Most applications don't need to be aware of
92
+ this.
93
+
94
+ A header enters the model in one of two ways: via a Parser, or by being set to
95
+ a specific value by an application program after the Model already exists.
96
+ Similarly, a header exits the model in one of two ways: by being serialized by
97
+ a Generator, or by being retrieved from a Model by an application program. The
98
+ Policy object provides hooks for all four of these pathways.
99
+
100
+ The model storage for headers is a list of (name, value) tuples.
101
+
102
+ The Parser identifies headers during parsing, and passes them to the
103
+ :meth:`~email.policy.Policy.header_source_parse` method of the Policy. The
104
+ result of that method is the (name, value) tuple to be stored in the model.
105
+
106
+ When an application program supplies a header value (for example, through the
107
+ `Message` object `__setitem__` interface), the name and the value are passed to
108
+ the :meth:`~email.policy.Policy.header_store_parse` method of the Policy, which
109
+ returns the (name, value) tuple to be stored in the model.
110
+
111
+ When an application program retrieves a header (through any of the dict or list
112
+ interfaces of `Message`), the name and value are passed to the
113
+ :meth:`~email.policy.Policy.header_fetch_parse` method of the Policy to
114
+ obtain the value returned to the application.
115
+
116
+ When a Generator requests a header during serialization, the name and value are
117
+ passed to the :meth:`~email.policy.Policy.fold` method of the Policy, which
118
+ returns a string containing line breaks in the appropriate places. The
119
+ :meth:`~email.policy.Policy.cte_type` Policy control determines whether or
120
+ not Content Transfer Encoding is performed on the data in the header. There is
121
+ also a :meth:`~email.policy.Policy.binary_fold` method for use by generators
122
+ that produce binary output, which returns the folded header as binary data,
123
+ possibly folded at different places than the corresponding string would be.
124
+
125
+
126
+ Handling Binary Data
127
+ --------------------
128
+
129
+ In an ideal world all message data would conform to the RFCs, meaning that the
130
+ parser could decode the message into the idealized unicode message that the
131
+ sender originally wrote. In the real world, the email package must also be
132
+ able to deal with badly formatted messages, including messages containing
133
+ non-ASCII characters that either have no indicated character set or are not
134
+ valid characters in the indicated character set.
135
+
136
+ Since email messages are *primarily* text data, and operations on message data
137
+ are primarily text operations (except for binary payloads of course), the model
138
+ stores all text data as unicode strings. Un-decodable binary inside text
139
+ data is handled by using the `surrogateescape` error handler of the ASCII
140
+ codec. As with the binary filenames the error handler was introduced to
141
+ handle, this allows the email package to "carry" the binary data received
142
+ during parsing along until the output stage, at which time it is regenerated
143
+ in its original form.
144
+
145
+ This carried binary data is almost entirely an implementation detail. The one
146
+ place where it is visible in the API is in the "internal" API. A Parser must
147
+ do the `surrogateescape` encoding of binary input data, and pass that data to
148
+ the appropriate Policy method. The "internal" interface used by the Generator
149
+ to access header values preserves the `surrogateescaped` bytes. All other
150
+ interfaces convert the binary data either back into bytes or into a safe form
151
+ (losing information in some cases).
152
+
153
+
154
+ Backward Compatibility
155
+ ----------------------
156
+
157
+ The :class:`~email.policy.Policy.Compat32` Policy provides backward
158
+ compatibility with version 5.1 of the email package. It does this via the
159
+ following implementation of the four+1 Policy methods described above:
160
+
161
+ header_source_parse
162
+ Splits the first line on the colon to obtain the name, discards any spaces
163
+ after the colon, and joins the remainder of the line with all of the
164
+ remaining lines, preserving the linesep characters to obtain the value.
165
+ Trailing carriage return and/or linefeed characters are stripped from the
166
+ resulting value string.
167
+
168
+ header_store_parse
169
+ Returns the name and value exactly as received from the application.
170
+
171
+ header_fetch_parse
172
+ If the value contains any `surrogateescaped` binary data, return the value
173
+ as a :class:`~email.header.Header` object, using the character set
174
+ `unknown-8bit`. Otherwise just returns the value.
175
+
176
+ fold
177
+ Uses :class:`~email.header.Header`'s folding to fold headers in the
178
+ same way the email5.1 generator did.
179
+
180
+ binary_fold
181
+ Same as fold, but encodes to 'ascii'.
182
+
183
+
184
+ New Algorithm
185
+ -------------
186
+
187
+ header_source_parse
188
+ Same as legacy behavior.
189
+
190
+ header_store_parse
191
+ Same as legacy behavior.
192
+
193
+ header_fetch_parse
194
+ If the value is already a header object, returns it. Otherwise, parses the
195
+ value using the new parser, and returns the resulting object as the value.
196
+ `surrogateescaped` bytes get turned into unicode unknown character code
197
+ points.
198
+
199
+ fold
200
+ Uses the new header folding algorithm, respecting the policy settings.
201
+ surrogateescaped bytes are encoded using the ``unknown-8bit`` charset for
202
+ ``cte_type=7bit`` or ``8bit``. Returns a string.
203
+
204
+ At some point there will also be a ``cte_type=unicode``, and for that
205
+ policy fold will serialize the idealized unicode message with RFC-like
206
+ folding, converting any surrogateescaped bytes into the unicode
207
+ unknown character glyph.
208
+
209
+ binary_fold
210
+ Uses the new header folding algorithm, respecting the policy settings.
211
+ surrogateescaped bytes are encoded using the `unknown-8bit` charset for
212
+ ``cte_type=7bit``, and get turned back into bytes for ``cte_type=8bit``.
213
+ Returns bytes.
214
+
215
+ At some point there will also be a ``cte_type=unicode``, and for that
216
+ policy binary_fold will serialize the message according to :rfc:``5335``.
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/base64mime.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2002-2007 Python Software Foundation
2
+ # Author: Ben Gertzfield
3
+ # Contact: email-sig@python.org
4
+
5
+ """Base64 content transfer encoding per RFCs 2045-2047.
6
+
7
+ This module handles the content transfer encoding method defined in RFC 2045
8
+ to encode arbitrary 8-bit data using the three 8-bit bytes in four 7-bit
9
+ characters encoding known as Base64.
10
+
11
+ It is used in the MIME standards for email to attach images, audio, and text
12
+ using some 8-bit character sets to messages.
13
+
14
+ This module provides an interface to encode and decode both headers and bodies
15
+ with Base64 encoding.
16
+
17
+ RFC 2045 defines a method for including character set information in an
18
+ `encoded-word' in a header. This method is commonly used for 8-bit real names
19
+ in To:, From:, Cc:, etc. fields, as well as Subject: lines.
20
+
21
+ This module does not do the line wrapping or end-of-line character conversion
22
+ necessary for proper internationalized headers; it only does dumb encoding and
23
+ decoding. To deal with the various line wrapping issues, use the email.header
24
+ module.
25
+ """
26
+
27
+ __all__ = [
28
+ 'body_decode',
29
+ 'body_encode',
30
+ 'decode',
31
+ 'decodestring',
32
+ 'header_encode',
33
+ 'header_length',
34
+ ]
35
+
36
+
37
+ from base64 import b64encode
38
+ from binascii import b2a_base64, a2b_base64
39
+
40
+ CRLF = '\r\n'
41
+ NL = '\n'
42
+ EMPTYSTRING = ''
43
+
44
+ # See also Charset.py
45
+ MISC_LEN = 7
46
+
47
+
48
+
49
+ # Helpers
50
+ def header_length(bytearray):
51
+ """Return the length of s when it is encoded with base64."""
52
+ groups_of_3, leftover = divmod(len(bytearray), 3)
53
+ # 4 bytes out for each 3 bytes (or nonzero fraction thereof) in.
54
+ n = groups_of_3 * 4
55
+ if leftover:
56
+ n += 4
57
+ return n
58
+
59
+
60
+
61
+ def header_encode(header_bytes, charset='iso-8859-1'):
62
+ """Encode a single header line with Base64 encoding in a given charset.
63
+
64
+ charset names the character set to use to encode the header. It defaults
65
+ to iso-8859-1. Base64 encoding is defined in RFC 2045.
66
+ """
67
+ if not header_bytes:
68
+ return ""
69
+ if isinstance(header_bytes, str):
70
+ header_bytes = header_bytes.encode(charset)
71
+ encoded = b64encode(header_bytes).decode("ascii")
72
+ return '=?%s?b?%s?=' % (charset, encoded)
73
+
74
+
75
+
76
+ def body_encode(s, maxlinelen=76, eol=NL):
77
+ r"""Encode a string with base64.
78
+
79
+ Each line will be wrapped at, at most, maxlinelen characters (defaults to
80
+ 76 characters).
81
+
82
+ Each line of encoded text will end with eol, which defaults to "\n". Set
83
+ this to "\r\n" if you will be using the result of this function directly
84
+ in an email.
85
+ """
86
+ if not s:
87
+ return s
88
+
89
+ encvec = []
90
+ max_unencoded = maxlinelen * 3 // 4
91
+ for i in range(0, len(s), max_unencoded):
92
+ # BAW: should encode() inherit b2a_base64()'s dubious behavior in
93
+ # adding a newline to the encoded string?
94
+ enc = b2a_base64(s[i:i + max_unencoded]).decode("ascii")
95
+ if enc.endswith(NL) and eol != NL:
96
+ enc = enc[:-1] + eol
97
+ encvec.append(enc)
98
+ return EMPTYSTRING.join(encvec)
99
+
100
+
101
+
102
+ def decode(string):
103
+ """Decode a raw base64 string, returning a bytes object.
104
+
105
+ This function does not parse a full MIME header value encoded with
106
+ base64 (like =?iso-8859-1?b?bmloISBuaWgh?=) -- please use the high
107
+ level email.header class for that functionality.
108
+ """
109
+ if not string:
110
+ return bytes()
111
+ elif isinstance(string, str):
112
+ return a2b_base64(string.encode('raw-unicode-escape'))
113
+ else:
114
+ return a2b_base64(string)
115
+
116
+
117
+ # For convenience and backwards compatibility w/ standard base64 module
118
+ body_decode = decode
119
+ decodestring = decode
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/charset.py ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2007 Python Software Foundation
2
+ # Author: Ben Gertzfield, Barry Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ __all__ = [
6
+ 'Charset',
7
+ 'add_alias',
8
+ 'add_charset',
9
+ 'add_codec',
10
+ ]
11
+
12
+ from functools import partial
13
+
14
+ import email.base64mime
15
+ import email.quoprimime
16
+
17
+ from email import errors
18
+ from email.encoders import encode_7or8bit
19
+
20
+
21
+
22
+ # Flags for types of header encodings
23
+ QP = 1 # Quoted-Printable
24
+ BASE64 = 2 # Base64
25
+ SHORTEST = 3 # the shorter of QP and base64, but only for headers
26
+
27
+ # In "=?charset?q?hello_world?=", the =?, ?q?, and ?= add up to 7
28
+ RFC2047_CHROME_LEN = 7
29
+
30
+ DEFAULT_CHARSET = 'us-ascii'
31
+ UNKNOWN8BIT = 'unknown-8bit'
32
+ EMPTYSTRING = ''
33
+
34
+
35
+
36
+ # Defaults
37
+ CHARSETS = {
38
+ # input header enc body enc output conv
39
+ 'iso-8859-1': (QP, QP, None),
40
+ 'iso-8859-2': (QP, QP, None),
41
+ 'iso-8859-3': (QP, QP, None),
42
+ 'iso-8859-4': (QP, QP, None),
43
+ # iso-8859-5 is Cyrillic, and not especially used
44
+ # iso-8859-6 is Arabic, also not particularly used
45
+ # iso-8859-7 is Greek, QP will not make it readable
46
+ # iso-8859-8 is Hebrew, QP will not make it readable
47
+ 'iso-8859-9': (QP, QP, None),
48
+ 'iso-8859-10': (QP, QP, None),
49
+ # iso-8859-11 is Thai, QP will not make it readable
50
+ 'iso-8859-13': (QP, QP, None),
51
+ 'iso-8859-14': (QP, QP, None),
52
+ 'iso-8859-15': (QP, QP, None),
53
+ 'iso-8859-16': (QP, QP, None),
54
+ 'windows-1252':(QP, QP, None),
55
+ 'viscii': (QP, QP, None),
56
+ 'us-ascii': (None, None, None),
57
+ 'big5': (BASE64, BASE64, None),
58
+ 'gb2312': (BASE64, BASE64, None),
59
+ 'euc-jp': (BASE64, None, 'iso-2022-jp'),
60
+ 'shift_jis': (BASE64, None, 'iso-2022-jp'),
61
+ 'iso-2022-jp': (BASE64, None, None),
62
+ 'koi8-r': (BASE64, BASE64, None),
63
+ 'utf-8': (SHORTEST, BASE64, 'utf-8'),
64
+ }
65
+
66
+ # Aliases for other commonly-used names for character sets. Map
67
+ # them to the real ones used in email.
68
+ ALIASES = {
69
+ 'latin_1': 'iso-8859-1',
70
+ 'latin-1': 'iso-8859-1',
71
+ 'latin_2': 'iso-8859-2',
72
+ 'latin-2': 'iso-8859-2',
73
+ 'latin_3': 'iso-8859-3',
74
+ 'latin-3': 'iso-8859-3',
75
+ 'latin_4': 'iso-8859-4',
76
+ 'latin-4': 'iso-8859-4',
77
+ 'latin_5': 'iso-8859-9',
78
+ 'latin-5': 'iso-8859-9',
79
+ 'latin_6': 'iso-8859-10',
80
+ 'latin-6': 'iso-8859-10',
81
+ 'latin_7': 'iso-8859-13',
82
+ 'latin-7': 'iso-8859-13',
83
+ 'latin_8': 'iso-8859-14',
84
+ 'latin-8': 'iso-8859-14',
85
+ 'latin_9': 'iso-8859-15',
86
+ 'latin-9': 'iso-8859-15',
87
+ 'latin_10':'iso-8859-16',
88
+ 'latin-10':'iso-8859-16',
89
+ 'cp949': 'ks_c_5601-1987',
90
+ 'euc_jp': 'euc-jp',
91
+ 'euc_kr': 'euc-kr',
92
+ 'ascii': 'us-ascii',
93
+ }
94
+
95
+
96
+ # Map charsets to their Unicode codec strings.
97
+ CODEC_MAP = {
98
+ 'gb2312': 'eucgb2312_cn',
99
+ 'big5': 'big5_tw',
100
+ # Hack: We don't want *any* conversion for stuff marked us-ascii, as all
101
+ # sorts of garbage might be sent to us in the guise of 7-bit us-ascii.
102
+ # Let that stuff pass through without conversion to/from Unicode.
103
+ 'us-ascii': None,
104
+ }
105
+
106
+
107
+
108
+ # Convenience functions for extending the above mappings
109
+ def add_charset(charset, header_enc=None, body_enc=None, output_charset=None):
110
+ """Add character set properties to the global registry.
111
+
112
+ charset is the input character set, and must be the canonical name of a
113
+ character set.
114
+
115
+ Optional header_enc and body_enc is either Charset.QP for
116
+ quoted-printable, Charset.BASE64 for base64 encoding, Charset.SHORTEST for
117
+ the shortest of qp or base64 encoding, or None for no encoding. SHORTEST
118
+ is only valid for header_enc. It describes how message headers and
119
+ message bodies in the input charset are to be encoded. Default is no
120
+ encoding.
121
+
122
+ Optional output_charset is the character set that the output should be
123
+ in. Conversions will proceed from input charset, to Unicode, to the
124
+ output charset when the method Charset.convert() is called. The default
125
+ is to output in the same character set as the input.
126
+
127
+ Both input_charset and output_charset must have Unicode codec entries in
128
+ the module's charset-to-codec mapping; use add_codec(charset, codecname)
129
+ to add codecs the module does not know about. See the codecs module's
130
+ documentation for more information.
131
+ """
132
+ if body_enc == SHORTEST:
133
+ raise ValueError('SHORTEST not allowed for body_enc')
134
+ CHARSETS[charset] = (header_enc, body_enc, output_charset)
135
+
136
+
137
+ def add_alias(alias, canonical):
138
+ """Add a character set alias.
139
+
140
+ alias is the alias name, e.g. latin-1
141
+ canonical is the character set's canonical name, e.g. iso-8859-1
142
+ """
143
+ ALIASES[alias] = canonical
144
+
145
+
146
+ def add_codec(charset, codecname):
147
+ """Add a codec that map characters in the given charset to/from Unicode.
148
+
149
+ charset is the canonical name of a character set. codecname is the name
150
+ of a Python codec, as appropriate for the second argument to the unicode()
151
+ built-in, or to the encode() method of a Unicode string.
152
+ """
153
+ CODEC_MAP[charset] = codecname
154
+
155
+
156
+
157
+ # Convenience function for encoding strings, taking into account
158
+ # that they might be unknown-8bit (ie: have surrogate-escaped bytes)
159
+ def _encode(string, codec):
160
+ if codec == UNKNOWN8BIT:
161
+ return string.encode('ascii', 'surrogateescape')
162
+ else:
163
+ return string.encode(codec)
164
+
165
+
166
+
167
+ class Charset:
168
+ """Map character sets to their email properties.
169
+
170
+ This class provides information about the requirements imposed on email
171
+ for a specific character set. It also provides convenience routines for
172
+ converting between character sets, given the availability of the
173
+ applicable codecs. Given a character set, it will do its best to provide
174
+ information on how to use that character set in an email in an
175
+ RFC-compliant way.
176
+
177
+ Certain character sets must be encoded with quoted-printable or base64
178
+ when used in email headers or bodies. Certain character sets must be
179
+ converted outright, and are not allowed in email. Instances of this
180
+ module expose the following information about a character set:
181
+
182
+ input_charset: The initial character set specified. Common aliases
183
+ are converted to their `official' email names (e.g. latin_1
184
+ is converted to iso-8859-1). Defaults to 7-bit us-ascii.
185
+
186
+ header_encoding: If the character set must be encoded before it can be
187
+ used in an email header, this attribute will be set to
188
+ Charset.QP (for quoted-printable), Charset.BASE64 (for
189
+ base64 encoding), or Charset.SHORTEST for the shortest of
190
+ QP or BASE64 encoding. Otherwise, it will be None.
191
+
192
+ body_encoding: Same as header_encoding, but describes the encoding for the
193
+ mail message's body, which indeed may be different than the
194
+ header encoding. Charset.SHORTEST is not allowed for
195
+ body_encoding.
196
+
197
+ output_charset: Some character sets must be converted before they can be
198
+ used in email headers or bodies. If the input_charset is
199
+ one of them, this attribute will contain the name of the
200
+ charset output will be converted to. Otherwise, it will
201
+ be None.
202
+
203
+ input_codec: The name of the Python codec used to convert the
204
+ input_charset to Unicode. If no conversion codec is
205
+ necessary, this attribute will be None.
206
+
207
+ output_codec: The name of the Python codec used to convert Unicode
208
+ to the output_charset. If no conversion codec is necessary,
209
+ this attribute will have the same value as the input_codec.
210
+ """
211
+ def __init__(self, input_charset=DEFAULT_CHARSET):
212
+ # RFC 2046, $4.1.2 says charsets are not case sensitive. We coerce to
213
+ # unicode because its .lower() is locale insensitive. If the argument
214
+ # is already a unicode, we leave it at that, but ensure that the
215
+ # charset is ASCII, as the standard (RFC XXX) requires.
216
+ try:
217
+ if isinstance(input_charset, str):
218
+ input_charset.encode('ascii')
219
+ else:
220
+ input_charset = str(input_charset, 'ascii')
221
+ except UnicodeError:
222
+ raise errors.CharsetError(input_charset)
223
+ input_charset = input_charset.lower()
224
+ # Set the input charset after filtering through the aliases
225
+ self.input_charset = ALIASES.get(input_charset, input_charset)
226
+ # We can try to guess which encoding and conversion to use by the
227
+ # charset_map dictionary. Try that first, but let the user override
228
+ # it.
229
+ henc, benc, conv = CHARSETS.get(self.input_charset,
230
+ (SHORTEST, BASE64, None))
231
+ if not conv:
232
+ conv = self.input_charset
233
+ # Set the attributes, allowing the arguments to override the default.
234
+ self.header_encoding = henc
235
+ self.body_encoding = benc
236
+ self.output_charset = ALIASES.get(conv, conv)
237
+ # Now set the codecs. If one isn't defined for input_charset,
238
+ # guess and try a Unicode codec with the same name as input_codec.
239
+ self.input_codec = CODEC_MAP.get(self.input_charset,
240
+ self.input_charset)
241
+ self.output_codec = CODEC_MAP.get(self.output_charset,
242
+ self.output_charset)
243
+
244
+ def __repr__(self):
245
+ return self.input_charset.lower()
246
+
247
+ def __eq__(self, other):
248
+ return str(self) == str(other).lower()
249
+
250
+ def get_body_encoding(self):
251
+ """Return the content-transfer-encoding used for body encoding.
252
+
253
+ This is either the string `quoted-printable' or `base64' depending on
254
+ the encoding used, or it is a function in which case you should call
255
+ the function with a single argument, the Message object being
256
+ encoded. The function should then set the Content-Transfer-Encoding
257
+ header itself to whatever is appropriate.
258
+
259
+ Returns "quoted-printable" if self.body_encoding is QP.
260
+ Returns "base64" if self.body_encoding is BASE64.
261
+ Returns conversion function otherwise.
262
+ """
263
+ assert self.body_encoding != SHORTEST
264
+ if self.body_encoding == QP:
265
+ return 'quoted-printable'
266
+ elif self.body_encoding == BASE64:
267
+ return 'base64'
268
+ else:
269
+ return encode_7or8bit
270
+
271
+ def get_output_charset(self):
272
+ """Return the output character set.
273
+
274
+ This is self.output_charset if that is not None, otherwise it is
275
+ self.input_charset.
276
+ """
277
+ return self.output_charset or self.input_charset
278
+
279
+ def header_encode(self, string):
280
+ """Header-encode a string by converting it first to bytes.
281
+
282
+ The type of encoding (base64 or quoted-printable) will be based on
283
+ this charset's `header_encoding`.
284
+
285
+ :param string: A unicode string for the header. It must be possible
286
+ to encode this string to bytes using the character set's
287
+ output codec.
288
+ :return: The encoded string, with RFC 2047 chrome.
289
+ """
290
+ codec = self.output_codec or 'us-ascii'
291
+ header_bytes = _encode(string, codec)
292
+ # 7bit/8bit encodings return the string unchanged (modulo conversions)
293
+ encoder_module = self._get_encoder(header_bytes)
294
+ if encoder_module is None:
295
+ return string
296
+ return encoder_module.header_encode(header_bytes, codec)
297
+
298
+ def header_encode_lines(self, string, maxlengths):
299
+ """Header-encode a string by converting it first to bytes.
300
+
301
+ This is similar to `header_encode()` except that the string is fit
302
+ into maximum line lengths as given by the argument.
303
+
304
+ :param string: A unicode string for the header. It must be possible
305
+ to encode this string to bytes using the character set's
306
+ output codec.
307
+ :param maxlengths: Maximum line length iterator. Each element
308
+ returned from this iterator will provide the next maximum line
309
+ length. This parameter is used as an argument to built-in next()
310
+ and should never be exhausted. The maximum line lengths should
311
+ not count the RFC 2047 chrome. These line lengths are only a
312
+ hint; the splitter does the best it can.
313
+ :return: Lines of encoded strings, each with RFC 2047 chrome.
314
+ """
315
+ # See which encoding we should use.
316
+ codec = self.output_codec or 'us-ascii'
317
+ header_bytes = _encode(string, codec)
318
+ encoder_module = self._get_encoder(header_bytes)
319
+ encoder = partial(encoder_module.header_encode, charset=codec)
320
+ # Calculate the number of characters that the RFC 2047 chrome will
321
+ # contribute to each line.
322
+ charset = self.get_output_charset()
323
+ extra = len(charset) + RFC2047_CHROME_LEN
324
+ # Now comes the hard part. We must encode bytes but we can't split on
325
+ # bytes because some character sets are variable length and each
326
+ # encoded word must stand on its own. So the problem is you have to
327
+ # encode to bytes to figure out this word's length, but you must split
328
+ # on characters. This causes two problems: first, we don't know how
329
+ # many octets a specific substring of unicode characters will get
330
+ # encoded to, and second, we don't know how many ASCII characters
331
+ # those octets will get encoded to. Unless we try it. Which seems
332
+ # inefficient. In the interest of being correct rather than fast (and
333
+ # in the hope that there will be few encoded headers in any such
334
+ # message), brute force it. :(
335
+ lines = []
336
+ current_line = []
337
+ maxlen = next(maxlengths) - extra
338
+ for character in string:
339
+ current_line.append(character)
340
+ this_line = EMPTYSTRING.join(current_line)
341
+ length = encoder_module.header_length(_encode(this_line, charset))
342
+ if length > maxlen:
343
+ # This last character doesn't fit so pop it off.
344
+ current_line.pop()
345
+ # Does nothing fit on the first line?
346
+ if not lines and not current_line:
347
+ lines.append(None)
348
+ else:
349
+ separator = (' ' if lines else '')
350
+ joined_line = EMPTYSTRING.join(current_line)
351
+ header_bytes = _encode(joined_line, codec)
352
+ lines.append(encoder(header_bytes))
353
+ current_line = [character]
354
+ maxlen = next(maxlengths) - extra
355
+ joined_line = EMPTYSTRING.join(current_line)
356
+ header_bytes = _encode(joined_line, codec)
357
+ lines.append(encoder(header_bytes))
358
+ return lines
359
+
360
+ def _get_encoder(self, header_bytes):
361
+ if self.header_encoding == BASE64:
362
+ return email.base64mime
363
+ elif self.header_encoding == QP:
364
+ return email.quoprimime
365
+ elif self.header_encoding == SHORTEST:
366
+ len64 = email.base64mime.header_length(header_bytes)
367
+ lenqp = email.quoprimime.header_length(header_bytes)
368
+ if len64 < lenqp:
369
+ return email.base64mime
370
+ else:
371
+ return email.quoprimime
372
+ else:
373
+ return None
374
+
375
+ def body_encode(self, string):
376
+ """Body-encode a string by converting it first to bytes.
377
+
378
+ The type of encoding (base64 or quoted-printable) will be based on
379
+ self.body_encoding. If body_encoding is None, we assume the
380
+ output charset is a 7bit encoding, so re-encoding the decoded
381
+ string using the ascii codec produces the correct string version
382
+ of the content.
383
+ """
384
+ if not string:
385
+ return string
386
+ if self.body_encoding is BASE64:
387
+ if isinstance(string, str):
388
+ string = string.encode(self.output_charset)
389
+ return email.base64mime.body_encode(string)
390
+ elif self.body_encoding is QP:
391
+ # quopromime.body_encode takes a string, but operates on it as if
392
+ # it were a list of byte codes. For a (minimal) history on why
393
+ # this is so, see changeset 0cf700464177. To correctly encode a
394
+ # character set, then, we must turn it into pseudo bytes via the
395
+ # latin1 charset, which will encode any byte as a single code point
396
+ # between 0 and 255, which is what body_encode is expecting.
397
+ if isinstance(string, str):
398
+ string = string.encode(self.output_charset)
399
+ string = string.decode('latin1')
400
+ return email.quoprimime.body_encode(string)
401
+ else:
402
+ if isinstance(string, str):
403
+ string = string.encode(self.output_charset).decode('ascii')
404
+ return string
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/contentmanager.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import binascii
2
+ import email.charset
3
+ import email.message
4
+ import email.errors
5
+ from email import quoprimime
6
+
7
+ class ContentManager:
8
+
9
+ def __init__(self):
10
+ self.get_handlers = {}
11
+ self.set_handlers = {}
12
+
13
+ def add_get_handler(self, key, handler):
14
+ self.get_handlers[key] = handler
15
+
16
+ def get_content(self, msg, *args, **kw):
17
+ content_type = msg.get_content_type()
18
+ if content_type in self.get_handlers:
19
+ return self.get_handlers[content_type](msg, *args, **kw)
20
+ maintype = msg.get_content_maintype()
21
+ if maintype in self.get_handlers:
22
+ return self.get_handlers[maintype](msg, *args, **kw)
23
+ if '' in self.get_handlers:
24
+ return self.get_handlers[''](msg, *args, **kw)
25
+ raise KeyError(content_type)
26
+
27
+ def add_set_handler(self, typekey, handler):
28
+ self.set_handlers[typekey] = handler
29
+
30
+ def set_content(self, msg, obj, *args, **kw):
31
+ if msg.get_content_maintype() == 'multipart':
32
+ # XXX: is this error a good idea or not? We can remove it later,
33
+ # but we can't add it later, so do it for now.
34
+ raise TypeError("set_content not valid on multipart")
35
+ handler = self._find_set_handler(msg, obj)
36
+ msg.clear_content()
37
+ handler(msg, obj, *args, **kw)
38
+
39
+ def _find_set_handler(self, msg, obj):
40
+ full_path_for_error = None
41
+ for typ in type(obj).__mro__:
42
+ if typ in self.set_handlers:
43
+ return self.set_handlers[typ]
44
+ qname = typ.__qualname__
45
+ modname = getattr(typ, '__module__', '')
46
+ full_path = '.'.join((modname, qname)) if modname else qname
47
+ if full_path_for_error is None:
48
+ full_path_for_error = full_path
49
+ if full_path in self.set_handlers:
50
+ return self.set_handlers[full_path]
51
+ if qname in self.set_handlers:
52
+ return self.set_handlers[qname]
53
+ name = typ.__name__
54
+ if name in self.set_handlers:
55
+ return self.set_handlers[name]
56
+ if None in self.set_handlers:
57
+ return self.set_handlers[None]
58
+ raise KeyError(full_path_for_error)
59
+
60
+
61
+ raw_data_manager = ContentManager()
62
+
63
+
64
+ def get_text_content(msg, errors='replace'):
65
+ content = msg.get_payload(decode=True)
66
+ charset = msg.get_param('charset', 'ASCII')
67
+ return content.decode(charset, errors=errors)
68
+ raw_data_manager.add_get_handler('text', get_text_content)
69
+
70
+
71
+ def get_non_text_content(msg):
72
+ return msg.get_payload(decode=True)
73
+ for maintype in 'audio image video application'.split():
74
+ raw_data_manager.add_get_handler(maintype, get_non_text_content)
75
+
76
+
77
+ def get_message_content(msg):
78
+ return msg.get_payload(0)
79
+ for subtype in 'rfc822 external-body'.split():
80
+ raw_data_manager.add_get_handler('message/'+subtype, get_message_content)
81
+
82
+
83
+ def get_and_fixup_unknown_message_content(msg):
84
+ # If we don't understand a message subtype, we are supposed to treat it as
85
+ # if it were application/octet-stream, per
86
+ # tools.ietf.org/html/rfc2046#section-5.2.4. Feedparser doesn't do that,
87
+ # so do our best to fix things up. Note that it is *not* appropriate to
88
+ # model message/partial content as Message objects, so they are handled
89
+ # here as well. (How to reassemble them is out of scope for this comment :)
90
+ return bytes(msg.get_payload(0))
91
+ raw_data_manager.add_get_handler('message',
92
+ get_and_fixup_unknown_message_content)
93
+
94
+
95
+ def _prepare_set(msg, maintype, subtype, headers):
96
+ msg['Content-Type'] = '/'.join((maintype, subtype))
97
+ if headers:
98
+ if not hasattr(headers[0], 'name'):
99
+ mp = msg.policy
100
+ headers = [mp.header_factory(*mp.header_source_parse([header]))
101
+ for header in headers]
102
+ try:
103
+ for header in headers:
104
+ if header.defects:
105
+ raise header.defects[0]
106
+ msg[header.name] = header
107
+ except email.errors.HeaderDefect as exc:
108
+ raise ValueError("Invalid header: {}".format(
109
+ header.fold(policy=msg.policy))) from exc
110
+
111
+
112
+ def _finalize_set(msg, disposition, filename, cid, params):
113
+ if disposition is None and filename is not None:
114
+ disposition = 'attachment'
115
+ if disposition is not None:
116
+ msg['Content-Disposition'] = disposition
117
+ if filename is not None:
118
+ msg.set_param('filename',
119
+ filename,
120
+ header='Content-Disposition',
121
+ replace=True)
122
+ if cid is not None:
123
+ msg['Content-ID'] = cid
124
+ if params is not None:
125
+ for key, value in params.items():
126
+ msg.set_param(key, value)
127
+
128
+
129
+ # XXX: This is a cleaned-up version of base64mime.body_encode (including a bug
130
+ # fix in the calculation of unencoded_bytes_per_line). It would be nice to
131
+ # drop both this and quoprimime.body_encode in favor of enhanced binascii
132
+ # routines that accepted a max_line_length parameter.
133
+ def _encode_base64(data, max_line_length):
134
+ encoded_lines = []
135
+ unencoded_bytes_per_line = max_line_length // 4 * 3
136
+ for i in range(0, len(data), unencoded_bytes_per_line):
137
+ thisline = data[i:i+unencoded_bytes_per_line]
138
+ encoded_lines.append(binascii.b2a_base64(thisline).decode('ascii'))
139
+ return ''.join(encoded_lines)
140
+
141
+
142
+ def _encode_text(string, charset, cte, policy):
143
+ lines = string.encode(charset).splitlines()
144
+ linesep = policy.linesep.encode('ascii')
145
+ def embedded_body(lines): return linesep.join(lines) + linesep
146
+ def normal_body(lines): return b'\n'.join(lines) + b'\n'
147
+ if cte==None:
148
+ # Use heuristics to decide on the "best" encoding.
149
+ if max((len(x) for x in lines), default=0) <= policy.max_line_length:
150
+ try:
151
+ return '7bit', normal_body(lines).decode('ascii')
152
+ except UnicodeDecodeError:
153
+ pass
154
+ if policy.cte_type == '8bit':
155
+ return '8bit', normal_body(lines).decode('ascii', 'surrogateescape')
156
+ sniff = embedded_body(lines[:10])
157
+ sniff_qp = quoprimime.body_encode(sniff.decode('latin-1'),
158
+ policy.max_line_length)
159
+ sniff_base64 = binascii.b2a_base64(sniff)
160
+ # This is a little unfair to qp; it includes lineseps, base64 doesn't.
161
+ if len(sniff_qp) > len(sniff_base64):
162
+ cte = 'base64'
163
+ else:
164
+ cte = 'quoted-printable'
165
+ if len(lines) <= 10:
166
+ return cte, sniff_qp
167
+ if cte == '7bit':
168
+ data = normal_body(lines).decode('ascii')
169
+ elif cte == '8bit':
170
+ data = normal_body(lines).decode('ascii', 'surrogateescape')
171
+ elif cte == 'quoted-printable':
172
+ data = quoprimime.body_encode(normal_body(lines).decode('latin-1'),
173
+ policy.max_line_length)
174
+ elif cte == 'base64':
175
+ data = _encode_base64(embedded_body(lines), policy.max_line_length)
176
+ else:
177
+ raise ValueError("Unknown content transfer encoding {}".format(cte))
178
+ return cte, data
179
+
180
+
181
+ def set_text_content(msg, string, subtype="plain", charset='utf-8', cte=None,
182
+ disposition=None, filename=None, cid=None,
183
+ params=None, headers=None):
184
+ _prepare_set(msg, 'text', subtype, headers)
185
+ cte, payload = _encode_text(string, charset, cte, msg.policy)
186
+ msg.set_payload(payload)
187
+ msg.set_param('charset',
188
+ email.charset.ALIASES.get(charset, charset),
189
+ replace=True)
190
+ msg['Content-Transfer-Encoding'] = cte
191
+ _finalize_set(msg, disposition, filename, cid, params)
192
+ raw_data_manager.add_set_handler(str, set_text_content)
193
+
194
+
195
+ def set_message_content(msg, message, subtype="rfc822", cte=None,
196
+ disposition=None, filename=None, cid=None,
197
+ params=None, headers=None):
198
+ if subtype == 'partial':
199
+ raise ValueError("message/partial is not supported for Message objects")
200
+ if subtype == 'rfc822':
201
+ if cte not in (None, '7bit', '8bit', 'binary'):
202
+ # http://tools.ietf.org/html/rfc2046#section-5.2.1 mandate.
203
+ raise ValueError(
204
+ "message/rfc822 parts do not support cte={}".format(cte))
205
+ # 8bit will get coerced on serialization if policy.cte_type='7bit'. We
206
+ # may end up claiming 8bit when it isn't needed, but the only negative
207
+ # result of that should be a gateway that needs to coerce to 7bit
208
+ # having to look through the whole embedded message to discover whether
209
+ # or not it actually has to do anything.
210
+ cte = '8bit' if cte is None else cte
211
+ elif subtype == 'external-body':
212
+ if cte not in (None, '7bit'):
213
+ # http://tools.ietf.org/html/rfc2046#section-5.2.3 mandate.
214
+ raise ValueError(
215
+ "message/external-body parts do not support cte={}".format(cte))
216
+ cte = '7bit'
217
+ elif cte is None:
218
+ # http://tools.ietf.org/html/rfc2046#section-5.2.4 says all future
219
+ # subtypes should be restricted to 7bit, so assume that.
220
+ cte = '7bit'
221
+ _prepare_set(msg, 'message', subtype, headers)
222
+ msg.set_payload([message])
223
+ msg['Content-Transfer-Encoding'] = cte
224
+ _finalize_set(msg, disposition, filename, cid, params)
225
+ raw_data_manager.add_set_handler(email.message.Message, set_message_content)
226
+
227
+
228
+ def set_bytes_content(msg, data, maintype, subtype, cte='base64',
229
+ disposition=None, filename=None, cid=None,
230
+ params=None, headers=None):
231
+ _prepare_set(msg, maintype, subtype, headers)
232
+ if cte == 'base64':
233
+ data = _encode_base64(data, max_line_length=msg.policy.max_line_length)
234
+ elif cte == 'quoted-printable':
235
+ # XXX: quoprimime.body_encode won't encode newline characters in data,
236
+ # so we can't use it. This means max_line_length is ignored. Another
237
+ # bug to fix later. (Note: encoders.quopri is broken on line ends.)
238
+ data = binascii.b2a_qp(data, istext=False, header=False, quotetabs=True)
239
+ data = data.decode('ascii')
240
+ elif cte == '7bit':
241
+ # Make sure it really is only ASCII. The early warning here seems
242
+ # worth the overhead...if you care write your own content manager :).
243
+ data.encode('ascii')
244
+ elif cte in ('8bit', 'binary'):
245
+ data = data.decode('ascii', 'surrogateescape')
246
+ msg.set_payload(data)
247
+ msg['Content-Transfer-Encoding'] = cte
248
+ _finalize_set(msg, disposition, filename, cid, params)
249
+ for typ in (bytes, bytearray, memoryview):
250
+ raw_data_manager.add_set_handler(typ, set_bytes_content)
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/encoders.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2006 Python Software Foundation
2
+ # Author: Barry Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ """Encodings and related functions."""
6
+
7
+ __all__ = [
8
+ 'encode_7or8bit',
9
+ 'encode_base64',
10
+ 'encode_noop',
11
+ 'encode_quopri',
12
+ ]
13
+
14
+
15
+ from base64 import encodebytes as _bencode
16
+ from quopri import encodestring as _encodestring
17
+
18
+
19
+
20
+ def _qencode(s):
21
+ enc = _encodestring(s, quotetabs=True)
22
+ # Must encode spaces, which quopri.encodestring() doesn't do
23
+ return enc.replace(b' ', b'=20')
24
+
25
+
26
+ def encode_base64(msg):
27
+ """Encode the message's payload in Base64.
28
+
29
+ Also, add an appropriate Content-Transfer-Encoding header.
30
+ """
31
+ orig = msg.get_payload(decode=True)
32
+ encdata = str(_bencode(orig), 'ascii')
33
+ msg.set_payload(encdata)
34
+ msg['Content-Transfer-Encoding'] = 'base64'
35
+
36
+
37
+
38
+ def encode_quopri(msg):
39
+ """Encode the message's payload in quoted-printable.
40
+
41
+ Also, add an appropriate Content-Transfer-Encoding header.
42
+ """
43
+ orig = msg.get_payload(decode=True)
44
+ encdata = _qencode(orig)
45
+ msg.set_payload(encdata)
46
+ msg['Content-Transfer-Encoding'] = 'quoted-printable'
47
+
48
+
49
+
50
+ def encode_7or8bit(msg):
51
+ """Set the Content-Transfer-Encoding header to 7bit or 8bit."""
52
+ orig = msg.get_payload(decode=True)
53
+ if orig is None:
54
+ # There's no payload. For backwards compatibility we use 7bit
55
+ msg['Content-Transfer-Encoding'] = '7bit'
56
+ return
57
+ # We play a trick to make this go fast. If decoding from ASCII succeeds,
58
+ # we know the data must be 7bit, otherwise treat it as 8bit.
59
+ try:
60
+ orig.decode('ascii')
61
+ except UnicodeError:
62
+ msg['Content-Transfer-Encoding'] = '8bit'
63
+ else:
64
+ msg['Content-Transfer-Encoding'] = '7bit'
65
+
66
+
67
+
68
+ def encode_noop(msg):
69
+ """Do nothing."""
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/errors.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2006 Python Software Foundation
2
+ # Author: Barry Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ """email package exception classes."""
6
+
7
+
8
+ class MessageError(Exception):
9
+ """Base class for errors in the email package."""
10
+
11
+
12
+ class MessageParseError(MessageError):
13
+ """Base class for message parsing errors."""
14
+
15
+
16
+ class HeaderParseError(MessageParseError):
17
+ """Error while parsing headers."""
18
+
19
+
20
+ class BoundaryError(MessageParseError):
21
+ """Couldn't find terminating boundary."""
22
+
23
+
24
+ class MultipartConversionError(MessageError, TypeError):
25
+ """Conversion to a multipart is prohibited."""
26
+
27
+
28
+ class CharsetError(MessageError):
29
+ """An illegal charset was given."""
30
+
31
+
32
+ # These are parsing defects which the parser was able to work around.
33
+ class MessageDefect(ValueError):
34
+ """Base class for a message defect."""
35
+
36
+ def __init__(self, line=None):
37
+ if line is not None:
38
+ super().__init__(line)
39
+ self.line = line
40
+
41
+ class NoBoundaryInMultipartDefect(MessageDefect):
42
+ """A message claimed to be a multipart but had no boundary parameter."""
43
+
44
+ class StartBoundaryNotFoundDefect(MessageDefect):
45
+ """The claimed start boundary was never found."""
46
+
47
+ class CloseBoundaryNotFoundDefect(MessageDefect):
48
+ """A start boundary was found, but not the corresponding close boundary."""
49
+
50
+ class FirstHeaderLineIsContinuationDefect(MessageDefect):
51
+ """A message had a continuation line as its first header line."""
52
+
53
+ class MisplacedEnvelopeHeaderDefect(MessageDefect):
54
+ """A 'Unix-from' header was found in the middle of a header block."""
55
+
56
+ class MissingHeaderBodySeparatorDefect(MessageDefect):
57
+ """Found line with no leading whitespace and no colon before blank line."""
58
+ # XXX: backward compatibility, just in case (it was never emitted).
59
+ MalformedHeaderDefect = MissingHeaderBodySeparatorDefect
60
+
61
+ class MultipartInvariantViolationDefect(MessageDefect):
62
+ """A message claimed to be a multipart but no subparts were found."""
63
+
64
+ class InvalidMultipartContentTransferEncodingDefect(MessageDefect):
65
+ """An invalid content transfer encoding was set on the multipart itself."""
66
+
67
+ class UndecodableBytesDefect(MessageDefect):
68
+ """Header contained bytes that could not be decoded"""
69
+
70
+ class InvalidBase64PaddingDefect(MessageDefect):
71
+ """base64 encoded sequence had an incorrect length"""
72
+
73
+ class InvalidBase64CharactersDefect(MessageDefect):
74
+ """base64 encoded sequence had characters not in base64 alphabet"""
75
+
76
+ class InvalidBase64LengthDefect(MessageDefect):
77
+ """base64 encoded sequence had invalid length (1 mod 4)"""
78
+
79
+ # These errors are specific to header parsing.
80
+
81
+ class HeaderDefect(MessageDefect):
82
+ """Base class for a header defect."""
83
+
84
+ def __init__(self, *args, **kw):
85
+ super().__init__(*args, **kw)
86
+
87
+ class InvalidHeaderDefect(HeaderDefect):
88
+ """Header is not valid, message gives details."""
89
+
90
+ class HeaderMissingRequiredValue(HeaderDefect):
91
+ """A header that must have a value had none"""
92
+
93
+ class NonPrintableDefect(HeaderDefect):
94
+ """ASCII characters outside the ascii-printable range found"""
95
+
96
+ def __init__(self, non_printables):
97
+ super().__init__(non_printables)
98
+ self.non_printables = non_printables
99
+
100
+ def __str__(self):
101
+ return ("the following ASCII non-printables found in header: "
102
+ "{}".format(self.non_printables))
103
+
104
+ class ObsoleteHeaderDefect(HeaderDefect):
105
+ """Header uses syntax declared obsolete by RFC 5322"""
106
+
107
+ class NonASCIILocalPartDefect(HeaderDefect):
108
+ """local_part contains non-ASCII characters"""
109
+ # This defect only occurs during unicode parsing, not when
110
+ # parsing messages decoded from binary.
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/feedparser.py ADDED
@@ -0,0 +1,536 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2004-2006 Python Software Foundation
2
+ # Authors: Baxter, Wouters and Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ """FeedParser - An email feed parser.
6
+
7
+ The feed parser implements an interface for incrementally parsing an email
8
+ message, line by line. This has advantages for certain applications, such as
9
+ those reading email messages off a socket.
10
+
11
+ FeedParser.feed() is the primary interface for pushing new data into the
12
+ parser. It returns when there's nothing more it can do with the available
13
+ data. When you have no more data to push into the parser, call .close().
14
+ This completes the parsing and returns the root message object.
15
+
16
+ The other advantage of this parser is that it will never raise a parsing
17
+ exception. Instead, when it finds something unexpected, it adds a 'defect' to
18
+ the current message. Defects are just instances that live on the message
19
+ object's .defects attribute.
20
+ """
21
+
22
+ __all__ = ['FeedParser', 'BytesFeedParser']
23
+
24
+ import re
25
+
26
+ from email import errors
27
+ from email._policybase import compat32
28
+ from collections import deque
29
+ from io import StringIO
30
+
31
+ NLCRE = re.compile(r'\r\n|\r|\n')
32
+ NLCRE_bol = re.compile(r'(\r\n|\r|\n)')
33
+ NLCRE_eol = re.compile(r'(\r\n|\r|\n)\Z')
34
+ NLCRE_crack = re.compile(r'(\r\n|\r|\n)')
35
+ # RFC 2822 $3.6.8 Optional fields. ftext is %d33-57 / %d59-126, Any character
36
+ # except controls, SP, and ":".
37
+ headerRE = re.compile(r'^(From |[\041-\071\073-\176]*:|[\t ])')
38
+ EMPTYSTRING = ''
39
+ NL = '\n'
40
+
41
+ NeedMoreData = object()
42
+
43
+
44
+
45
+ class BufferedSubFile(object):
46
+ """A file-ish object that can have new data loaded into it.
47
+
48
+ You can also push and pop line-matching predicates onto a stack. When the
49
+ current predicate matches the current line, a false EOF response
50
+ (i.e. empty string) is returned instead. This lets the parser adhere to a
51
+ simple abstraction -- it parses until EOF closes the current message.
52
+ """
53
+ def __init__(self):
54
+ # Text stream of the last partial line pushed into this object.
55
+ # See issue 22233 for why this is a text stream and not a list.
56
+ self._partial = StringIO(newline='')
57
+ # A deque of full, pushed lines
58
+ self._lines = deque()
59
+ # The stack of false-EOF checking predicates.
60
+ self._eofstack = []
61
+ # A flag indicating whether the file has been closed or not.
62
+ self._closed = False
63
+
64
+ def push_eof_matcher(self, pred):
65
+ self._eofstack.append(pred)
66
+
67
+ def pop_eof_matcher(self):
68
+ return self._eofstack.pop()
69
+
70
+ def close(self):
71
+ # Don't forget any trailing partial line.
72
+ self._partial.seek(0)
73
+ self.pushlines(self._partial.readlines())
74
+ self._partial.seek(0)
75
+ self._partial.truncate()
76
+ self._closed = True
77
+
78
+ def readline(self):
79
+ if not self._lines:
80
+ if self._closed:
81
+ return ''
82
+ return NeedMoreData
83
+ # Pop the line off the stack and see if it matches the current
84
+ # false-EOF predicate.
85
+ line = self._lines.popleft()
86
+ # RFC 2046, section 5.1.2 requires us to recognize outer level
87
+ # boundaries at any level of inner nesting. Do this, but be sure it's
88
+ # in the order of most to least nested.
89
+ for ateof in reversed(self._eofstack):
90
+ if ateof(line):
91
+ # We're at the false EOF. But push the last line back first.
92
+ self._lines.appendleft(line)
93
+ return ''
94
+ return line
95
+
96
+ def unreadline(self, line):
97
+ # Let the consumer push a line back into the buffer.
98
+ assert line is not NeedMoreData
99
+ self._lines.appendleft(line)
100
+
101
+ def push(self, data):
102
+ """Push some new data into this object."""
103
+ self._partial.write(data)
104
+ if '\n' not in data and '\r' not in data:
105
+ # No new complete lines, wait for more.
106
+ return
107
+
108
+ # Crack into lines, preserving the linesep characters.
109
+ self._partial.seek(0)
110
+ parts = self._partial.readlines()
111
+ self._partial.seek(0)
112
+ self._partial.truncate()
113
+
114
+ # If the last element of the list does not end in a newline, then treat
115
+ # it as a partial line. We only check for '\n' here because a line
116
+ # ending with '\r' might be a line that was split in the middle of a
117
+ # '\r\n' sequence (see bugs 1555570 and 1721862).
118
+ if not parts[-1].endswith('\n'):
119
+ self._partial.write(parts.pop())
120
+ self.pushlines(parts)
121
+
122
+ def pushlines(self, lines):
123
+ self._lines.extend(lines)
124
+
125
+ def __iter__(self):
126
+ return self
127
+
128
+ def __next__(self):
129
+ line = self.readline()
130
+ if line == '':
131
+ raise StopIteration
132
+ return line
133
+
134
+
135
+
136
+ class FeedParser:
137
+ """A feed-style parser of email."""
138
+
139
+ def __init__(self, _factory=None, *, policy=compat32):
140
+ """_factory is called with no arguments to create a new message obj
141
+
142
+ The policy keyword specifies a policy object that controls a number of
143
+ aspects of the parser's operation. The default policy maintains
144
+ backward compatibility.
145
+
146
+ """
147
+ self.policy = policy
148
+ self._old_style_factory = False
149
+ if _factory is None:
150
+ if policy.message_factory is None:
151
+ from email.message import Message
152
+ self._factory = Message
153
+ else:
154
+ self._factory = policy.message_factory
155
+ else:
156
+ self._factory = _factory
157
+ try:
158
+ _factory(policy=self.policy)
159
+ except TypeError:
160
+ # Assume this is an old-style factory
161
+ self._old_style_factory = True
162
+ self._input = BufferedSubFile()
163
+ self._msgstack = []
164
+ self._parse = self._parsegen().__next__
165
+ self._cur = None
166
+ self._last = None
167
+ self._headersonly = False
168
+
169
+ # Non-public interface for supporting Parser's headersonly flag
170
+ def _set_headersonly(self):
171
+ self._headersonly = True
172
+
173
+ def feed(self, data):
174
+ """Push more data into the parser."""
175
+ self._input.push(data)
176
+ self._call_parse()
177
+
178
+ def _call_parse(self):
179
+ try:
180
+ self._parse()
181
+ except StopIteration:
182
+ pass
183
+
184
+ def close(self):
185
+ """Parse all remaining data and return the root message object."""
186
+ self._input.close()
187
+ self._call_parse()
188
+ root = self._pop_message()
189
+ assert not self._msgstack
190
+ # Look for final set of defects
191
+ if root.get_content_maintype() == 'multipart' \
192
+ and not root.is_multipart():
193
+ defect = errors.MultipartInvariantViolationDefect()
194
+ self.policy.handle_defect(root, defect)
195
+ return root
196
+
197
+ def _new_message(self):
198
+ if self._old_style_factory:
199
+ msg = self._factory()
200
+ else:
201
+ msg = self._factory(policy=self.policy)
202
+ if self._cur and self._cur.get_content_type() == 'multipart/digest':
203
+ msg.set_default_type('message/rfc822')
204
+ if self._msgstack:
205
+ self._msgstack[-1].attach(msg)
206
+ self._msgstack.append(msg)
207
+ self._cur = msg
208
+ self._last = msg
209
+
210
+ def _pop_message(self):
211
+ retval = self._msgstack.pop()
212
+ if self._msgstack:
213
+ self._cur = self._msgstack[-1]
214
+ else:
215
+ self._cur = None
216
+ return retval
217
+
218
+ def _parsegen(self):
219
+ # Create a new message and start by parsing headers.
220
+ self._new_message()
221
+ headers = []
222
+ # Collect the headers, searching for a line that doesn't match the RFC
223
+ # 2822 header or continuation pattern (including an empty line).
224
+ for line in self._input:
225
+ if line is NeedMoreData:
226
+ yield NeedMoreData
227
+ continue
228
+ if not headerRE.match(line):
229
+ # If we saw the RFC defined header/body separator
230
+ # (i.e. newline), just throw it away. Otherwise the line is
231
+ # part of the body so push it back.
232
+ if not NLCRE.match(line):
233
+ defect = errors.MissingHeaderBodySeparatorDefect()
234
+ self.policy.handle_defect(self._cur, defect)
235
+ self._input.unreadline(line)
236
+ break
237
+ headers.append(line)
238
+ # Done with the headers, so parse them and figure out what we're
239
+ # supposed to see in the body of the message.
240
+ self._parse_headers(headers)
241
+ # Headers-only parsing is a backwards compatibility hack, which was
242
+ # necessary in the older parser, which could raise errors. All
243
+ # remaining lines in the input are thrown into the message body.
244
+ if self._headersonly:
245
+ lines = []
246
+ while True:
247
+ line = self._input.readline()
248
+ if line is NeedMoreData:
249
+ yield NeedMoreData
250
+ continue
251
+ if line == '':
252
+ break
253
+ lines.append(line)
254
+ self._cur.set_payload(EMPTYSTRING.join(lines))
255
+ return
256
+ if self._cur.get_content_type() == 'message/delivery-status':
257
+ # message/delivery-status contains blocks of headers separated by
258
+ # a blank line. We'll represent each header block as a separate
259
+ # nested message object, but the processing is a bit different
260
+ # than standard message/* types because there is no body for the
261
+ # nested messages. A blank line separates the subparts.
262
+ while True:
263
+ self._input.push_eof_matcher(NLCRE.match)
264
+ for retval in self._parsegen():
265
+ if retval is NeedMoreData:
266
+ yield NeedMoreData
267
+ continue
268
+ break
269
+ msg = self._pop_message()
270
+ # We need to pop the EOF matcher in order to tell if we're at
271
+ # the end of the current file, not the end of the last block
272
+ # of message headers.
273
+ self._input.pop_eof_matcher()
274
+ # The input stream must be sitting at the newline or at the
275
+ # EOF. We want to see if we're at the end of this subpart, so
276
+ # first consume the blank line, then test the next line to see
277
+ # if we're at this subpart's EOF.
278
+ while True:
279
+ line = self._input.readline()
280
+ if line is NeedMoreData:
281
+ yield NeedMoreData
282
+ continue
283
+ break
284
+ while True:
285
+ line = self._input.readline()
286
+ if line is NeedMoreData:
287
+ yield NeedMoreData
288
+ continue
289
+ break
290
+ if line == '':
291
+ break
292
+ # Not at EOF so this is a line we're going to need.
293
+ self._input.unreadline(line)
294
+ return
295
+ if self._cur.get_content_maintype() == 'message':
296
+ # The message claims to be a message/* type, then what follows is
297
+ # another RFC 2822 message.
298
+ for retval in self._parsegen():
299
+ if retval is NeedMoreData:
300
+ yield NeedMoreData
301
+ continue
302
+ break
303
+ self._pop_message()
304
+ return
305
+ if self._cur.get_content_maintype() == 'multipart':
306
+ boundary = self._cur.get_boundary()
307
+ if boundary is None:
308
+ # The message /claims/ to be a multipart but it has not
309
+ # defined a boundary. That's a problem which we'll handle by
310
+ # reading everything until the EOF and marking the message as
311
+ # defective.
312
+ defect = errors.NoBoundaryInMultipartDefect()
313
+ self.policy.handle_defect(self._cur, defect)
314
+ lines = []
315
+ for line in self._input:
316
+ if line is NeedMoreData:
317
+ yield NeedMoreData
318
+ continue
319
+ lines.append(line)
320
+ self._cur.set_payload(EMPTYSTRING.join(lines))
321
+ return
322
+ # Make sure a valid content type was specified per RFC 2045:6.4.
323
+ if (str(self._cur.get('content-transfer-encoding', '8bit')).lower()
324
+ not in ('7bit', '8bit', 'binary')):
325
+ defect = errors.InvalidMultipartContentTransferEncodingDefect()
326
+ self.policy.handle_defect(self._cur, defect)
327
+ # Create a line match predicate which matches the inter-part
328
+ # boundary as well as the end-of-multipart boundary. Don't push
329
+ # this onto the input stream until we've scanned past the
330
+ # preamble.
331
+ separator = '--' + boundary
332
+ boundaryre = re.compile(
333
+ '(?P<sep>' + re.escape(separator) +
334
+ r')(?P<end>--)?(?P<ws>[ \t]*)(?P<linesep>\r\n|\r|\n)?$')
335
+ capturing_preamble = True
336
+ preamble = []
337
+ linesep = False
338
+ close_boundary_seen = False
339
+ while True:
340
+ line = self._input.readline()
341
+ if line is NeedMoreData:
342
+ yield NeedMoreData
343
+ continue
344
+ if line == '':
345
+ break
346
+ mo = boundaryre.match(line)
347
+ if mo:
348
+ # If we're looking at the end boundary, we're done with
349
+ # this multipart. If there was a newline at the end of
350
+ # the closing boundary, then we need to initialize the
351
+ # epilogue with the empty string (see below).
352
+ if mo.group('end'):
353
+ close_boundary_seen = True
354
+ linesep = mo.group('linesep')
355
+ break
356
+ # We saw an inter-part boundary. Were we in the preamble?
357
+ if capturing_preamble:
358
+ if preamble:
359
+ # According to RFC 2046, the last newline belongs
360
+ # to the boundary.
361
+ lastline = preamble[-1]
362
+ eolmo = NLCRE_eol.search(lastline)
363
+ if eolmo:
364
+ preamble[-1] = lastline[:-len(eolmo.group(0))]
365
+ self._cur.preamble = EMPTYSTRING.join(preamble)
366
+ capturing_preamble = False
367
+ self._input.unreadline(line)
368
+ continue
369
+ # We saw a boundary separating two parts. Consume any
370
+ # multiple boundary lines that may be following. Our
371
+ # interpretation of RFC 2046 BNF grammar does not produce
372
+ # body parts within such double boundaries.
373
+ while True:
374
+ line = self._input.readline()
375
+ if line is NeedMoreData:
376
+ yield NeedMoreData
377
+ continue
378
+ mo = boundaryre.match(line)
379
+ if not mo:
380
+ self._input.unreadline(line)
381
+ break
382
+ # Recurse to parse this subpart; the input stream points
383
+ # at the subpart's first line.
384
+ self._input.push_eof_matcher(boundaryre.match)
385
+ for retval in self._parsegen():
386
+ if retval is NeedMoreData:
387
+ yield NeedMoreData
388
+ continue
389
+ break
390
+ # Because of RFC 2046, the newline preceding the boundary
391
+ # separator actually belongs to the boundary, not the
392
+ # previous subpart's payload (or epilogue if the previous
393
+ # part is a multipart).
394
+ if self._last.get_content_maintype() == 'multipart':
395
+ epilogue = self._last.epilogue
396
+ if epilogue == '':
397
+ self._last.epilogue = None
398
+ elif epilogue is not None:
399
+ mo = NLCRE_eol.search(epilogue)
400
+ if mo:
401
+ end = len(mo.group(0))
402
+ self._last.epilogue = epilogue[:-end]
403
+ else:
404
+ payload = self._last._payload
405
+ if isinstance(payload, str):
406
+ mo = NLCRE_eol.search(payload)
407
+ if mo:
408
+ payload = payload[:-len(mo.group(0))]
409
+ self._last._payload = payload
410
+ self._input.pop_eof_matcher()
411
+ self._pop_message()
412
+ # Set the multipart up for newline cleansing, which will
413
+ # happen if we're in a nested multipart.
414
+ self._last = self._cur
415
+ else:
416
+ # I think we must be in the preamble
417
+ assert capturing_preamble
418
+ preamble.append(line)
419
+ # We've seen either the EOF or the end boundary. If we're still
420
+ # capturing the preamble, we never saw the start boundary. Note
421
+ # that as a defect and store the captured text as the payload.
422
+ if capturing_preamble:
423
+ defect = errors.StartBoundaryNotFoundDefect()
424
+ self.policy.handle_defect(self._cur, defect)
425
+ self._cur.set_payload(EMPTYSTRING.join(preamble))
426
+ epilogue = []
427
+ for line in self._input:
428
+ if line is NeedMoreData:
429
+ yield NeedMoreData
430
+ continue
431
+ self._cur.epilogue = EMPTYSTRING.join(epilogue)
432
+ return
433
+ # If we're not processing the preamble, then we might have seen
434
+ # EOF without seeing that end boundary...that is also a defect.
435
+ if not close_boundary_seen:
436
+ defect = errors.CloseBoundaryNotFoundDefect()
437
+ self.policy.handle_defect(self._cur, defect)
438
+ return
439
+ # Everything from here to the EOF is epilogue. If the end boundary
440
+ # ended in a newline, we'll need to make sure the epilogue isn't
441
+ # None
442
+ if linesep:
443
+ epilogue = ['']
444
+ else:
445
+ epilogue = []
446
+ for line in self._input:
447
+ if line is NeedMoreData:
448
+ yield NeedMoreData
449
+ continue
450
+ epilogue.append(line)
451
+ # Any CRLF at the front of the epilogue is not technically part of
452
+ # the epilogue. Also, watch out for an empty string epilogue,
453
+ # which means a single newline.
454
+ if epilogue:
455
+ firstline = epilogue[0]
456
+ bolmo = NLCRE_bol.match(firstline)
457
+ if bolmo:
458
+ epilogue[0] = firstline[len(bolmo.group(0)):]
459
+ self._cur.epilogue = EMPTYSTRING.join(epilogue)
460
+ return
461
+ # Otherwise, it's some non-multipart type, so the entire rest of the
462
+ # file contents becomes the payload.
463
+ lines = []
464
+ for line in self._input:
465
+ if line is NeedMoreData:
466
+ yield NeedMoreData
467
+ continue
468
+ lines.append(line)
469
+ self._cur.set_payload(EMPTYSTRING.join(lines))
470
+
471
+ def _parse_headers(self, lines):
472
+ # Passed a list of lines that make up the headers for the current msg
473
+ lastheader = ''
474
+ lastvalue = []
475
+ for lineno, line in enumerate(lines):
476
+ # Check for continuation
477
+ if line[0] in ' \t':
478
+ if not lastheader:
479
+ # The first line of the headers was a continuation. This
480
+ # is illegal, so let's note the defect, store the illegal
481
+ # line, and ignore it for purposes of headers.
482
+ defect = errors.FirstHeaderLineIsContinuationDefect(line)
483
+ self.policy.handle_defect(self._cur, defect)
484
+ continue
485
+ lastvalue.append(line)
486
+ continue
487
+ if lastheader:
488
+ self._cur.set_raw(*self.policy.header_source_parse(lastvalue))
489
+ lastheader, lastvalue = '', []
490
+ # Check for envelope header, i.e. unix-from
491
+ if line.startswith('From '):
492
+ if lineno == 0:
493
+ # Strip off the trailing newline
494
+ mo = NLCRE_eol.search(line)
495
+ if mo:
496
+ line = line[:-len(mo.group(0))]
497
+ self._cur.set_unixfrom(line)
498
+ continue
499
+ elif lineno == len(lines) - 1:
500
+ # Something looking like a unix-from at the end - it's
501
+ # probably the first line of the body, so push back the
502
+ # line and stop.
503
+ self._input.unreadline(line)
504
+ return
505
+ else:
506
+ # Weirdly placed unix-from line. Note this as a defect
507
+ # and ignore it.
508
+ defect = errors.MisplacedEnvelopeHeaderDefect(line)
509
+ self._cur.defects.append(defect)
510
+ continue
511
+ # Split the line on the colon separating field name from value.
512
+ # There will always be a colon, because if there wasn't the part of
513
+ # the parser that calls us would have started parsing the body.
514
+ i = line.find(':')
515
+
516
+ # If the colon is on the start of the line the header is clearly
517
+ # malformed, but we might be able to salvage the rest of the
518
+ # message. Track the error but keep going.
519
+ if i == 0:
520
+ defect = errors.InvalidHeaderDefect("Missing header name.")
521
+ self._cur.defects.append(defect)
522
+ continue
523
+
524
+ assert i>0, "_parse_headers fed line with no : and no leading WS"
525
+ lastheader = line[:i]
526
+ lastvalue = [line]
527
+ # Done with all the lines, so handle the last header.
528
+ if lastheader:
529
+ self._cur.set_raw(*self.policy.header_source_parse(lastvalue))
530
+
531
+
532
+ class BytesFeedParser(FeedParser):
533
+ """Like FeedParser, but feed accepts bytes."""
534
+
535
+ def feed(self, data):
536
+ super().feed(data.decode('ascii', 'surrogateescape'))
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/generator.py ADDED
@@ -0,0 +1,512 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2010 Python Software Foundation
2
+ # Author: Barry Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ """Classes to generate plain text from a message object tree."""
6
+
7
+ __all__ = ['Generator', 'DecodedGenerator', 'BytesGenerator']
8
+
9
+ import re
10
+ import sys
11
+ import time
12
+ import random
13
+
14
+ from copy import deepcopy
15
+ from io import StringIO, BytesIO
16
+ from email.utils import _has_surrogates
17
+
18
+ UNDERSCORE = '_'
19
+ NL = '\n' # XXX: no longer used by the code below.
20
+
21
+ NLCRE = re.compile(r'\r\n|\r|\n')
22
+ fcre = re.compile(r'^From ', re.MULTILINE)
23
+
24
+
25
+
26
+ class Generator:
27
+ """Generates output from a Message object tree.
28
+
29
+ This basic generator writes the message to the given file object as plain
30
+ text.
31
+ """
32
+ #
33
+ # Public interface
34
+ #
35
+
36
+ def __init__(self, outfp, mangle_from_=None, maxheaderlen=None, *,
37
+ policy=None):
38
+ """Create the generator for message flattening.
39
+
40
+ outfp is the output file-like object for writing the message to. It
41
+ must have a write() method.
42
+
43
+ Optional mangle_from_ is a flag that, when True (the default if policy
44
+ is not set), escapes From_ lines in the body of the message by putting
45
+ a `>' in front of them.
46
+
47
+ Optional maxheaderlen specifies the longest length for a non-continued
48
+ header. When a header line is longer (in characters, with tabs
49
+ expanded to 8 spaces) than maxheaderlen, the header will split as
50
+ defined in the Header class. Set maxheaderlen to zero to disable
51
+ header wrapping. The default is 78, as recommended (but not required)
52
+ by RFC 2822.
53
+
54
+ The policy keyword specifies a policy object that controls a number of
55
+ aspects of the generator's operation. If no policy is specified,
56
+ the policy associated with the Message object passed to the
57
+ flatten method is used.
58
+
59
+ """
60
+
61
+ if mangle_from_ is None:
62
+ mangle_from_ = True if policy is None else policy.mangle_from_
63
+ self._fp = outfp
64
+ self._mangle_from_ = mangle_from_
65
+ self.maxheaderlen = maxheaderlen
66
+ self.policy = policy
67
+
68
+ def write(self, s):
69
+ # Just delegate to the file object
70
+ self._fp.write(s)
71
+
72
+ def flatten(self, msg, unixfrom=False, linesep=None):
73
+ r"""Print the message object tree rooted at msg to the output file
74
+ specified when the Generator instance was created.
75
+
76
+ unixfrom is a flag that forces the printing of a Unix From_ delimiter
77
+ before the first object in the message tree. If the original message
78
+ has no From_ delimiter, a `standard' one is crafted. By default, this
79
+ is False to inhibit the printing of any From_ delimiter.
80
+
81
+ Note that for subobjects, no From_ line is printed.
82
+
83
+ linesep specifies the characters used to indicate a new line in
84
+ the output. The default value is determined by the policy specified
85
+ when the Generator instance was created or, if none was specified,
86
+ from the policy associated with the msg.
87
+
88
+ """
89
+ # We use the _XXX constants for operating on data that comes directly
90
+ # from the msg, and _encoded_XXX constants for operating on data that
91
+ # has already been converted (to bytes in the BytesGenerator) and
92
+ # inserted into a temporary buffer.
93
+ policy = msg.policy if self.policy is None else self.policy
94
+ if linesep is not None:
95
+ policy = policy.clone(linesep=linesep)
96
+ if self.maxheaderlen is not None:
97
+ policy = policy.clone(max_line_length=self.maxheaderlen)
98
+ self._NL = policy.linesep
99
+ self._encoded_NL = self._encode(self._NL)
100
+ self._EMPTY = ''
101
+ self._encoded_EMPTY = self._encode(self._EMPTY)
102
+ # Because we use clone (below) when we recursively process message
103
+ # subparts, and because clone uses the computed policy (not None),
104
+ # submessages will automatically get set to the computed policy when
105
+ # they are processed by this code.
106
+ old_gen_policy = self.policy
107
+ old_msg_policy = msg.policy
108
+ try:
109
+ self.policy = policy
110
+ msg.policy = policy
111
+ if unixfrom:
112
+ ufrom = msg.get_unixfrom()
113
+ if not ufrom:
114
+ ufrom = 'From nobody ' + time.ctime(time.time())
115
+ self.write(ufrom + self._NL)
116
+ self._write(msg)
117
+ finally:
118
+ self.policy = old_gen_policy
119
+ msg.policy = old_msg_policy
120
+
121
+ def clone(self, fp):
122
+ """Clone this generator with the exact same options."""
123
+ return self.__class__(fp,
124
+ self._mangle_from_,
125
+ None, # Use policy setting, which we've adjusted
126
+ policy=self.policy)
127
+
128
+ #
129
+ # Protected interface - undocumented ;/
130
+ #
131
+
132
+ # Note that we use 'self.write' when what we are writing is coming from
133
+ # the source, and self._fp.write when what we are writing is coming from a
134
+ # buffer (because the Bytes subclass has already had a chance to transform
135
+ # the data in its write method in that case). This is an entirely
136
+ # pragmatic split determined by experiment; we could be more general by
137
+ # always using write and having the Bytes subclass write method detect when
138
+ # it has already transformed the input; but, since this whole thing is a
139
+ # hack anyway this seems good enough.
140
+
141
+ def _new_buffer(self):
142
+ # BytesGenerator overrides this to return BytesIO.
143
+ return StringIO()
144
+
145
+ def _encode(self, s):
146
+ # BytesGenerator overrides this to encode strings to bytes.
147
+ return s
148
+
149
+ def _write_lines(self, lines):
150
+ # We have to transform the line endings.
151
+ if not lines:
152
+ return
153
+ lines = NLCRE.split(lines)
154
+ for line in lines[:-1]:
155
+ self.write(line)
156
+ self.write(self._NL)
157
+ if lines[-1]:
158
+ self.write(lines[-1])
159
+ # XXX logic tells me this else should be needed, but the tests fail
160
+ # with it and pass without it. (NLCRE.split ends with a blank element
161
+ # if and only if there was a trailing newline.)
162
+ #else:
163
+ # self.write(self._NL)
164
+
165
+ def _write(self, msg):
166
+ # We can't write the headers yet because of the following scenario:
167
+ # say a multipart message includes the boundary string somewhere in
168
+ # its body. We'd have to calculate the new boundary /before/ we write
169
+ # the headers so that we can write the correct Content-Type:
170
+ # parameter.
171
+ #
172
+ # The way we do this, so as to make the _handle_*() methods simpler,
173
+ # is to cache any subpart writes into a buffer. The we write the
174
+ # headers and the buffer contents. That way, subpart handlers can
175
+ # Do The Right Thing, and can still modify the Content-Type: header if
176
+ # necessary.
177
+ oldfp = self._fp
178
+ try:
179
+ self._munge_cte = None
180
+ self._fp = sfp = self._new_buffer()
181
+ self._dispatch(msg)
182
+ finally:
183
+ self._fp = oldfp
184
+ munge_cte = self._munge_cte
185
+ del self._munge_cte
186
+ # If we munged the cte, copy the message again and re-fix the CTE.
187
+ if munge_cte:
188
+ msg = deepcopy(msg)
189
+ # Preserve the header order if the CTE header already exists.
190
+ if msg.get('content-transfer-encoding') is None:
191
+ msg['Content-Transfer-Encoding'] = munge_cte[0]
192
+ else:
193
+ msg.replace_header('content-transfer-encoding', munge_cte[0])
194
+ msg.replace_header('content-type', munge_cte[1])
195
+ # Write the headers. First we see if the message object wants to
196
+ # handle that itself. If not, we'll do it generically.
197
+ meth = getattr(msg, '_write_headers', None)
198
+ if meth is None:
199
+ self._write_headers(msg)
200
+ else:
201
+ meth(self)
202
+ self._fp.write(sfp.getvalue())
203
+
204
+ def _dispatch(self, msg):
205
+ # Get the Content-Type: for the message, then try to dispatch to
206
+ # self._handle_<maintype>_<subtype>(). If there's no handler for the
207
+ # full MIME type, then dispatch to self._handle_<maintype>(). If
208
+ # that's missing too, then dispatch to self._writeBody().
209
+ main = msg.get_content_maintype()
210
+ sub = msg.get_content_subtype()
211
+ specific = UNDERSCORE.join((main, sub)).replace('-', '_')
212
+ meth = getattr(self, '_handle_' + specific, None)
213
+ if meth is None:
214
+ generic = main.replace('-', '_')
215
+ meth = getattr(self, '_handle_' + generic, None)
216
+ if meth is None:
217
+ meth = self._writeBody
218
+ meth(msg)
219
+
220
+ #
221
+ # Default handlers
222
+ #
223
+
224
+ def _write_headers(self, msg):
225
+ for h, v in msg.raw_items():
226
+ self.write(self.policy.fold(h, v))
227
+ # A blank line always separates headers from body
228
+ self.write(self._NL)
229
+
230
+ #
231
+ # Handlers for writing types and subtypes
232
+ #
233
+
234
+ def _handle_text(self, msg):
235
+ payload = msg.get_payload()
236
+ if payload is None:
237
+ return
238
+ if not isinstance(payload, str):
239
+ raise TypeError('string payload expected: %s' % type(payload))
240
+ if _has_surrogates(msg._payload):
241
+ charset = msg.get_param('charset')
242
+ if charset is not None:
243
+ # XXX: This copy stuff is an ugly hack to avoid modifying the
244
+ # existing message.
245
+ msg = deepcopy(msg)
246
+ del msg['content-transfer-encoding']
247
+ msg.set_payload(payload, charset)
248
+ payload = msg.get_payload()
249
+ self._munge_cte = (msg['content-transfer-encoding'],
250
+ msg['content-type'])
251
+ if self._mangle_from_:
252
+ payload = fcre.sub('>From ', payload)
253
+ self._write_lines(payload)
254
+
255
+ # Default body handler
256
+ _writeBody = _handle_text
257
+
258
+ def _handle_multipart(self, msg):
259
+ # The trick here is to write out each part separately, merge them all
260
+ # together, and then make sure that the boundary we've chosen isn't
261
+ # present in the payload.
262
+ msgtexts = []
263
+ subparts = msg.get_payload()
264
+ if subparts is None:
265
+ subparts = []
266
+ elif isinstance(subparts, str):
267
+ # e.g. a non-strict parse of a message with no starting boundary.
268
+ self.write(subparts)
269
+ return
270
+ elif not isinstance(subparts, list):
271
+ # Scalar payload
272
+ subparts = [subparts]
273
+ for part in subparts:
274
+ s = self._new_buffer()
275
+ g = self.clone(s)
276
+ g.flatten(part, unixfrom=False, linesep=self._NL)
277
+ msgtexts.append(s.getvalue())
278
+ # BAW: What about boundaries that are wrapped in double-quotes?
279
+ boundary = msg.get_boundary()
280
+ if not boundary:
281
+ # Create a boundary that doesn't appear in any of the
282
+ # message texts.
283
+ alltext = self._encoded_NL.join(msgtexts)
284
+ boundary = self._make_boundary(alltext)
285
+ msg.set_boundary(boundary)
286
+ # If there's a preamble, write it out, with a trailing CRLF
287
+ if msg.preamble is not None:
288
+ if self._mangle_from_:
289
+ preamble = fcre.sub('>From ', msg.preamble)
290
+ else:
291
+ preamble = msg.preamble
292
+ self._write_lines(preamble)
293
+ self.write(self._NL)
294
+ # dash-boundary transport-padding CRLF
295
+ self.write('--' + boundary + self._NL)
296
+ # body-part
297
+ if msgtexts:
298
+ self._fp.write(msgtexts.pop(0))
299
+ # *encapsulation
300
+ # --> delimiter transport-padding
301
+ # --> CRLF body-part
302
+ for body_part in msgtexts:
303
+ # delimiter transport-padding CRLF
304
+ self.write(self._NL + '--' + boundary + self._NL)
305
+ # body-part
306
+ self._fp.write(body_part)
307
+ # close-delimiter transport-padding
308
+ self.write(self._NL + '--' + boundary + '--' + self._NL)
309
+ if msg.epilogue is not None:
310
+ if self._mangle_from_:
311
+ epilogue = fcre.sub('>From ', msg.epilogue)
312
+ else:
313
+ epilogue = msg.epilogue
314
+ self._write_lines(epilogue)
315
+
316
+ def _handle_multipart_signed(self, msg):
317
+ # The contents of signed parts has to stay unmodified in order to keep
318
+ # the signature intact per RFC1847 2.1, so we disable header wrapping.
319
+ # RDM: This isn't enough to completely preserve the part, but it helps.
320
+ p = self.policy
321
+ self.policy = p.clone(max_line_length=0)
322
+ try:
323
+ self._handle_multipart(msg)
324
+ finally:
325
+ self.policy = p
326
+
327
+ def _handle_message_delivery_status(self, msg):
328
+ # We can't just write the headers directly to self's file object
329
+ # because this will leave an extra newline between the last header
330
+ # block and the boundary. Sigh.
331
+ blocks = []
332
+ for part in msg.get_payload():
333
+ s = self._new_buffer()
334
+ g = self.clone(s)
335
+ g.flatten(part, unixfrom=False, linesep=self._NL)
336
+ text = s.getvalue()
337
+ lines = text.split(self._encoded_NL)
338
+ # Strip off the unnecessary trailing empty line
339
+ if lines and lines[-1] == self._encoded_EMPTY:
340
+ blocks.append(self._encoded_NL.join(lines[:-1]))
341
+ else:
342
+ blocks.append(text)
343
+ # Now join all the blocks with an empty line. This has the lovely
344
+ # effect of separating each block with an empty line, but not adding
345
+ # an extra one after the last one.
346
+ self._fp.write(self._encoded_NL.join(blocks))
347
+
348
+ def _handle_message(self, msg):
349
+ s = self._new_buffer()
350
+ g = self.clone(s)
351
+ # The payload of a message/rfc822 part should be a multipart sequence
352
+ # of length 1. The zeroth element of the list should be the Message
353
+ # object for the subpart. Extract that object, stringify it, and
354
+ # write it out.
355
+ # Except, it turns out, when it's a string instead, which happens when
356
+ # and only when HeaderParser is used on a message of mime type
357
+ # message/rfc822. Such messages are generated by, for example,
358
+ # Groupwise when forwarding unadorned messages. (Issue 7970.) So
359
+ # in that case we just emit the string body.
360
+ payload = msg._payload
361
+ if isinstance(payload, list):
362
+ g.flatten(msg.get_payload(0), unixfrom=False, linesep=self._NL)
363
+ payload = s.getvalue()
364
+ else:
365
+ payload = self._encode(payload)
366
+ self._fp.write(payload)
367
+
368
+ # This used to be a module level function; we use a classmethod for this
369
+ # and _compile_re so we can continue to provide the module level function
370
+ # for backward compatibility by doing
371
+ # _make_boundary = Generator._make_boundary
372
+ # at the end of the module. It *is* internal, so we could drop that...
373
+ @classmethod
374
+ def _make_boundary(cls, text=None):
375
+ # Craft a random boundary. If text is given, ensure that the chosen
376
+ # boundary doesn't appear in the text.
377
+ token = random.randrange(sys.maxsize)
378
+ boundary = ('=' * 15) + (_fmt % token) + '=='
379
+ if text is None:
380
+ return boundary
381
+ b = boundary
382
+ counter = 0
383
+ while True:
384
+ cre = cls._compile_re('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
385
+ if not cre.search(text):
386
+ break
387
+ b = boundary + '.' + str(counter)
388
+ counter += 1
389
+ return b
390
+
391
+ @classmethod
392
+ def _compile_re(cls, s, flags):
393
+ return re.compile(s, flags)
394
+
395
+
396
+ class BytesGenerator(Generator):
397
+ """Generates a bytes version of a Message object tree.
398
+
399
+ Functionally identical to the base Generator except that the output is
400
+ bytes and not string. When surrogates were used in the input to encode
401
+ bytes, these are decoded back to bytes for output. If the policy has
402
+ cte_type set to 7bit, then the message is transformed such that the
403
+ non-ASCII bytes are properly content transfer encoded, using the charset
404
+ unknown-8bit.
405
+
406
+ The outfp object must accept bytes in its write method.
407
+ """
408
+
409
+ def write(self, s):
410
+ self._fp.write(s.encode('ascii', 'surrogateescape'))
411
+
412
+ def _new_buffer(self):
413
+ return BytesIO()
414
+
415
+ def _encode(self, s):
416
+ return s.encode('ascii')
417
+
418
+ def _write_headers(self, msg):
419
+ # This is almost the same as the string version, except for handling
420
+ # strings with 8bit bytes.
421
+ for h, v in msg.raw_items():
422
+ self._fp.write(self.policy.fold_binary(h, v))
423
+ # A blank line always separates headers from body
424
+ self.write(self._NL)
425
+
426
+ def _handle_text(self, msg):
427
+ # If the string has surrogates the original source was bytes, so
428
+ # just write it back out.
429
+ if msg._payload is None:
430
+ return
431
+ if _has_surrogates(msg._payload) and not self.policy.cte_type=='7bit':
432
+ if self._mangle_from_:
433
+ msg._payload = fcre.sub(">From ", msg._payload)
434
+ self._write_lines(msg._payload)
435
+ else:
436
+ super(BytesGenerator,self)._handle_text(msg)
437
+
438
+ # Default body handler
439
+ _writeBody = _handle_text
440
+
441
+ @classmethod
442
+ def _compile_re(cls, s, flags):
443
+ return re.compile(s.encode('ascii'), flags)
444
+
445
+
446
+
447
+ _FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]'
448
+
449
+ class DecodedGenerator(Generator):
450
+ """Generates a text representation of a message.
451
+
452
+ Like the Generator base class, except that non-text parts are substituted
453
+ with a format string representing the part.
454
+ """
455
+ def __init__(self, outfp, mangle_from_=None, maxheaderlen=None, fmt=None, *,
456
+ policy=None):
457
+ """Like Generator.__init__() except that an additional optional
458
+ argument is allowed.
459
+
460
+ Walks through all subparts of a message. If the subpart is of main
461
+ type `text', then it prints the decoded payload of the subpart.
462
+
463
+ Otherwise, fmt is a format string that is used instead of the message
464
+ payload. fmt is expanded with the following keywords (in
465
+ %(keyword)s format):
466
+
467
+ type : Full MIME type of the non-text part
468
+ maintype : Main MIME type of the non-text part
469
+ subtype : Sub-MIME type of the non-text part
470
+ filename : Filename of the non-text part
471
+ description: Description associated with the non-text part
472
+ encoding : Content transfer encoding of the non-text part
473
+
474
+ The default value for fmt is None, meaning
475
+
476
+ [Non-text (%(type)s) part of message omitted, filename %(filename)s]
477
+ """
478
+ Generator.__init__(self, outfp, mangle_from_, maxheaderlen,
479
+ policy=policy)
480
+ if fmt is None:
481
+ self._fmt = _FMT
482
+ else:
483
+ self._fmt = fmt
484
+
485
+ def _dispatch(self, msg):
486
+ for part in msg.walk():
487
+ maintype = part.get_content_maintype()
488
+ if maintype == 'text':
489
+ print(part.get_payload(decode=False), file=self)
490
+ elif maintype == 'multipart':
491
+ # Just skip this
492
+ pass
493
+ else:
494
+ print(self._fmt % {
495
+ 'type' : part.get_content_type(),
496
+ 'maintype' : part.get_content_maintype(),
497
+ 'subtype' : part.get_content_subtype(),
498
+ 'filename' : part.get_filename('[no filename]'),
499
+ 'description': part.get('Content-Description',
500
+ '[no description]'),
501
+ 'encoding' : part.get('Content-Transfer-Encoding',
502
+ '[no encoding]'),
503
+ }, file=self)
504
+
505
+
506
+
507
+ # Helper used by Generator._make_boundary
508
+ _width = len(repr(sys.maxsize-1))
509
+ _fmt = '%%0%dd' % _width
510
+
511
+ # Backward compatibility
512
+ _make_boundary = Generator._make_boundary
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/header.py ADDED
@@ -0,0 +1,578 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2002-2007 Python Software Foundation
2
+ # Author: Ben Gertzfield, Barry Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ """Header encoding and decoding functionality."""
6
+
7
+ __all__ = [
8
+ 'Header',
9
+ 'decode_header',
10
+ 'make_header',
11
+ ]
12
+
13
+ import re
14
+ import binascii
15
+
16
+ import email.quoprimime
17
+ import email.base64mime
18
+
19
+ from email.errors import HeaderParseError
20
+ from email import charset as _charset
21
+ Charset = _charset.Charset
22
+
23
+ NL = '\n'
24
+ SPACE = ' '
25
+ BSPACE = b' '
26
+ SPACE8 = ' ' * 8
27
+ EMPTYSTRING = ''
28
+ MAXLINELEN = 78
29
+ FWS = ' \t'
30
+
31
+ USASCII = Charset('us-ascii')
32
+ UTF8 = Charset('utf-8')
33
+
34
+ # Match encoded-word strings in the form =?charset?q?Hello_World?=
35
+ ecre = re.compile(r'''
36
+ =\? # literal =?
37
+ (?P<charset>[^?]*?) # non-greedy up to the next ? is the charset
38
+ \? # literal ?
39
+ (?P<encoding>[qQbB]) # either a "q" or a "b", case insensitive
40
+ \? # literal ?
41
+ (?P<encoded>.*?) # non-greedy up to the next ?= is the encoded string
42
+ \?= # literal ?=
43
+ ''', re.VERBOSE | re.MULTILINE)
44
+
45
+ # Field name regexp, including trailing colon, but not separating whitespace,
46
+ # according to RFC 2822. Character range is from tilde to exclamation mark.
47
+ # For use with .match()
48
+ fcre = re.compile(r'[\041-\176]+:$')
49
+
50
+ # Find a header embedded in a putative header value. Used to check for
51
+ # header injection attack.
52
+ _embedded_header = re.compile(r'\n[^ \t]+:')
53
+
54
+
55
+
56
+ # Helpers
57
+ _max_append = email.quoprimime._max_append
58
+
59
+
60
+
61
+ def decode_header(header):
62
+ """Decode a message header value without converting charset.
63
+
64
+ Returns a list of (string, charset) pairs containing each of the decoded
65
+ parts of the header. Charset is None for non-encoded parts of the header,
66
+ otherwise a lower-case string containing the name of the character set
67
+ specified in the encoded string.
68
+
69
+ header may be a string that may or may not contain RFC2047 encoded words,
70
+ or it may be a Header object.
71
+
72
+ An email.errors.HeaderParseError may be raised when certain decoding error
73
+ occurs (e.g. a base64 decoding exception).
74
+ """
75
+ # If it is a Header object, we can just return the encoded chunks.
76
+ if hasattr(header, '_chunks'):
77
+ return [(_charset._encode(string, str(charset)), str(charset))
78
+ for string, charset in header._chunks]
79
+ # If no encoding, just return the header with no charset.
80
+ if not ecre.search(header):
81
+ return [(header, None)]
82
+ # First step is to parse all the encoded parts into triplets of the form
83
+ # (encoded_string, encoding, charset). For unencoded strings, the last
84
+ # two parts will be None.
85
+ words = []
86
+ for line in header.splitlines():
87
+ parts = ecre.split(line)
88
+ first = True
89
+ while parts:
90
+ unencoded = parts.pop(0)
91
+ if first:
92
+ unencoded = unencoded.lstrip()
93
+ first = False
94
+ if unencoded:
95
+ words.append((unencoded, None, None))
96
+ if parts:
97
+ charset = parts.pop(0).lower()
98
+ encoding = parts.pop(0).lower()
99
+ encoded = parts.pop(0)
100
+ words.append((encoded, encoding, charset))
101
+ # Now loop over words and remove words that consist of whitespace
102
+ # between two encoded strings.
103
+ droplist = []
104
+ for n, w in enumerate(words):
105
+ if n>1 and w[1] and words[n-2][1] and words[n-1][0].isspace():
106
+ droplist.append(n-1)
107
+ for d in reversed(droplist):
108
+ del words[d]
109
+
110
+ # The next step is to decode each encoded word by applying the reverse
111
+ # base64 or quopri transformation. decoded_words is now a list of the
112
+ # form (decoded_word, charset).
113
+ decoded_words = []
114
+ for encoded_string, encoding, charset in words:
115
+ if encoding is None:
116
+ # This is an unencoded word.
117
+ decoded_words.append((encoded_string, charset))
118
+ elif encoding == 'q':
119
+ word = email.quoprimime.header_decode(encoded_string)
120
+ decoded_words.append((word, charset))
121
+ elif encoding == 'b':
122
+ paderr = len(encoded_string) % 4 # Postel's law: add missing padding
123
+ if paderr:
124
+ encoded_string += '==='[:4 - paderr]
125
+ try:
126
+ word = email.base64mime.decode(encoded_string)
127
+ except binascii.Error:
128
+ raise HeaderParseError('Base64 decoding error')
129
+ else:
130
+ decoded_words.append((word, charset))
131
+ else:
132
+ raise AssertionError('Unexpected encoding: ' + encoding)
133
+ # Now convert all words to bytes and collapse consecutive runs of
134
+ # similarly encoded words.
135
+ collapsed = []
136
+ last_word = last_charset = None
137
+ for word, charset in decoded_words:
138
+ if isinstance(word, str):
139
+ word = bytes(word, 'raw-unicode-escape')
140
+ if last_word is None:
141
+ last_word = word
142
+ last_charset = charset
143
+ elif charset != last_charset:
144
+ collapsed.append((last_word, last_charset))
145
+ last_word = word
146
+ last_charset = charset
147
+ elif last_charset is None:
148
+ last_word += BSPACE + word
149
+ else:
150
+ last_word += word
151
+ collapsed.append((last_word, last_charset))
152
+ return collapsed
153
+
154
+
155
+
156
+ def make_header(decoded_seq, maxlinelen=None, header_name=None,
157
+ continuation_ws=' '):
158
+ """Create a Header from a sequence of pairs as returned by decode_header()
159
+
160
+ decode_header() takes a header value string and returns a sequence of
161
+ pairs of the format (decoded_string, charset) where charset is the string
162
+ name of the character set.
163
+
164
+ This function takes one of those sequence of pairs and returns a Header
165
+ instance. Optional maxlinelen, header_name, and continuation_ws are as in
166
+ the Header constructor.
167
+ """
168
+ h = Header(maxlinelen=maxlinelen, header_name=header_name,
169
+ continuation_ws=continuation_ws)
170
+ for s, charset in decoded_seq:
171
+ # None means us-ascii but we can simply pass it on to h.append()
172
+ if charset is not None and not isinstance(charset, Charset):
173
+ charset = Charset(charset)
174
+ h.append(s, charset)
175
+ return h
176
+
177
+
178
+
179
+ class Header:
180
+ def __init__(self, s=None, charset=None,
181
+ maxlinelen=None, header_name=None,
182
+ continuation_ws=' ', errors='strict'):
183
+ """Create a MIME-compliant header that can contain many character sets.
184
+
185
+ Optional s is the initial header value. If None, the initial header
186
+ value is not set. You can later append to the header with .append()
187
+ method calls. s may be a byte string or a Unicode string, but see the
188
+ .append() documentation for semantics.
189
+
190
+ Optional charset serves two purposes: it has the same meaning as the
191
+ charset argument to the .append() method. It also sets the default
192
+ character set for all subsequent .append() calls that omit the charset
193
+ argument. If charset is not provided in the constructor, the us-ascii
194
+ charset is used both as s's initial charset and as the default for
195
+ subsequent .append() calls.
196
+
197
+ The maximum line length can be specified explicitly via maxlinelen. For
198
+ splitting the first line to a shorter value (to account for the field
199
+ header which isn't included in s, e.g. `Subject') pass in the name of
200
+ the field in header_name. The default maxlinelen is 78 as recommended
201
+ by RFC 2822.
202
+
203
+ continuation_ws must be RFC 2822 compliant folding whitespace (usually
204
+ either a space or a hard tab) which will be prepended to continuation
205
+ lines.
206
+
207
+ errors is passed through to the .append() call.
208
+ """
209
+ if charset is None:
210
+ charset = USASCII
211
+ elif not isinstance(charset, Charset):
212
+ charset = Charset(charset)
213
+ self._charset = charset
214
+ self._continuation_ws = continuation_ws
215
+ self._chunks = []
216
+ if s is not None:
217
+ self.append(s, charset, errors)
218
+ if maxlinelen is None:
219
+ maxlinelen = MAXLINELEN
220
+ self._maxlinelen = maxlinelen
221
+ if header_name is None:
222
+ self._headerlen = 0
223
+ else:
224
+ # Take the separating colon and space into account.
225
+ self._headerlen = len(header_name) + 2
226
+
227
+ def __str__(self):
228
+ """Return the string value of the header."""
229
+ self._normalize()
230
+ uchunks = []
231
+ lastcs = None
232
+ lastspace = None
233
+ for string, charset in self._chunks:
234
+ # We must preserve spaces between encoded and non-encoded word
235
+ # boundaries, which means for us we need to add a space when we go
236
+ # from a charset to None/us-ascii, or from None/us-ascii to a
237
+ # charset. Only do this for the second and subsequent chunks.
238
+ # Don't add a space if the None/us-ascii string already has
239
+ # a space (trailing or leading depending on transition)
240
+ nextcs = charset
241
+ if nextcs == _charset.UNKNOWN8BIT:
242
+ original_bytes = string.encode('ascii', 'surrogateescape')
243
+ string = original_bytes.decode('ascii', 'replace')
244
+ if uchunks:
245
+ hasspace = string and self._nonctext(string[0])
246
+ if lastcs not in (None, 'us-ascii'):
247
+ if nextcs in (None, 'us-ascii') and not hasspace:
248
+ uchunks.append(SPACE)
249
+ nextcs = None
250
+ elif nextcs not in (None, 'us-ascii') and not lastspace:
251
+ uchunks.append(SPACE)
252
+ lastspace = string and self._nonctext(string[-1])
253
+ lastcs = nextcs
254
+ uchunks.append(string)
255
+ return EMPTYSTRING.join(uchunks)
256
+
257
+ # Rich comparison operators for equality only. BAW: does it make sense to
258
+ # have or explicitly disable <, <=, >, >= operators?
259
+ def __eq__(self, other):
260
+ # other may be a Header or a string. Both are fine so coerce
261
+ # ourselves to a unicode (of the unencoded header value), swap the
262
+ # args and do another comparison.
263
+ return other == str(self)
264
+
265
+ def append(self, s, charset=None, errors='strict'):
266
+ """Append a string to the MIME header.
267
+
268
+ Optional charset, if given, should be a Charset instance or the name
269
+ of a character set (which will be converted to a Charset instance). A
270
+ value of None (the default) means that the charset given in the
271
+ constructor is used.
272
+
273
+ s may be a byte string or a Unicode string. If it is a byte string
274
+ (i.e. isinstance(s, str) is false), then charset is the encoding of
275
+ that byte string, and a UnicodeError will be raised if the string
276
+ cannot be decoded with that charset. If s is a Unicode string, then
277
+ charset is a hint specifying the character set of the characters in
278
+ the string. In either case, when producing an RFC 2822 compliant
279
+ header using RFC 2047 rules, the string will be encoded using the
280
+ output codec of the charset. If the string cannot be encoded to the
281
+ output codec, a UnicodeError will be raised.
282
+
283
+ Optional `errors' is passed as the errors argument to the decode
284
+ call if s is a byte string.
285
+ """
286
+ if charset is None:
287
+ charset = self._charset
288
+ elif not isinstance(charset, Charset):
289
+ charset = Charset(charset)
290
+ if not isinstance(s, str):
291
+ input_charset = charset.input_codec or 'us-ascii'
292
+ if input_charset == _charset.UNKNOWN8BIT:
293
+ s = s.decode('us-ascii', 'surrogateescape')
294
+ else:
295
+ s = s.decode(input_charset, errors)
296
+ # Ensure that the bytes we're storing can be decoded to the output
297
+ # character set, otherwise an early error is raised.
298
+ output_charset = charset.output_codec or 'us-ascii'
299
+ if output_charset != _charset.UNKNOWN8BIT:
300
+ try:
301
+ s.encode(output_charset, errors)
302
+ except UnicodeEncodeError:
303
+ if output_charset!='us-ascii':
304
+ raise
305
+ charset = UTF8
306
+ self._chunks.append((s, charset))
307
+
308
+ def _nonctext(self, s):
309
+ """True if string s is not a ctext character of RFC822.
310
+ """
311
+ return s.isspace() or s in ('(', ')', '\\')
312
+
313
+ def encode(self, splitchars=';, \t', maxlinelen=None, linesep='\n'):
314
+ r"""Encode a message header into an RFC-compliant format.
315
+
316
+ There are many issues involved in converting a given string for use in
317
+ an email header. Only certain character sets are readable in most
318
+ email clients, and as header strings can only contain a subset of
319
+ 7-bit ASCII, care must be taken to properly convert and encode (with
320
+ Base64 or quoted-printable) header strings. In addition, there is a
321
+ 75-character length limit on any given encoded header field, so
322
+ line-wrapping must be performed, even with double-byte character sets.
323
+
324
+ Optional maxlinelen specifies the maximum length of each generated
325
+ line, exclusive of the linesep string. Individual lines may be longer
326
+ than maxlinelen if a folding point cannot be found. The first line
327
+ will be shorter by the length of the header name plus ": " if a header
328
+ name was specified at Header construction time. The default value for
329
+ maxlinelen is determined at header construction time.
330
+
331
+ Optional splitchars is a string containing characters which should be
332
+ given extra weight by the splitting algorithm during normal header
333
+ wrapping. This is in very rough support of RFC 2822's `higher level
334
+ syntactic breaks': split points preceded by a splitchar are preferred
335
+ during line splitting, with the characters preferred in the order in
336
+ which they appear in the string. Space and tab may be included in the
337
+ string to indicate whether preference should be given to one over the
338
+ other as a split point when other split chars do not appear in the line
339
+ being split. Splitchars does not affect RFC 2047 encoded lines.
340
+
341
+ Optional linesep is a string to be used to separate the lines of
342
+ the value. The default value is the most useful for typical
343
+ Python applications, but it can be set to \r\n to produce RFC-compliant
344
+ line separators when needed.
345
+ """
346
+ self._normalize()
347
+ if maxlinelen is None:
348
+ maxlinelen = self._maxlinelen
349
+ # A maxlinelen of 0 means don't wrap. For all practical purposes,
350
+ # choosing a huge number here accomplishes that and makes the
351
+ # _ValueFormatter algorithm much simpler.
352
+ if maxlinelen == 0:
353
+ maxlinelen = 1000000
354
+ formatter = _ValueFormatter(self._headerlen, maxlinelen,
355
+ self._continuation_ws, splitchars)
356
+ lastcs = None
357
+ hasspace = lastspace = None
358
+ for string, charset in self._chunks:
359
+ if hasspace is not None:
360
+ hasspace = string and self._nonctext(string[0])
361
+ if lastcs not in (None, 'us-ascii'):
362
+ if not hasspace or charset not in (None, 'us-ascii'):
363
+ formatter.add_transition()
364
+ elif charset not in (None, 'us-ascii') and not lastspace:
365
+ formatter.add_transition()
366
+ lastspace = string and self._nonctext(string[-1])
367
+ lastcs = charset
368
+ hasspace = False
369
+ lines = string.splitlines()
370
+ if lines:
371
+ formatter.feed('', lines[0], charset)
372
+ else:
373
+ formatter.feed('', '', charset)
374
+ for line in lines[1:]:
375
+ formatter.newline()
376
+ if charset.header_encoding is not None:
377
+ formatter.feed(self._continuation_ws, ' ' + line.lstrip(),
378
+ charset)
379
+ else:
380
+ sline = line.lstrip()
381
+ fws = line[:len(line)-len(sline)]
382
+ formatter.feed(fws, sline, charset)
383
+ if len(lines) > 1:
384
+ formatter.newline()
385
+ if self._chunks:
386
+ formatter.add_transition()
387
+ value = formatter._str(linesep)
388
+ if _embedded_header.search(value):
389
+ raise HeaderParseError("header value appears to contain "
390
+ "an embedded header: {!r}".format(value))
391
+ return value
392
+
393
+ def _normalize(self):
394
+ # Step 1: Normalize the chunks so that all runs of identical charsets
395
+ # get collapsed into a single unicode string.
396
+ chunks = []
397
+ last_charset = None
398
+ last_chunk = []
399
+ for string, charset in self._chunks:
400
+ if charset == last_charset:
401
+ last_chunk.append(string)
402
+ else:
403
+ if last_charset is not None:
404
+ chunks.append((SPACE.join(last_chunk), last_charset))
405
+ last_chunk = [string]
406
+ last_charset = charset
407
+ if last_chunk:
408
+ chunks.append((SPACE.join(last_chunk), last_charset))
409
+ self._chunks = chunks
410
+
411
+
412
+
413
+ class _ValueFormatter:
414
+ def __init__(self, headerlen, maxlen, continuation_ws, splitchars):
415
+ self._maxlen = maxlen
416
+ self._continuation_ws = continuation_ws
417
+ self._continuation_ws_len = len(continuation_ws)
418
+ self._splitchars = splitchars
419
+ self._lines = []
420
+ self._current_line = _Accumulator(headerlen)
421
+
422
+ def _str(self, linesep):
423
+ self.newline()
424
+ return linesep.join(self._lines)
425
+
426
+ def __str__(self):
427
+ return self._str(NL)
428
+
429
+ def newline(self):
430
+ end_of_line = self._current_line.pop()
431
+ if end_of_line != (' ', ''):
432
+ self._current_line.push(*end_of_line)
433
+ if len(self._current_line) > 0:
434
+ if self._current_line.is_onlyws() and self._lines:
435
+ self._lines[-1] += str(self._current_line)
436
+ else:
437
+ self._lines.append(str(self._current_line))
438
+ self._current_line.reset()
439
+
440
+ def add_transition(self):
441
+ self._current_line.push(' ', '')
442
+
443
+ def feed(self, fws, string, charset):
444
+ # If the charset has no header encoding (i.e. it is an ASCII encoding)
445
+ # then we must split the header at the "highest level syntactic break"
446
+ # possible. Note that we don't have a lot of smarts about field
447
+ # syntax; we just try to break on semi-colons, then commas, then
448
+ # whitespace. Eventually, this should be pluggable.
449
+ if charset.header_encoding is None:
450
+ self._ascii_split(fws, string, self._splitchars)
451
+ return
452
+ # Otherwise, we're doing either a Base64 or a quoted-printable
453
+ # encoding which means we don't need to split the line on syntactic
454
+ # breaks. We can basically just find enough characters to fit on the
455
+ # current line, minus the RFC 2047 chrome. What makes this trickier
456
+ # though is that we have to split at octet boundaries, not character
457
+ # boundaries but it's only safe to split at character boundaries so at
458
+ # best we can only get close.
459
+ encoded_lines = charset.header_encode_lines(string, self._maxlengths())
460
+ # The first element extends the current line, but if it's None then
461
+ # nothing more fit on the current line so start a new line.
462
+ try:
463
+ first_line = encoded_lines.pop(0)
464
+ except IndexError:
465
+ # There are no encoded lines, so we're done.
466
+ return
467
+ if first_line is not None:
468
+ self._append_chunk(fws, first_line)
469
+ try:
470
+ last_line = encoded_lines.pop()
471
+ except IndexError:
472
+ # There was only one line.
473
+ return
474
+ self.newline()
475
+ self._current_line.push(self._continuation_ws, last_line)
476
+ # Everything else are full lines in themselves.
477
+ for line in encoded_lines:
478
+ self._lines.append(self._continuation_ws + line)
479
+
480
+ def _maxlengths(self):
481
+ # The first line's length.
482
+ yield self._maxlen - len(self._current_line)
483
+ while True:
484
+ yield self._maxlen - self._continuation_ws_len
485
+
486
+ def _ascii_split(self, fws, string, splitchars):
487
+ # The RFC 2822 header folding algorithm is simple in principle but
488
+ # complex in practice. Lines may be folded any place where "folding
489
+ # white space" appears by inserting a linesep character in front of the
490
+ # FWS. The complication is that not all spaces or tabs qualify as FWS,
491
+ # and we are also supposed to prefer to break at "higher level
492
+ # syntactic breaks". We can't do either of these without intimate
493
+ # knowledge of the structure of structured headers, which we don't have
494
+ # here. So the best we can do here is prefer to break at the specified
495
+ # splitchars, and hope that we don't choose any spaces or tabs that
496
+ # aren't legal FWS. (This is at least better than the old algorithm,
497
+ # where we would sometimes *introduce* FWS after a splitchar, or the
498
+ # algorithm before that, where we would turn all white space runs into
499
+ # single spaces or tabs.)
500
+ parts = re.split("(["+FWS+"]+)", fws+string)
501
+ if parts[0]:
502
+ parts[:0] = ['']
503
+ else:
504
+ parts.pop(0)
505
+ for fws, part in zip(*[iter(parts)]*2):
506
+ self._append_chunk(fws, part)
507
+
508
+ def _append_chunk(self, fws, string):
509
+ self._current_line.push(fws, string)
510
+ if len(self._current_line) > self._maxlen:
511
+ # Find the best split point, working backward from the end.
512
+ # There might be none, on a long first line.
513
+ for ch in self._splitchars:
514
+ for i in range(self._current_line.part_count()-1, 0, -1):
515
+ if ch.isspace():
516
+ fws = self._current_line[i][0]
517
+ if fws and fws[0]==ch:
518
+ break
519
+ prevpart = self._current_line[i-1][1]
520
+ if prevpart and prevpart[-1]==ch:
521
+ break
522
+ else:
523
+ continue
524
+ break
525
+ else:
526
+ fws, part = self._current_line.pop()
527
+ if self._current_line._initial_size > 0:
528
+ # There will be a header, so leave it on a line by itself.
529
+ self.newline()
530
+ if not fws:
531
+ # We don't use continuation_ws here because the whitespace
532
+ # after a header should always be a space.
533
+ fws = ' '
534
+ self._current_line.push(fws, part)
535
+ return
536
+ remainder = self._current_line.pop_from(i)
537
+ self._lines.append(str(self._current_line))
538
+ self._current_line.reset(remainder)
539
+
540
+
541
+ class _Accumulator(list):
542
+
543
+ def __init__(self, initial_size=0):
544
+ self._initial_size = initial_size
545
+ super().__init__()
546
+
547
+ def push(self, fws, string):
548
+ self.append((fws, string))
549
+
550
+ def pop_from(self, i=0):
551
+ popped = self[i:]
552
+ self[i:] = []
553
+ return popped
554
+
555
+ def pop(self):
556
+ if self.part_count()==0:
557
+ return ('', '')
558
+ return super().pop()
559
+
560
+ def __len__(self):
561
+ return sum((len(fws)+len(part) for fws, part in self),
562
+ self._initial_size)
563
+
564
+ def __str__(self):
565
+ return EMPTYSTRING.join((EMPTYSTRING.join((fws, part))
566
+ for fws, part in self))
567
+
568
+ def reset(self, startval=None):
569
+ if startval is None:
570
+ startval = []
571
+ self[:] = startval
572
+ self._initial_size = 0
573
+
574
+ def is_onlyws(self):
575
+ return self._initial_size==0 and (not self or str(self).isspace())
576
+
577
+ def part_count(self):
578
+ return super().__len__()
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/headerregistry.py ADDED
@@ -0,0 +1,607 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Representing and manipulating email headers via custom objects.
2
+
3
+ This module provides an implementation of the HeaderRegistry API.
4
+ The implementation is designed to flexibly follow RFC5322 rules.
5
+
6
+ Eventually HeaderRegistry will be a public API, but it isn't yet,
7
+ and will probably change some before that happens.
8
+
9
+ """
10
+ from types import MappingProxyType
11
+
12
+ from email import utils
13
+ from email import errors
14
+ from email import _header_value_parser as parser
15
+
16
+ class Address:
17
+
18
+ def __init__(self, display_name='', username='', domain='', addr_spec=None):
19
+ """Create an object representing a full email address.
20
+
21
+ An address can have a 'display_name', a 'username', and a 'domain'. In
22
+ addition to specifying the username and domain separately, they may be
23
+ specified together by using the addr_spec keyword *instead of* the
24
+ username and domain keywords. If an addr_spec string is specified it
25
+ must be properly quoted according to RFC 5322 rules; an error will be
26
+ raised if it is not.
27
+
28
+ An Address object has display_name, username, domain, and addr_spec
29
+ attributes, all of which are read-only. The addr_spec and the string
30
+ value of the object are both quoted according to RFC5322 rules, but
31
+ without any Content Transfer Encoding.
32
+
33
+ """
34
+
35
+ inputs = ''.join(filter(None, (display_name, username, domain, addr_spec)))
36
+ if '\r' in inputs or '\n' in inputs:
37
+ raise ValueError("invalid arguments; address parts cannot contain CR or LF")
38
+
39
+ # This clause with its potential 'raise' may only happen when an
40
+ # application program creates an Address object using an addr_spec
41
+ # keyword. The email library code itself must always supply username
42
+ # and domain.
43
+ if addr_spec is not None:
44
+ if username or domain:
45
+ raise TypeError("addrspec specified when username and/or "
46
+ "domain also specified")
47
+ a_s, rest = parser.get_addr_spec(addr_spec)
48
+ if rest:
49
+ raise ValueError("Invalid addr_spec; only '{}' "
50
+ "could be parsed from '{}'".format(
51
+ a_s, addr_spec))
52
+ if a_s.all_defects:
53
+ raise a_s.all_defects[0]
54
+ username = a_s.local_part
55
+ domain = a_s.domain
56
+ self._display_name = display_name
57
+ self._username = username
58
+ self._domain = domain
59
+
60
+ @property
61
+ def display_name(self):
62
+ return self._display_name
63
+
64
+ @property
65
+ def username(self):
66
+ return self._username
67
+
68
+ @property
69
+ def domain(self):
70
+ return self._domain
71
+
72
+ @property
73
+ def addr_spec(self):
74
+ """The addr_spec (username@domain) portion of the address, quoted
75
+ according to RFC 5322 rules, but with no Content Transfer Encoding.
76
+ """
77
+ nameset = set(self.username)
78
+ if len(nameset) > len(nameset-parser.DOT_ATOM_ENDS):
79
+ lp = parser.quote_string(self.username)
80
+ else:
81
+ lp = self.username
82
+ if self.domain:
83
+ return lp + '@' + self.domain
84
+ if not lp:
85
+ return '<>'
86
+ return lp
87
+
88
+ def __repr__(self):
89
+ return "{}(display_name={!r}, username={!r}, domain={!r})".format(
90
+ self.__class__.__name__,
91
+ self.display_name, self.username, self.domain)
92
+
93
+ def __str__(self):
94
+ nameset = set(self.display_name)
95
+ if len(nameset) > len(nameset-parser.SPECIALS):
96
+ disp = parser.quote_string(self.display_name)
97
+ else:
98
+ disp = self.display_name
99
+ if disp:
100
+ addr_spec = '' if self.addr_spec=='<>' else self.addr_spec
101
+ return "{} <{}>".format(disp, addr_spec)
102
+ return self.addr_spec
103
+
104
+ def __eq__(self, other):
105
+ if type(other) != type(self):
106
+ return False
107
+ return (self.display_name == other.display_name and
108
+ self.username == other.username and
109
+ self.domain == other.domain)
110
+
111
+
112
+ class Group:
113
+
114
+ def __init__(self, display_name=None, addresses=None):
115
+ """Create an object representing an address group.
116
+
117
+ An address group consists of a display_name followed by colon and a
118
+ list of addresses (see Address) terminated by a semi-colon. The Group
119
+ is created by specifying a display_name and a possibly empty list of
120
+ Address objects. A Group can also be used to represent a single
121
+ address that is not in a group, which is convenient when manipulating
122
+ lists that are a combination of Groups and individual Addresses. In
123
+ this case the display_name should be set to None. In particular, the
124
+ string representation of a Group whose display_name is None is the same
125
+ as the Address object, if there is one and only one Address object in
126
+ the addresses list.
127
+
128
+ """
129
+ self._display_name = display_name
130
+ self._addresses = tuple(addresses) if addresses else tuple()
131
+
132
+ @property
133
+ def display_name(self):
134
+ return self._display_name
135
+
136
+ @property
137
+ def addresses(self):
138
+ return self._addresses
139
+
140
+ def __repr__(self):
141
+ return "{}(display_name={!r}, addresses={!r}".format(
142
+ self.__class__.__name__,
143
+ self.display_name, self.addresses)
144
+
145
+ def __str__(self):
146
+ if self.display_name is None and len(self.addresses)==1:
147
+ return str(self.addresses[0])
148
+ disp = self.display_name
149
+ if disp is not None:
150
+ nameset = set(disp)
151
+ if len(nameset) > len(nameset-parser.SPECIALS):
152
+ disp = parser.quote_string(disp)
153
+ adrstr = ", ".join(str(x) for x in self.addresses)
154
+ adrstr = ' ' + adrstr if adrstr else adrstr
155
+ return "{}:{};".format(disp, adrstr)
156
+
157
+ def __eq__(self, other):
158
+ if type(other) != type(self):
159
+ return False
160
+ return (self.display_name == other.display_name and
161
+ self.addresses == other.addresses)
162
+
163
+
164
+ # Header Classes #
165
+
166
+ class BaseHeader(str):
167
+
168
+ """Base class for message headers.
169
+
170
+ Implements generic behavior and provides tools for subclasses.
171
+
172
+ A subclass must define a classmethod named 'parse' that takes an unfolded
173
+ value string and a dictionary as its arguments. The dictionary will
174
+ contain one key, 'defects', initialized to an empty list. After the call
175
+ the dictionary must contain two additional keys: parse_tree, set to the
176
+ parse tree obtained from parsing the header, and 'decoded', set to the
177
+ string value of the idealized representation of the data from the value.
178
+ (That is, encoded words are decoded, and values that have canonical
179
+ representations are so represented.)
180
+
181
+ The defects key is intended to collect parsing defects, which the message
182
+ parser will subsequently dispose of as appropriate. The parser should not,
183
+ insofar as practical, raise any errors. Defects should be added to the
184
+ list instead. The standard header parsers register defects for RFC
185
+ compliance issues, for obsolete RFC syntax, and for unrecoverable parsing
186
+ errors.
187
+
188
+ The parse method may add additional keys to the dictionary. In this case
189
+ the subclass must define an 'init' method, which will be passed the
190
+ dictionary as its keyword arguments. The method should use (usually by
191
+ setting them as the value of similarly named attributes) and remove all the
192
+ extra keys added by its parse method, and then use super to call its parent
193
+ class with the remaining arguments and keywords.
194
+
195
+ The subclass should also make sure that a 'max_count' attribute is defined
196
+ that is either None or 1. XXX: need to better define this API.
197
+
198
+ """
199
+
200
+ def __new__(cls, name, value):
201
+ kwds = {'defects': []}
202
+ cls.parse(value, kwds)
203
+ if utils._has_surrogates(kwds['decoded']):
204
+ kwds['decoded'] = utils._sanitize(kwds['decoded'])
205
+ self = str.__new__(cls, kwds['decoded'])
206
+ del kwds['decoded']
207
+ self.init(name, **kwds)
208
+ return self
209
+
210
+ def init(self, name, *, parse_tree, defects):
211
+ self._name = name
212
+ self._parse_tree = parse_tree
213
+ self._defects = defects
214
+
215
+ @property
216
+ def name(self):
217
+ return self._name
218
+
219
+ @property
220
+ def defects(self):
221
+ return tuple(self._defects)
222
+
223
+ def __reduce__(self):
224
+ return (
225
+ _reconstruct_header,
226
+ (
227
+ self.__class__.__name__,
228
+ self.__class__.__bases__,
229
+ str(self),
230
+ ),
231
+ self.__dict__)
232
+
233
+ @classmethod
234
+ def _reconstruct(cls, value):
235
+ return str.__new__(cls, value)
236
+
237
+ def fold(self, *, policy):
238
+ """Fold header according to policy.
239
+
240
+ The parsed representation of the header is folded according to
241
+ RFC5322 rules, as modified by the policy. If the parse tree
242
+ contains surrogateescaped bytes, the bytes are CTE encoded using
243
+ the charset 'unknown-8bit".
244
+
245
+ Any non-ASCII characters in the parse tree are CTE encoded using
246
+ charset utf-8. XXX: make this a policy setting.
247
+
248
+ The returned value is an ASCII-only string possibly containing linesep
249
+ characters, and ending with a linesep character. The string includes
250
+ the header name and the ': ' separator.
251
+
252
+ """
253
+ # At some point we need to put fws here if it was in the source.
254
+ header = parser.Header([
255
+ parser.HeaderLabel([
256
+ parser.ValueTerminal(self.name, 'header-name'),
257
+ parser.ValueTerminal(':', 'header-sep')]),
258
+ ])
259
+ if self._parse_tree:
260
+ header.append(
261
+ parser.CFWSList([parser.WhiteSpaceTerminal(' ', 'fws')]))
262
+ header.append(self._parse_tree)
263
+ return header.fold(policy=policy)
264
+
265
+
266
+ def _reconstruct_header(cls_name, bases, value):
267
+ return type(cls_name, bases, {})._reconstruct(value)
268
+
269
+
270
+ class UnstructuredHeader:
271
+
272
+ max_count = None
273
+ value_parser = staticmethod(parser.get_unstructured)
274
+
275
+ @classmethod
276
+ def parse(cls, value, kwds):
277
+ kwds['parse_tree'] = cls.value_parser(value)
278
+ kwds['decoded'] = str(kwds['parse_tree'])
279
+
280
+
281
+ class UniqueUnstructuredHeader(UnstructuredHeader):
282
+
283
+ max_count = 1
284
+
285
+
286
+ class DateHeader:
287
+
288
+ """Header whose value consists of a single timestamp.
289
+
290
+ Provides an additional attribute, datetime, which is either an aware
291
+ datetime using a timezone, or a naive datetime if the timezone
292
+ in the input string is -0000. Also accepts a datetime as input.
293
+ The 'value' attribute is the normalized form of the timestamp,
294
+ which means it is the output of format_datetime on the datetime.
295
+ """
296
+
297
+ max_count = None
298
+
299
+ # This is used only for folding, not for creating 'decoded'.
300
+ value_parser = staticmethod(parser.get_unstructured)
301
+
302
+ @classmethod
303
+ def parse(cls, value, kwds):
304
+ if not value:
305
+ kwds['defects'].append(errors.HeaderMissingRequiredValue())
306
+ kwds['datetime'] = None
307
+ kwds['decoded'] = ''
308
+ kwds['parse_tree'] = parser.TokenList()
309
+ return
310
+ if isinstance(value, str):
311
+ value = utils.parsedate_to_datetime(value)
312
+ kwds['datetime'] = value
313
+ kwds['decoded'] = utils.format_datetime(kwds['datetime'])
314
+ kwds['parse_tree'] = cls.value_parser(kwds['decoded'])
315
+
316
+ def init(self, *args, **kw):
317
+ self._datetime = kw.pop('datetime')
318
+ super().init(*args, **kw)
319
+
320
+ @property
321
+ def datetime(self):
322
+ return self._datetime
323
+
324
+
325
+ class UniqueDateHeader(DateHeader):
326
+
327
+ max_count = 1
328
+
329
+
330
+ class AddressHeader:
331
+
332
+ max_count = None
333
+
334
+ @staticmethod
335
+ def value_parser(value):
336
+ address_list, value = parser.get_address_list(value)
337
+ assert not value, 'this should not happen'
338
+ return address_list
339
+
340
+ @classmethod
341
+ def parse(cls, value, kwds):
342
+ if isinstance(value, str):
343
+ # We are translating here from the RFC language (address/mailbox)
344
+ # to our API language (group/address).
345
+ kwds['parse_tree'] = address_list = cls.value_parser(value)
346
+ groups = []
347
+ for addr in address_list.addresses:
348
+ groups.append(Group(addr.display_name,
349
+ [Address(mb.display_name or '',
350
+ mb.local_part or '',
351
+ mb.domain or '')
352
+ for mb in addr.all_mailboxes]))
353
+ defects = list(address_list.all_defects)
354
+ else:
355
+ # Assume it is Address/Group stuff
356
+ if not hasattr(value, '__iter__'):
357
+ value = [value]
358
+ groups = [Group(None, [item]) if not hasattr(item, 'addresses')
359
+ else item
360
+ for item in value]
361
+ defects = []
362
+ kwds['groups'] = groups
363
+ kwds['defects'] = defects
364
+ kwds['decoded'] = ', '.join([str(item) for item in groups])
365
+ if 'parse_tree' not in kwds:
366
+ kwds['parse_tree'] = cls.value_parser(kwds['decoded'])
367
+
368
+ def init(self, *args, **kw):
369
+ self._groups = tuple(kw.pop('groups'))
370
+ self._addresses = None
371
+ super().init(*args, **kw)
372
+
373
+ @property
374
+ def groups(self):
375
+ return self._groups
376
+
377
+ @property
378
+ def addresses(self):
379
+ if self._addresses is None:
380
+ self._addresses = tuple(address for group in self._groups
381
+ for address in group.addresses)
382
+ return self._addresses
383
+
384
+
385
+ class UniqueAddressHeader(AddressHeader):
386
+
387
+ max_count = 1
388
+
389
+
390
+ class SingleAddressHeader(AddressHeader):
391
+
392
+ @property
393
+ def address(self):
394
+ if len(self.addresses)!=1:
395
+ raise ValueError(("value of single address header {} is not "
396
+ "a single address").format(self.name))
397
+ return self.addresses[0]
398
+
399
+
400
+ class UniqueSingleAddressHeader(SingleAddressHeader):
401
+
402
+ max_count = 1
403
+
404
+
405
+ class MIMEVersionHeader:
406
+
407
+ max_count = 1
408
+
409
+ value_parser = staticmethod(parser.parse_mime_version)
410
+
411
+ @classmethod
412
+ def parse(cls, value, kwds):
413
+ kwds['parse_tree'] = parse_tree = cls.value_parser(value)
414
+ kwds['decoded'] = str(parse_tree)
415
+ kwds['defects'].extend(parse_tree.all_defects)
416
+ kwds['major'] = None if parse_tree.minor is None else parse_tree.major
417
+ kwds['minor'] = parse_tree.minor
418
+ if parse_tree.minor is not None:
419
+ kwds['version'] = '{}.{}'.format(kwds['major'], kwds['minor'])
420
+ else:
421
+ kwds['version'] = None
422
+
423
+ def init(self, *args, **kw):
424
+ self._version = kw.pop('version')
425
+ self._major = kw.pop('major')
426
+ self._minor = kw.pop('minor')
427
+ super().init(*args, **kw)
428
+
429
+ @property
430
+ def major(self):
431
+ return self._major
432
+
433
+ @property
434
+ def minor(self):
435
+ return self._minor
436
+
437
+ @property
438
+ def version(self):
439
+ return self._version
440
+
441
+
442
+ class ParameterizedMIMEHeader:
443
+
444
+ # Mixin that handles the params dict. Must be subclassed and
445
+ # a property value_parser for the specific header provided.
446
+
447
+ max_count = 1
448
+
449
+ @classmethod
450
+ def parse(cls, value, kwds):
451
+ kwds['parse_tree'] = parse_tree = cls.value_parser(value)
452
+ kwds['decoded'] = str(parse_tree)
453
+ kwds['defects'].extend(parse_tree.all_defects)
454
+ if parse_tree.params is None:
455
+ kwds['params'] = {}
456
+ else:
457
+ # The MIME RFCs specify that parameter ordering is arbitrary.
458
+ kwds['params'] = {utils._sanitize(name).lower():
459
+ utils._sanitize(value)
460
+ for name, value in parse_tree.params}
461
+
462
+ def init(self, *args, **kw):
463
+ self._params = kw.pop('params')
464
+ super().init(*args, **kw)
465
+
466
+ @property
467
+ def params(self):
468
+ return MappingProxyType(self._params)
469
+
470
+
471
+ class ContentTypeHeader(ParameterizedMIMEHeader):
472
+
473
+ value_parser = staticmethod(parser.parse_content_type_header)
474
+
475
+ def init(self, *args, **kw):
476
+ super().init(*args, **kw)
477
+ self._maintype = utils._sanitize(self._parse_tree.maintype)
478
+ self._subtype = utils._sanitize(self._parse_tree.subtype)
479
+
480
+ @property
481
+ def maintype(self):
482
+ return self._maintype
483
+
484
+ @property
485
+ def subtype(self):
486
+ return self._subtype
487
+
488
+ @property
489
+ def content_type(self):
490
+ return self.maintype + '/' + self.subtype
491
+
492
+
493
+ class ContentDispositionHeader(ParameterizedMIMEHeader):
494
+
495
+ value_parser = staticmethod(parser.parse_content_disposition_header)
496
+
497
+ def init(self, *args, **kw):
498
+ super().init(*args, **kw)
499
+ cd = self._parse_tree.content_disposition
500
+ self._content_disposition = cd if cd is None else utils._sanitize(cd)
501
+
502
+ @property
503
+ def content_disposition(self):
504
+ return self._content_disposition
505
+
506
+
507
+ class ContentTransferEncodingHeader:
508
+
509
+ max_count = 1
510
+
511
+ value_parser = staticmethod(parser.parse_content_transfer_encoding_header)
512
+
513
+ @classmethod
514
+ def parse(cls, value, kwds):
515
+ kwds['parse_tree'] = parse_tree = cls.value_parser(value)
516
+ kwds['decoded'] = str(parse_tree)
517
+ kwds['defects'].extend(parse_tree.all_defects)
518
+
519
+ def init(self, *args, **kw):
520
+ super().init(*args, **kw)
521
+ self._cte = utils._sanitize(self._parse_tree.cte)
522
+
523
+ @property
524
+ def cte(self):
525
+ return self._cte
526
+
527
+
528
+ class MessageIDHeader:
529
+
530
+ max_count = 1
531
+ value_parser = staticmethod(parser.parse_message_id)
532
+
533
+ @classmethod
534
+ def parse(cls, value, kwds):
535
+ kwds['parse_tree'] = parse_tree = cls.value_parser(value)
536
+ kwds['decoded'] = str(parse_tree)
537
+ kwds['defects'].extend(parse_tree.all_defects)
538
+
539
+
540
+ # The header factory #
541
+
542
+ _default_header_map = {
543
+ 'subject': UniqueUnstructuredHeader,
544
+ 'date': UniqueDateHeader,
545
+ 'resent-date': DateHeader,
546
+ 'orig-date': UniqueDateHeader,
547
+ 'sender': UniqueSingleAddressHeader,
548
+ 'resent-sender': SingleAddressHeader,
549
+ 'to': UniqueAddressHeader,
550
+ 'resent-to': AddressHeader,
551
+ 'cc': UniqueAddressHeader,
552
+ 'resent-cc': AddressHeader,
553
+ 'bcc': UniqueAddressHeader,
554
+ 'resent-bcc': AddressHeader,
555
+ 'from': UniqueAddressHeader,
556
+ 'resent-from': AddressHeader,
557
+ 'reply-to': UniqueAddressHeader,
558
+ 'mime-version': MIMEVersionHeader,
559
+ 'content-type': ContentTypeHeader,
560
+ 'content-disposition': ContentDispositionHeader,
561
+ 'content-transfer-encoding': ContentTransferEncodingHeader,
562
+ 'message-id': MessageIDHeader,
563
+ }
564
+
565
+ class HeaderRegistry:
566
+
567
+ """A header_factory and header registry."""
568
+
569
+ def __init__(self, base_class=BaseHeader, default_class=UnstructuredHeader,
570
+ use_default_map=True):
571
+ """Create a header_factory that works with the Policy API.
572
+
573
+ base_class is the class that will be the last class in the created
574
+ header class's __bases__ list. default_class is the class that will be
575
+ used if "name" (see __call__) does not appear in the registry.
576
+ use_default_map controls whether or not the default mapping of names to
577
+ specialized classes is copied in to the registry when the factory is
578
+ created. The default is True.
579
+
580
+ """
581
+ self.registry = {}
582
+ self.base_class = base_class
583
+ self.default_class = default_class
584
+ if use_default_map:
585
+ self.registry.update(_default_header_map)
586
+
587
+ def map_to_type(self, name, cls):
588
+ """Register cls as the specialized class for handling "name" headers.
589
+
590
+ """
591
+ self.registry[name.lower()] = cls
592
+
593
+ def __getitem__(self, name):
594
+ cls = self.registry.get(name.lower(), self.default_class)
595
+ return type('_'+cls.__name__, (cls, self.base_class), {})
596
+
597
+ def __call__(self, name, value):
598
+ """Create a header instance for header 'name' from 'value'.
599
+
600
+ Creates a header instance by creating a specialized class for parsing
601
+ and representing the specified header by combining the factory
602
+ base_class with a specialized class from the registry or the
603
+ default_class, and passing the name and value to the constructed
604
+ class's constructor.
605
+
606
+ """
607
+ return self[name](name, value)
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/iterators.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2006 Python Software Foundation
2
+ # Author: Barry Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ """Various types of useful iterators and generators."""
6
+
7
+ __all__ = [
8
+ 'body_line_iterator',
9
+ 'typed_subpart_iterator',
10
+ 'walk',
11
+ # Do not include _structure() since it's part of the debugging API.
12
+ ]
13
+
14
+ import sys
15
+ from io import StringIO
16
+
17
+
18
+
19
+ # This function will become a method of the Message class
20
+ def walk(self):
21
+ """Walk over the message tree, yielding each subpart.
22
+
23
+ The walk is performed in depth-first order. This method is a
24
+ generator.
25
+ """
26
+ yield self
27
+ if self.is_multipart():
28
+ for subpart in self.get_payload():
29
+ yield from subpart.walk()
30
+
31
+
32
+
33
+ # These two functions are imported into the Iterators.py interface module.
34
+ def body_line_iterator(msg, decode=False):
35
+ """Iterate over the parts, returning string payloads line-by-line.
36
+
37
+ Optional decode (default False) is passed through to .get_payload().
38
+ """
39
+ for subpart in msg.walk():
40
+ payload = subpart.get_payload(decode=decode)
41
+ if isinstance(payload, str):
42
+ yield from StringIO(payload)
43
+
44
+
45
+ def typed_subpart_iterator(msg, maintype='text', subtype=None):
46
+ """Iterate over the subparts with a given MIME type.
47
+
48
+ Use `maintype' as the main MIME type to match against; this defaults to
49
+ "text". Optional `subtype' is the MIME subtype to match against; if
50
+ omitted, only the main type is matched.
51
+ """
52
+ for subpart in msg.walk():
53
+ if subpart.get_content_maintype() == maintype:
54
+ if subtype is None or subpart.get_content_subtype() == subtype:
55
+ yield subpart
56
+
57
+
58
+
59
+ def _structure(msg, fp=None, level=0, include_default=False):
60
+ """A handy debugging aid"""
61
+ if fp is None:
62
+ fp = sys.stdout
63
+ tab = ' ' * (level * 4)
64
+ print(tab + msg.get_content_type(), end='', file=fp)
65
+ if include_default:
66
+ print(' [%s]' % msg.get_default_type(), file=fp)
67
+ else:
68
+ print(file=fp)
69
+ if msg.is_multipart():
70
+ for subpart in msg.get_payload():
71
+ _structure(subpart, fp, level+1, include_default)
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/message.py ADDED
@@ -0,0 +1,1173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2007 Python Software Foundation
2
+ # Author: Barry Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ """Basic message object for the email package object model."""
6
+
7
+ __all__ = ['Message', 'EmailMessage']
8
+
9
+ import re
10
+ import uu
11
+ import quopri
12
+ from io import BytesIO, StringIO
13
+
14
+ # Intrapackage imports
15
+ from email import utils
16
+ from email import errors
17
+ from email._policybase import Policy, compat32
18
+ from email import charset as _charset
19
+ from email._encoded_words import decode_b
20
+ Charset = _charset.Charset
21
+
22
+ SEMISPACE = '; '
23
+
24
+ # Regular expression that matches `special' characters in parameters, the
25
+ # existence of which force quoting of the parameter value.
26
+ tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
27
+
28
+
29
+ def _splitparam(param):
30
+ # Split header parameters. BAW: this may be too simple. It isn't
31
+ # strictly RFC 2045 (section 5.1) compliant, but it catches most headers
32
+ # found in the wild. We may eventually need a full fledged parser.
33
+ # RDM: we might have a Header here; for now just stringify it.
34
+ a, sep, b = str(param).partition(';')
35
+ if not sep:
36
+ return a.strip(), None
37
+ return a.strip(), b.strip()
38
+
39
+ def _formatparam(param, value=None, quote=True):
40
+ """Convenience function to format and return a key=value pair.
41
+
42
+ This will quote the value if needed or if quote is true. If value is a
43
+ three tuple (charset, language, value), it will be encoded according
44
+ to RFC2231 rules. If it contains non-ascii characters it will likewise
45
+ be encoded according to RFC2231 rules, using the utf-8 charset and
46
+ a null language.
47
+ """
48
+ if value is not None and len(value) > 0:
49
+ # A tuple is used for RFC 2231 encoded parameter values where items
50
+ # are (charset, language, value). charset is a string, not a Charset
51
+ # instance. RFC 2231 encoded values are never quoted, per RFC.
52
+ if isinstance(value, tuple):
53
+ # Encode as per RFC 2231
54
+ param += '*'
55
+ value = utils.encode_rfc2231(value[2], value[0], value[1])
56
+ return '%s=%s' % (param, value)
57
+ else:
58
+ try:
59
+ value.encode('ascii')
60
+ except UnicodeEncodeError:
61
+ param += '*'
62
+ value = utils.encode_rfc2231(value, 'utf-8', '')
63
+ return '%s=%s' % (param, value)
64
+ # BAW: Please check this. I think that if quote is set it should
65
+ # force quoting even if not necessary.
66
+ if quote or tspecials.search(value):
67
+ return '%s="%s"' % (param, utils.quote(value))
68
+ else:
69
+ return '%s=%s' % (param, value)
70
+ else:
71
+ return param
72
+
73
+ def _parseparam(s):
74
+ # RDM This might be a Header, so for now stringify it.
75
+ s = ';' + str(s)
76
+ plist = []
77
+ while s[:1] == ';':
78
+ s = s[1:]
79
+ end = s.find(';')
80
+ while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
81
+ end = s.find(';', end + 1)
82
+ if end < 0:
83
+ end = len(s)
84
+ f = s[:end]
85
+ if '=' in f:
86
+ i = f.index('=')
87
+ f = f[:i].strip().lower() + '=' + f[i+1:].strip()
88
+ plist.append(f.strip())
89
+ s = s[end:]
90
+ return plist
91
+
92
+
93
+ def _unquotevalue(value):
94
+ # This is different than utils.collapse_rfc2231_value() because it doesn't
95
+ # try to convert the value to a unicode. Message.get_param() and
96
+ # Message.get_params() are both currently defined to return the tuple in
97
+ # the face of RFC 2231 parameters.
98
+ if isinstance(value, tuple):
99
+ return value[0], value[1], utils.unquote(value[2])
100
+ else:
101
+ return utils.unquote(value)
102
+
103
+
104
+
105
+ class Message:
106
+ """Basic message object.
107
+
108
+ A message object is defined as something that has a bunch of RFC 2822
109
+ headers and a payload. It may optionally have an envelope header
110
+ (a.k.a. Unix-From or From_ header). If the message is a container (i.e. a
111
+ multipart or a message/rfc822), then the payload is a list of Message
112
+ objects, otherwise it is a string.
113
+
114
+ Message objects implement part of the `mapping' interface, which assumes
115
+ there is exactly one occurrence of the header per message. Some headers
116
+ do in fact appear multiple times (e.g. Received) and for those headers,
117
+ you must use the explicit API to set or get all the headers. Not all of
118
+ the mapping methods are implemented.
119
+ """
120
+ def __init__(self, policy=compat32):
121
+ self.policy = policy
122
+ self._headers = []
123
+ self._unixfrom = None
124
+ self._payload = None
125
+ self._charset = None
126
+ # Defaults for multipart messages
127
+ self.preamble = self.epilogue = None
128
+ self.defects = []
129
+ # Default content type
130
+ self._default_type = 'text/plain'
131
+
132
+ def __str__(self):
133
+ """Return the entire formatted message as a string.
134
+ """
135
+ return self.as_string()
136
+
137
+ def as_string(self, unixfrom=False, maxheaderlen=0, policy=None):
138
+ """Return the entire formatted message as a string.
139
+
140
+ Optional 'unixfrom', when true, means include the Unix From_ envelope
141
+ header. For backward compatibility reasons, if maxheaderlen is
142
+ not specified it defaults to 0, so you must override it explicitly
143
+ if you want a different maxheaderlen. 'policy' is passed to the
144
+ Generator instance used to serialize the message; if it is not
145
+ specified the policy associated with the message instance is used.
146
+
147
+ If the message object contains binary data that is not encoded
148
+ according to RFC standards, the non-compliant data will be replaced by
149
+ unicode "unknown character" code points.
150
+ """
151
+ from email.generator import Generator
152
+ policy = self.policy if policy is None else policy
153
+ fp = StringIO()
154
+ g = Generator(fp,
155
+ mangle_from_=False,
156
+ maxheaderlen=maxheaderlen,
157
+ policy=policy)
158
+ g.flatten(self, unixfrom=unixfrom)
159
+ return fp.getvalue()
160
+
161
+ def __bytes__(self):
162
+ """Return the entire formatted message as a bytes object.
163
+ """
164
+ return self.as_bytes()
165
+
166
+ def as_bytes(self, unixfrom=False, policy=None):
167
+ """Return the entire formatted message as a bytes object.
168
+
169
+ Optional 'unixfrom', when true, means include the Unix From_ envelope
170
+ header. 'policy' is passed to the BytesGenerator instance used to
171
+ serialize the message; if not specified the policy associated with
172
+ the message instance is used.
173
+ """
174
+ from email.generator import BytesGenerator
175
+ policy = self.policy if policy is None else policy
176
+ fp = BytesIO()
177
+ g = BytesGenerator(fp, mangle_from_=False, policy=policy)
178
+ g.flatten(self, unixfrom=unixfrom)
179
+ return fp.getvalue()
180
+
181
+ def is_multipart(self):
182
+ """Return True if the message consists of multiple parts."""
183
+ return isinstance(self._payload, list)
184
+
185
+ #
186
+ # Unix From_ line
187
+ #
188
+ def set_unixfrom(self, unixfrom):
189
+ self._unixfrom = unixfrom
190
+
191
+ def get_unixfrom(self):
192
+ return self._unixfrom
193
+
194
+ #
195
+ # Payload manipulation.
196
+ #
197
+ def attach(self, payload):
198
+ """Add the given payload to the current payload.
199
+
200
+ The current payload will always be a list of objects after this method
201
+ is called. If you want to set the payload to a scalar object, use
202
+ set_payload() instead.
203
+ """
204
+ if self._payload is None:
205
+ self._payload = [payload]
206
+ else:
207
+ try:
208
+ self._payload.append(payload)
209
+ except AttributeError:
210
+ raise TypeError("Attach is not valid on a message with a"
211
+ " non-multipart payload")
212
+
213
+ def get_payload(self, i=None, decode=False):
214
+ """Return a reference to the payload.
215
+
216
+ The payload will either be a list object or a string. If you mutate
217
+ the list object, you modify the message's payload in place. Optional
218
+ i returns that index into the payload.
219
+
220
+ Optional decode is a flag indicating whether the payload should be
221
+ decoded or not, according to the Content-Transfer-Encoding header
222
+ (default is False).
223
+
224
+ When True and the message is not a multipart, the payload will be
225
+ decoded if this header's value is `quoted-printable' or `base64'. If
226
+ some other encoding is used, or the header is missing, or if the
227
+ payload has bogus data (i.e. bogus base64 or uuencoded data), the
228
+ payload is returned as-is.
229
+
230
+ If the message is a multipart and the decode flag is True, then None
231
+ is returned.
232
+ """
233
+ # Here is the logic table for this code, based on the email5.0.0 code:
234
+ # i decode is_multipart result
235
+ # ------ ------ ------------ ------------------------------
236
+ # None True True None
237
+ # i True True None
238
+ # None False True _payload (a list)
239
+ # i False True _payload element i (a Message)
240
+ # i False False error (not a list)
241
+ # i True False error (not a list)
242
+ # None False False _payload
243
+ # None True False _payload decoded (bytes)
244
+ # Note that Barry planned to factor out the 'decode' case, but that
245
+ # isn't so easy now that we handle the 8 bit data, which needs to be
246
+ # converted in both the decode and non-decode path.
247
+ if self.is_multipart():
248
+ if decode:
249
+ return None
250
+ if i is None:
251
+ return self._payload
252
+ else:
253
+ return self._payload[i]
254
+ # For backward compatibility, Use isinstance and this error message
255
+ # instead of the more logical is_multipart test.
256
+ if i is not None and not isinstance(self._payload, list):
257
+ raise TypeError('Expected list, got %s' % type(self._payload))
258
+ payload = self._payload
259
+ # cte might be a Header, so for now stringify it.
260
+ cte = str(self.get('content-transfer-encoding', '')).lower()
261
+ # payload may be bytes here.
262
+ if isinstance(payload, str):
263
+ if utils._has_surrogates(payload):
264
+ bpayload = payload.encode('ascii', 'surrogateescape')
265
+ if not decode:
266
+ try:
267
+ payload = bpayload.decode(self.get_param('charset', 'ascii'), 'replace')
268
+ except LookupError:
269
+ payload = bpayload.decode('ascii', 'replace')
270
+ elif decode:
271
+ try:
272
+ bpayload = payload.encode('ascii')
273
+ except UnicodeError:
274
+ # This won't happen for RFC compliant messages (messages
275
+ # containing only ASCII code points in the unicode input).
276
+ # If it does happen, turn the string into bytes in a way
277
+ # guaranteed not to fail.
278
+ bpayload = payload.encode('raw-unicode-escape')
279
+ if not decode:
280
+ return payload
281
+ if cte == 'quoted-printable':
282
+ return quopri.decodestring(bpayload)
283
+ elif cte == 'base64':
284
+ # XXX: this is a bit of a hack; decode_b should probably be factored
285
+ # out somewhere, but I haven't figured out where yet.
286
+ value, defects = decode_b(b''.join(bpayload.splitlines()))
287
+ for defect in defects:
288
+ self.policy.handle_defect(self, defect)
289
+ return value
290
+ elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'):
291
+ in_file = BytesIO(bpayload)
292
+ out_file = BytesIO()
293
+ try:
294
+ uu.decode(in_file, out_file, quiet=True)
295
+ return out_file.getvalue()
296
+ except uu.Error:
297
+ # Some decoding problem
298
+ return bpayload
299
+ if isinstance(payload, str):
300
+ return bpayload
301
+ return payload
302
+
303
+ def set_payload(self, payload, charset=None):
304
+ """Set the payload to the given value.
305
+
306
+ Optional charset sets the message's default character set. See
307
+ set_charset() for details.
308
+ """
309
+ if hasattr(payload, 'encode'):
310
+ if charset is None:
311
+ self._payload = payload
312
+ return
313
+ if not isinstance(charset, Charset):
314
+ charset = Charset(charset)
315
+ payload = payload.encode(charset.output_charset)
316
+ if hasattr(payload, 'decode'):
317
+ self._payload = payload.decode('ascii', 'surrogateescape')
318
+ else:
319
+ self._payload = payload
320
+ if charset is not None:
321
+ self.set_charset(charset)
322
+
323
+ def set_charset(self, charset):
324
+ """Set the charset of the payload to a given character set.
325
+
326
+ charset can be a Charset instance, a string naming a character set, or
327
+ None. If it is a string it will be converted to a Charset instance.
328
+ If charset is None, the charset parameter will be removed from the
329
+ Content-Type field. Anything else will generate a TypeError.
330
+
331
+ The message will be assumed to be of type text/* encoded with
332
+ charset.input_charset. It will be converted to charset.output_charset
333
+ and encoded properly, if needed, when generating the plain text
334
+ representation of the message. MIME headers (MIME-Version,
335
+ Content-Type, Content-Transfer-Encoding) will be added as needed.
336
+ """
337
+ if charset is None:
338
+ self.del_param('charset')
339
+ self._charset = None
340
+ return
341
+ if not isinstance(charset, Charset):
342
+ charset = Charset(charset)
343
+ self._charset = charset
344
+ if 'MIME-Version' not in self:
345
+ self.add_header('MIME-Version', '1.0')
346
+ if 'Content-Type' not in self:
347
+ self.add_header('Content-Type', 'text/plain',
348
+ charset=charset.get_output_charset())
349
+ else:
350
+ self.set_param('charset', charset.get_output_charset())
351
+ if charset != charset.get_output_charset():
352
+ self._payload = charset.body_encode(self._payload)
353
+ if 'Content-Transfer-Encoding' not in self:
354
+ cte = charset.get_body_encoding()
355
+ try:
356
+ cte(self)
357
+ except TypeError:
358
+ # This 'if' is for backward compatibility, it allows unicode
359
+ # through even though that won't work correctly if the
360
+ # message is serialized.
361
+ payload = self._payload
362
+ if payload:
363
+ try:
364
+ payload = payload.encode('ascii', 'surrogateescape')
365
+ except UnicodeError:
366
+ payload = payload.encode(charset.output_charset)
367
+ self._payload = charset.body_encode(payload)
368
+ self.add_header('Content-Transfer-Encoding', cte)
369
+
370
+ def get_charset(self):
371
+ """Return the Charset instance associated with the message's payload.
372
+ """
373
+ return self._charset
374
+
375
+ #
376
+ # MAPPING INTERFACE (partial)
377
+ #
378
+ def __len__(self):
379
+ """Return the total number of headers, including duplicates."""
380
+ return len(self._headers)
381
+
382
+ def __getitem__(self, name):
383
+ """Get a header value.
384
+
385
+ Return None if the header is missing instead of raising an exception.
386
+
387
+ Note that if the header appeared multiple times, exactly which
388
+ occurrence gets returned is undefined. Use get_all() to get all
389
+ the values matching a header field name.
390
+ """
391
+ return self.get(name)
392
+
393
+ def __setitem__(self, name, val):
394
+ """Set the value of a header.
395
+
396
+ Note: this does not overwrite an existing header with the same field
397
+ name. Use __delitem__() first to delete any existing headers.
398
+ """
399
+ max_count = self.policy.header_max_count(name)
400
+ if max_count:
401
+ lname = name.lower()
402
+ found = 0
403
+ for k, v in self._headers:
404
+ if k.lower() == lname:
405
+ found += 1
406
+ if found >= max_count:
407
+ raise ValueError("There may be at most {} {} headers "
408
+ "in a message".format(max_count, name))
409
+ self._headers.append(self.policy.header_store_parse(name, val))
410
+
411
+ def __delitem__(self, name):
412
+ """Delete all occurrences of a header, if present.
413
+
414
+ Does not raise an exception if the header is missing.
415
+ """
416
+ name = name.lower()
417
+ newheaders = []
418
+ for k, v in self._headers:
419
+ if k.lower() != name:
420
+ newheaders.append((k, v))
421
+ self._headers = newheaders
422
+
423
+ def __contains__(self, name):
424
+ return name.lower() in [k.lower() for k, v in self._headers]
425
+
426
+ def __iter__(self):
427
+ for field, value in self._headers:
428
+ yield field
429
+
430
+ def keys(self):
431
+ """Return a list of all the message's header field names.
432
+
433
+ These will be sorted in the order they appeared in the original
434
+ message, or were added to the message, and may contain duplicates.
435
+ Any fields deleted and re-inserted are always appended to the header
436
+ list.
437
+ """
438
+ return [k for k, v in self._headers]
439
+
440
+ def values(self):
441
+ """Return a list of all the message's header values.
442
+
443
+ These will be sorted in the order they appeared in the original
444
+ message, or were added to the message, and may contain duplicates.
445
+ Any fields deleted and re-inserted are always appended to the header
446
+ list.
447
+ """
448
+ return [self.policy.header_fetch_parse(k, v)
449
+ for k, v in self._headers]
450
+
451
+ def items(self):
452
+ """Get all the message's header fields and values.
453
+
454
+ These will be sorted in the order they appeared in the original
455
+ message, or were added to the message, and may contain duplicates.
456
+ Any fields deleted and re-inserted are always appended to the header
457
+ list.
458
+ """
459
+ return [(k, self.policy.header_fetch_parse(k, v))
460
+ for k, v in self._headers]
461
+
462
+ def get(self, name, failobj=None):
463
+ """Get a header value.
464
+
465
+ Like __getitem__() but return failobj instead of None when the field
466
+ is missing.
467
+ """
468
+ name = name.lower()
469
+ for k, v in self._headers:
470
+ if k.lower() == name:
471
+ return self.policy.header_fetch_parse(k, v)
472
+ return failobj
473
+
474
+ #
475
+ # "Internal" methods (public API, but only intended for use by a parser
476
+ # or generator, not normal application code.
477
+ #
478
+
479
+ def set_raw(self, name, value):
480
+ """Store name and value in the model without modification.
481
+
482
+ This is an "internal" API, intended only for use by a parser.
483
+ """
484
+ self._headers.append((name, value))
485
+
486
+ def raw_items(self):
487
+ """Return the (name, value) header pairs without modification.
488
+
489
+ This is an "internal" API, intended only for use by a generator.
490
+ """
491
+ return iter(self._headers.copy())
492
+
493
+ #
494
+ # Additional useful stuff
495
+ #
496
+
497
+ def get_all(self, name, failobj=None):
498
+ """Return a list of all the values for the named field.
499
+
500
+ These will be sorted in the order they appeared in the original
501
+ message, and may contain duplicates. Any fields deleted and
502
+ re-inserted are always appended to the header list.
503
+
504
+ If no such fields exist, failobj is returned (defaults to None).
505
+ """
506
+ values = []
507
+ name = name.lower()
508
+ for k, v in self._headers:
509
+ if k.lower() == name:
510
+ values.append(self.policy.header_fetch_parse(k, v))
511
+ if not values:
512
+ return failobj
513
+ return values
514
+
515
+ def add_header(self, _name, _value, **_params):
516
+ """Extended header setting.
517
+
518
+ name is the header field to add. keyword arguments can be used to set
519
+ additional parameters for the header field, with underscores converted
520
+ to dashes. Normally the parameter will be added as key="value" unless
521
+ value is None, in which case only the key will be added. If a
522
+ parameter value contains non-ASCII characters it can be specified as a
523
+ three-tuple of (charset, language, value), in which case it will be
524
+ encoded according to RFC2231 rules. Otherwise it will be encoded using
525
+ the utf-8 charset and a language of ''.
526
+
527
+ Examples:
528
+
529
+ msg.add_header('content-disposition', 'attachment', filename='bud.gif')
530
+ msg.add_header('content-disposition', 'attachment',
531
+ filename=('utf-8', '', Fußballer.ppt'))
532
+ msg.add_header('content-disposition', 'attachment',
533
+ filename='Fußballer.ppt'))
534
+ """
535
+ parts = []
536
+ for k, v in _params.items():
537
+ if v is None:
538
+ parts.append(k.replace('_', '-'))
539
+ else:
540
+ parts.append(_formatparam(k.replace('_', '-'), v))
541
+ if _value is not None:
542
+ parts.insert(0, _value)
543
+ self[_name] = SEMISPACE.join(parts)
544
+
545
+ def replace_header(self, _name, _value):
546
+ """Replace a header.
547
+
548
+ Replace the first matching header found in the message, retaining
549
+ header order and case. If no matching header was found, a KeyError is
550
+ raised.
551
+ """
552
+ _name = _name.lower()
553
+ for i, (k, v) in zip(range(len(self._headers)), self._headers):
554
+ if k.lower() == _name:
555
+ self._headers[i] = self.policy.header_store_parse(k, _value)
556
+ break
557
+ else:
558
+ raise KeyError(_name)
559
+
560
+ #
561
+ # Use these three methods instead of the three above.
562
+ #
563
+
564
+ def get_content_type(self):
565
+ """Return the message's content type.
566
+
567
+ The returned string is coerced to lower case of the form
568
+ `maintype/subtype'. If there was no Content-Type header in the
569
+ message, the default type as given by get_default_type() will be
570
+ returned. Since according to RFC 2045, messages always have a default
571
+ type this will always return a value.
572
+
573
+ RFC 2045 defines a message's default type to be text/plain unless it
574
+ appears inside a multipart/digest container, in which case it would be
575
+ message/rfc822.
576
+ """
577
+ missing = object()
578
+ value = self.get('content-type', missing)
579
+ if value is missing:
580
+ # This should have no parameters
581
+ return self.get_default_type()
582
+ ctype = _splitparam(value)[0].lower()
583
+ # RFC 2045, section 5.2 says if its invalid, use text/plain
584
+ if ctype.count('/') != 1:
585
+ return 'text/plain'
586
+ return ctype
587
+
588
+ def get_content_maintype(self):
589
+ """Return the message's main content type.
590
+
591
+ This is the `maintype' part of the string returned by
592
+ get_content_type().
593
+ """
594
+ ctype = self.get_content_type()
595
+ return ctype.split('/')[0]
596
+
597
+ def get_content_subtype(self):
598
+ """Returns the message's sub-content type.
599
+
600
+ This is the `subtype' part of the string returned by
601
+ get_content_type().
602
+ """
603
+ ctype = self.get_content_type()
604
+ return ctype.split('/')[1]
605
+
606
+ def get_default_type(self):
607
+ """Return the `default' content type.
608
+
609
+ Most messages have a default content type of text/plain, except for
610
+ messages that are subparts of multipart/digest containers. Such
611
+ subparts have a default content type of message/rfc822.
612
+ """
613
+ return self._default_type
614
+
615
+ def set_default_type(self, ctype):
616
+ """Set the `default' content type.
617
+
618
+ ctype should be either "text/plain" or "message/rfc822", although this
619
+ is not enforced. The default content type is not stored in the
620
+ Content-Type header.
621
+ """
622
+ self._default_type = ctype
623
+
624
+ def _get_params_preserve(self, failobj, header):
625
+ # Like get_params() but preserves the quoting of values. BAW:
626
+ # should this be part of the public interface?
627
+ missing = object()
628
+ value = self.get(header, missing)
629
+ if value is missing:
630
+ return failobj
631
+ params = []
632
+ for p in _parseparam(value):
633
+ try:
634
+ name, val = p.split('=', 1)
635
+ name = name.strip()
636
+ val = val.strip()
637
+ except ValueError:
638
+ # Must have been a bare attribute
639
+ name = p.strip()
640
+ val = ''
641
+ params.append((name, val))
642
+ params = utils.decode_params(params)
643
+ return params
644
+
645
+ def get_params(self, failobj=None, header='content-type', unquote=True):
646
+ """Return the message's Content-Type parameters, as a list.
647
+
648
+ The elements of the returned list are 2-tuples of key/value pairs, as
649
+ split on the `=' sign. The left hand side of the `=' is the key,
650
+ while the right hand side is the value. If there is no `=' sign in
651
+ the parameter the value is the empty string. The value is as
652
+ described in the get_param() method.
653
+
654
+ Optional failobj is the object to return if there is no Content-Type
655
+ header. Optional header is the header to search instead of
656
+ Content-Type. If unquote is True, the value is unquoted.
657
+ """
658
+ missing = object()
659
+ params = self._get_params_preserve(missing, header)
660
+ if params is missing:
661
+ return failobj
662
+ if unquote:
663
+ return [(k, _unquotevalue(v)) for k, v in params]
664
+ else:
665
+ return params
666
+
667
+ def get_param(self, param, failobj=None, header='content-type',
668
+ unquote=True):
669
+ """Return the parameter value if found in the Content-Type header.
670
+
671
+ Optional failobj is the object to return if there is no Content-Type
672
+ header, or the Content-Type header has no such parameter. Optional
673
+ header is the header to search instead of Content-Type.
674
+
675
+ Parameter keys are always compared case insensitively. The return
676
+ value can either be a string, or a 3-tuple if the parameter was RFC
677
+ 2231 encoded. When it's a 3-tuple, the elements of the value are of
678
+ the form (CHARSET, LANGUAGE, VALUE). Note that both CHARSET and
679
+ LANGUAGE can be None, in which case you should consider VALUE to be
680
+ encoded in the us-ascii charset. You can usually ignore LANGUAGE.
681
+ The parameter value (either the returned string, or the VALUE item in
682
+ the 3-tuple) is always unquoted, unless unquote is set to False.
683
+
684
+ If your application doesn't care whether the parameter was RFC 2231
685
+ encoded, it can turn the return value into a string as follows:
686
+
687
+ rawparam = msg.get_param('foo')
688
+ param = email.utils.collapse_rfc2231_value(rawparam)
689
+
690
+ """
691
+ if header not in self:
692
+ return failobj
693
+ for k, v in self._get_params_preserve(failobj, header):
694
+ if k.lower() == param.lower():
695
+ if unquote:
696
+ return _unquotevalue(v)
697
+ else:
698
+ return v
699
+ return failobj
700
+
701
+ def set_param(self, param, value, header='Content-Type', requote=True,
702
+ charset=None, language='', replace=False):
703
+ """Set a parameter in the Content-Type header.
704
+
705
+ If the parameter already exists in the header, its value will be
706
+ replaced with the new value.
707
+
708
+ If header is Content-Type and has not yet been defined for this
709
+ message, it will be set to "text/plain" and the new parameter and
710
+ value will be appended as per RFC 2045.
711
+
712
+ An alternate header can be specified in the header argument, and all
713
+ parameters will be quoted as necessary unless requote is False.
714
+
715
+ If charset is specified, the parameter will be encoded according to RFC
716
+ 2231. Optional language specifies the RFC 2231 language, defaulting
717
+ to the empty string. Both charset and language should be strings.
718
+ """
719
+ if not isinstance(value, tuple) and charset:
720
+ value = (charset, language, value)
721
+
722
+ if header not in self and header.lower() == 'content-type':
723
+ ctype = 'text/plain'
724
+ else:
725
+ ctype = self.get(header)
726
+ if not self.get_param(param, header=header):
727
+ if not ctype:
728
+ ctype = _formatparam(param, value, requote)
729
+ else:
730
+ ctype = SEMISPACE.join(
731
+ [ctype, _formatparam(param, value, requote)])
732
+ else:
733
+ ctype = ''
734
+ for old_param, old_value in self.get_params(header=header,
735
+ unquote=requote):
736
+ append_param = ''
737
+ if old_param.lower() == param.lower():
738
+ append_param = _formatparam(param, value, requote)
739
+ else:
740
+ append_param = _formatparam(old_param, old_value, requote)
741
+ if not ctype:
742
+ ctype = append_param
743
+ else:
744
+ ctype = SEMISPACE.join([ctype, append_param])
745
+ if ctype != self.get(header):
746
+ if replace:
747
+ self.replace_header(header, ctype)
748
+ else:
749
+ del self[header]
750
+ self[header] = ctype
751
+
752
+ def del_param(self, param, header='content-type', requote=True):
753
+ """Remove the given parameter completely from the Content-Type header.
754
+
755
+ The header will be re-written in place without the parameter or its
756
+ value. All values will be quoted as necessary unless requote is
757
+ False. Optional header specifies an alternative to the Content-Type
758
+ header.
759
+ """
760
+ if header not in self:
761
+ return
762
+ new_ctype = ''
763
+ for p, v in self.get_params(header=header, unquote=requote):
764
+ if p.lower() != param.lower():
765
+ if not new_ctype:
766
+ new_ctype = _formatparam(p, v, requote)
767
+ else:
768
+ new_ctype = SEMISPACE.join([new_ctype,
769
+ _formatparam(p, v, requote)])
770
+ if new_ctype != self.get(header):
771
+ del self[header]
772
+ self[header] = new_ctype
773
+
774
+ def set_type(self, type, header='Content-Type', requote=True):
775
+ """Set the main type and subtype for the Content-Type header.
776
+
777
+ type must be a string in the form "maintype/subtype", otherwise a
778
+ ValueError is raised.
779
+
780
+ This method replaces the Content-Type header, keeping all the
781
+ parameters in place. If requote is False, this leaves the existing
782
+ header's quoting as is. Otherwise, the parameters will be quoted (the
783
+ default).
784
+
785
+ An alternative header can be specified in the header argument. When
786
+ the Content-Type header is set, we'll always also add a MIME-Version
787
+ header.
788
+ """
789
+ # BAW: should we be strict?
790
+ if not type.count('/') == 1:
791
+ raise ValueError
792
+ # Set the Content-Type, you get a MIME-Version
793
+ if header.lower() == 'content-type':
794
+ del self['mime-version']
795
+ self['MIME-Version'] = '1.0'
796
+ if header not in self:
797
+ self[header] = type
798
+ return
799
+ params = self.get_params(header=header, unquote=requote)
800
+ del self[header]
801
+ self[header] = type
802
+ # Skip the first param; it's the old type.
803
+ for p, v in params[1:]:
804
+ self.set_param(p, v, header, requote)
805
+
806
+ def get_filename(self, failobj=None):
807
+ """Return the filename associated with the payload if present.
808
+
809
+ The filename is extracted from the Content-Disposition header's
810
+ `filename' parameter, and it is unquoted. If that header is missing
811
+ the `filename' parameter, this method falls back to looking for the
812
+ `name' parameter.
813
+ """
814
+ missing = object()
815
+ filename = self.get_param('filename', missing, 'content-disposition')
816
+ if filename is missing:
817
+ filename = self.get_param('name', missing, 'content-type')
818
+ if filename is missing:
819
+ return failobj
820
+ return utils.collapse_rfc2231_value(filename).strip()
821
+
822
+ def get_boundary(self, failobj=None):
823
+ """Return the boundary associated with the payload if present.
824
+
825
+ The boundary is extracted from the Content-Type header's `boundary'
826
+ parameter, and it is unquoted.
827
+ """
828
+ missing = object()
829
+ boundary = self.get_param('boundary', missing)
830
+ if boundary is missing:
831
+ return failobj
832
+ # RFC 2046 says that boundaries may begin but not end in w/s
833
+ return utils.collapse_rfc2231_value(boundary).rstrip()
834
+
835
+ def set_boundary(self, boundary):
836
+ """Set the boundary parameter in Content-Type to 'boundary'.
837
+
838
+ This is subtly different than deleting the Content-Type header and
839
+ adding a new one with a new boundary parameter via add_header(). The
840
+ main difference is that using the set_boundary() method preserves the
841
+ order of the Content-Type header in the original message.
842
+
843
+ HeaderParseError is raised if the message has no Content-Type header.
844
+ """
845
+ missing = object()
846
+ params = self._get_params_preserve(missing, 'content-type')
847
+ if params is missing:
848
+ # There was no Content-Type header, and we don't know what type
849
+ # to set it to, so raise an exception.
850
+ raise errors.HeaderParseError('No Content-Type header found')
851
+ newparams = []
852
+ foundp = False
853
+ for pk, pv in params:
854
+ if pk.lower() == 'boundary':
855
+ newparams.append(('boundary', '"%s"' % boundary))
856
+ foundp = True
857
+ else:
858
+ newparams.append((pk, pv))
859
+ if not foundp:
860
+ # The original Content-Type header had no boundary attribute.
861
+ # Tack one on the end. BAW: should we raise an exception
862
+ # instead???
863
+ newparams.append(('boundary', '"%s"' % boundary))
864
+ # Replace the existing Content-Type header with the new value
865
+ newheaders = []
866
+ for h, v in self._headers:
867
+ if h.lower() == 'content-type':
868
+ parts = []
869
+ for k, v in newparams:
870
+ if v == '':
871
+ parts.append(k)
872
+ else:
873
+ parts.append('%s=%s' % (k, v))
874
+ val = SEMISPACE.join(parts)
875
+ newheaders.append(self.policy.header_store_parse(h, val))
876
+
877
+ else:
878
+ newheaders.append((h, v))
879
+ self._headers = newheaders
880
+
881
+ def get_content_charset(self, failobj=None):
882
+ """Return the charset parameter of the Content-Type header.
883
+
884
+ The returned string is always coerced to lower case. If there is no
885
+ Content-Type header, or if that header has no charset parameter,
886
+ failobj is returned.
887
+ """
888
+ missing = object()
889
+ charset = self.get_param('charset', missing)
890
+ if charset is missing:
891
+ return failobj
892
+ if isinstance(charset, tuple):
893
+ # RFC 2231 encoded, so decode it, and it better end up as ascii.
894
+ pcharset = charset[0] or 'us-ascii'
895
+ try:
896
+ # LookupError will be raised if the charset isn't known to
897
+ # Python. UnicodeError will be raised if the encoded text
898
+ # contains a character not in the charset.
899
+ as_bytes = charset[2].encode('raw-unicode-escape')
900
+ charset = str(as_bytes, pcharset)
901
+ except (LookupError, UnicodeError):
902
+ charset = charset[2]
903
+ # charset characters must be in us-ascii range
904
+ try:
905
+ charset.encode('us-ascii')
906
+ except UnicodeError:
907
+ return failobj
908
+ # RFC 2046, $4.1.2 says charsets are not case sensitive
909
+ return charset.lower()
910
+
911
+ def get_charsets(self, failobj=None):
912
+ """Return a list containing the charset(s) used in this message.
913
+
914
+ The returned list of items describes the Content-Type headers'
915
+ charset parameter for this message and all the subparts in its
916
+ payload.
917
+
918
+ Each item will either be a string (the value of the charset parameter
919
+ in the Content-Type header of that part) or the value of the
920
+ 'failobj' parameter (defaults to None), if the part does not have a
921
+ main MIME type of "text", or the charset is not defined.
922
+
923
+ The list will contain one string for each part of the message, plus
924
+ one for the container message (i.e. self), so that a non-multipart
925
+ message will still return a list of length 1.
926
+ """
927
+ return [part.get_content_charset(failobj) for part in self.walk()]
928
+
929
+ def get_content_disposition(self):
930
+ """Return the message's content-disposition if it exists, or None.
931
+
932
+ The return values can be either 'inline', 'attachment' or None
933
+ according to the rfc2183.
934
+ """
935
+ value = self.get('content-disposition')
936
+ if value is None:
937
+ return None
938
+ c_d = _splitparam(value)[0].lower()
939
+ return c_d
940
+
941
+ # I.e. def walk(self): ...
942
+ from email.iterators import walk
943
+
944
+
945
+ class MIMEPart(Message):
946
+
947
+ def __init__(self, policy=None):
948
+ if policy is None:
949
+ from email.policy import default
950
+ policy = default
951
+ Message.__init__(self, policy)
952
+
953
+
954
+ def as_string(self, unixfrom=False, maxheaderlen=None, policy=None):
955
+ """Return the entire formatted message as a string.
956
+
957
+ Optional 'unixfrom', when true, means include the Unix From_ envelope
958
+ header. maxheaderlen is retained for backward compatibility with the
959
+ base Message class, but defaults to None, meaning that the policy value
960
+ for max_line_length controls the header maximum length. 'policy' is
961
+ passed to the Generator instance used to serialize the message; if it
962
+ is not specified the policy associated with the message instance is
963
+ used.
964
+ """
965
+ policy = self.policy if policy is None else policy
966
+ if maxheaderlen is None:
967
+ maxheaderlen = policy.max_line_length
968
+ return super().as_string(maxheaderlen=maxheaderlen, policy=policy)
969
+
970
+ def __str__(self):
971
+ return self.as_string(policy=self.policy.clone(utf8=True))
972
+
973
+ def is_attachment(self):
974
+ c_d = self.get('content-disposition')
975
+ return False if c_d is None else c_d.content_disposition == 'attachment'
976
+
977
+ def _find_body(self, part, preferencelist):
978
+ if part.is_attachment():
979
+ return
980
+ maintype, subtype = part.get_content_type().split('/')
981
+ if maintype == 'text':
982
+ if subtype in preferencelist:
983
+ yield (preferencelist.index(subtype), part)
984
+ return
985
+ if maintype != 'multipart':
986
+ return
987
+ if subtype != 'related':
988
+ for subpart in part.iter_parts():
989
+ yield from self._find_body(subpart, preferencelist)
990
+ return
991
+ if 'related' in preferencelist:
992
+ yield (preferencelist.index('related'), part)
993
+ candidate = None
994
+ start = part.get_param('start')
995
+ if start:
996
+ for subpart in part.iter_parts():
997
+ if subpart['content-id'] == start:
998
+ candidate = subpart
999
+ break
1000
+ if candidate is None:
1001
+ subparts = part.get_payload()
1002
+ candidate = subparts[0] if subparts else None
1003
+ if candidate is not None:
1004
+ yield from self._find_body(candidate, preferencelist)
1005
+
1006
+ def get_body(self, preferencelist=('related', 'html', 'plain')):
1007
+ """Return best candidate mime part for display as 'body' of message.
1008
+
1009
+ Do a depth first search, starting with self, looking for the first part
1010
+ matching each of the items in preferencelist, and return the part
1011
+ corresponding to the first item that has a match, or None if no items
1012
+ have a match. If 'related' is not included in preferencelist, consider
1013
+ the root part of any multipart/related encountered as a candidate
1014
+ match. Ignore parts with 'Content-Disposition: attachment'.
1015
+ """
1016
+ best_prio = len(preferencelist)
1017
+ body = None
1018
+ for prio, part in self._find_body(self, preferencelist):
1019
+ if prio < best_prio:
1020
+ best_prio = prio
1021
+ body = part
1022
+ if prio == 0:
1023
+ break
1024
+ return body
1025
+
1026
+ _body_types = {('text', 'plain'),
1027
+ ('text', 'html'),
1028
+ ('multipart', 'related'),
1029
+ ('multipart', 'alternative')}
1030
+ def iter_attachments(self):
1031
+ """Return an iterator over the non-main parts of a multipart.
1032
+
1033
+ Skip the first of each occurrence of text/plain, text/html,
1034
+ multipart/related, or multipart/alternative in the multipart (unless
1035
+ they have a 'Content-Disposition: attachment' header) and include all
1036
+ remaining subparts in the returned iterator. When applied to a
1037
+ multipart/related, return all parts except the root part. Return an
1038
+ empty iterator when applied to a multipart/alternative or a
1039
+ non-multipart.
1040
+ """
1041
+ maintype, subtype = self.get_content_type().split('/')
1042
+ if maintype != 'multipart' or subtype == 'alternative':
1043
+ return
1044
+ payload = self.get_payload()
1045
+ # Certain malformed messages can have content type set to `multipart/*`
1046
+ # but still have single part body, in which case payload.copy() can
1047
+ # fail with AttributeError.
1048
+ try:
1049
+ parts = payload.copy()
1050
+ except AttributeError:
1051
+ # payload is not a list, it is most probably a string.
1052
+ return
1053
+
1054
+ if maintype == 'multipart' and subtype == 'related':
1055
+ # For related, we treat everything but the root as an attachment.
1056
+ # The root may be indicated by 'start'; if there's no start or we
1057
+ # can't find the named start, treat the first subpart as the root.
1058
+ start = self.get_param('start')
1059
+ if start:
1060
+ found = False
1061
+ attachments = []
1062
+ for part in parts:
1063
+ if part.get('content-id') == start:
1064
+ found = True
1065
+ else:
1066
+ attachments.append(part)
1067
+ if found:
1068
+ yield from attachments
1069
+ return
1070
+ parts.pop(0)
1071
+ yield from parts
1072
+ return
1073
+ # Otherwise we more or less invert the remaining logic in get_body.
1074
+ # This only really works in edge cases (ex: non-text related or
1075
+ # alternatives) if the sending agent sets content-disposition.
1076
+ seen = [] # Only skip the first example of each candidate type.
1077
+ for part in parts:
1078
+ maintype, subtype = part.get_content_type().split('/')
1079
+ if ((maintype, subtype) in self._body_types and
1080
+ not part.is_attachment() and subtype not in seen):
1081
+ seen.append(subtype)
1082
+ continue
1083
+ yield part
1084
+
1085
+ def iter_parts(self):
1086
+ """Return an iterator over all immediate subparts of a multipart.
1087
+
1088
+ Return an empty iterator for a non-multipart.
1089
+ """
1090
+ if self.get_content_maintype() == 'multipart':
1091
+ yield from self.get_payload()
1092
+
1093
+ def get_content(self, *args, content_manager=None, **kw):
1094
+ if content_manager is None:
1095
+ content_manager = self.policy.content_manager
1096
+ return content_manager.get_content(self, *args, **kw)
1097
+
1098
+ def set_content(self, *args, content_manager=None, **kw):
1099
+ if content_manager is None:
1100
+ content_manager = self.policy.content_manager
1101
+ content_manager.set_content(self, *args, **kw)
1102
+
1103
+ def _make_multipart(self, subtype, disallowed_subtypes, boundary):
1104
+ if self.get_content_maintype() == 'multipart':
1105
+ existing_subtype = self.get_content_subtype()
1106
+ disallowed_subtypes = disallowed_subtypes + (subtype,)
1107
+ if existing_subtype in disallowed_subtypes:
1108
+ raise ValueError("Cannot convert {} to {}".format(
1109
+ existing_subtype, subtype))
1110
+ keep_headers = []
1111
+ part_headers = []
1112
+ for name, value in self._headers:
1113
+ if name.lower().startswith('content-'):
1114
+ part_headers.append((name, value))
1115
+ else:
1116
+ keep_headers.append((name, value))
1117
+ if part_headers:
1118
+ # There is existing content, move it to the first subpart.
1119
+ part = type(self)(policy=self.policy)
1120
+ part._headers = part_headers
1121
+ part._payload = self._payload
1122
+ self._payload = [part]
1123
+ else:
1124
+ self._payload = []
1125
+ self._headers = keep_headers
1126
+ self['Content-Type'] = 'multipart/' + subtype
1127
+ if boundary is not None:
1128
+ self.set_param('boundary', boundary)
1129
+
1130
+ def make_related(self, boundary=None):
1131
+ self._make_multipart('related', ('alternative', 'mixed'), boundary)
1132
+
1133
+ def make_alternative(self, boundary=None):
1134
+ self._make_multipart('alternative', ('mixed',), boundary)
1135
+
1136
+ def make_mixed(self, boundary=None):
1137
+ self._make_multipart('mixed', (), boundary)
1138
+
1139
+ def _add_multipart(self, _subtype, *args, _disp=None, **kw):
1140
+ if (self.get_content_maintype() != 'multipart' or
1141
+ self.get_content_subtype() != _subtype):
1142
+ getattr(self, 'make_' + _subtype)()
1143
+ part = type(self)(policy=self.policy)
1144
+ part.set_content(*args, **kw)
1145
+ if _disp and 'content-disposition' not in part:
1146
+ part['Content-Disposition'] = _disp
1147
+ self.attach(part)
1148
+
1149
+ def add_related(self, *args, **kw):
1150
+ self._add_multipart('related', *args, _disp='inline', **kw)
1151
+
1152
+ def add_alternative(self, *args, **kw):
1153
+ self._add_multipart('alternative', *args, **kw)
1154
+
1155
+ def add_attachment(self, *args, **kw):
1156
+ self._add_multipart('mixed', *args, _disp='attachment', **kw)
1157
+
1158
+ def clear(self):
1159
+ self._headers = []
1160
+ self._payload = None
1161
+
1162
+ def clear_content(self):
1163
+ self._headers = [(n, v) for n, v in self._headers
1164
+ if not n.lower().startswith('content-')]
1165
+ self._payload = None
1166
+
1167
+
1168
+ class EmailMessage(MIMEPart):
1169
+
1170
+ def set_content(self, *args, **kw):
1171
+ super().set_content(*args, **kw)
1172
+ if 'MIME-Version' not in self:
1173
+ self['MIME-Version'] = '1.0'
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/parser.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2007 Python Software Foundation
2
+ # Author: Barry Warsaw, Thomas Wouters, Anthony Baxter
3
+ # Contact: email-sig@python.org
4
+
5
+ """A parser of RFC 2822 and MIME email messages."""
6
+
7
+ __all__ = ['Parser', 'HeaderParser', 'BytesParser', 'BytesHeaderParser',
8
+ 'FeedParser', 'BytesFeedParser']
9
+
10
+ from io import StringIO, TextIOWrapper
11
+
12
+ from email.feedparser import FeedParser, BytesFeedParser
13
+ from email._policybase import compat32
14
+
15
+
16
+ class Parser:
17
+ def __init__(self, _class=None, *, policy=compat32):
18
+ """Parser of RFC 2822 and MIME email messages.
19
+
20
+ Creates an in-memory object tree representing the email message, which
21
+ can then be manipulated and turned over to a Generator to return the
22
+ textual representation of the message.
23
+
24
+ The string must be formatted as a block of RFC 2822 headers and header
25
+ continuation lines, optionally preceded by a `Unix-from' header. The
26
+ header block is terminated either by the end of the string or by a
27
+ blank line.
28
+
29
+ _class is the class to instantiate for new message objects when they
30
+ must be created. This class must have a constructor that can take
31
+ zero arguments. Default is Message.Message.
32
+
33
+ The policy keyword specifies a policy object that controls a number of
34
+ aspects of the parser's operation. The default policy maintains
35
+ backward compatibility.
36
+
37
+ """
38
+ self._class = _class
39
+ self.policy = policy
40
+
41
+ def parse(self, fp, headersonly=False):
42
+ """Create a message structure from the data in a file.
43
+
44
+ Reads all the data from the file and returns the root of the message
45
+ structure. Optional headersonly is a flag specifying whether to stop
46
+ parsing after reading the headers or not. The default is False,
47
+ meaning it parses the entire contents of the file.
48
+ """
49
+ feedparser = FeedParser(self._class, policy=self.policy)
50
+ if headersonly:
51
+ feedparser._set_headersonly()
52
+ while True:
53
+ data = fp.read(8192)
54
+ if not data:
55
+ break
56
+ feedparser.feed(data)
57
+ return feedparser.close()
58
+
59
+ def parsestr(self, text, headersonly=False):
60
+ """Create a message structure from a string.
61
+
62
+ Returns the root of the message structure. Optional headersonly is a
63
+ flag specifying whether to stop parsing after reading the headers or
64
+ not. The default is False, meaning it parses the entire contents of
65
+ the file.
66
+ """
67
+ return self.parse(StringIO(text), headersonly=headersonly)
68
+
69
+
70
+
71
+ class HeaderParser(Parser):
72
+ def parse(self, fp, headersonly=True):
73
+ return Parser.parse(self, fp, True)
74
+
75
+ def parsestr(self, text, headersonly=True):
76
+ return Parser.parsestr(self, text, True)
77
+
78
+
79
+ class BytesParser:
80
+
81
+ def __init__(self, *args, **kw):
82
+ """Parser of binary RFC 2822 and MIME email messages.
83
+
84
+ Creates an in-memory object tree representing the email message, which
85
+ can then be manipulated and turned over to a Generator to return the
86
+ textual representation of the message.
87
+
88
+ The input must be formatted as a block of RFC 2822 headers and header
89
+ continuation lines, optionally preceded by a `Unix-from' header. The
90
+ header block is terminated either by the end of the input or by a
91
+ blank line.
92
+
93
+ _class is the class to instantiate for new message objects when they
94
+ must be created. This class must have a constructor that can take
95
+ zero arguments. Default is Message.Message.
96
+ """
97
+ self.parser = Parser(*args, **kw)
98
+
99
+ def parse(self, fp, headersonly=False):
100
+ """Create a message structure from the data in a binary file.
101
+
102
+ Reads all the data from the file and returns the root of the message
103
+ structure. Optional headersonly is a flag specifying whether to stop
104
+ parsing after reading the headers or not. The default is False,
105
+ meaning it parses the entire contents of the file.
106
+ """
107
+ fp = TextIOWrapper(fp, encoding='ascii', errors='surrogateescape')
108
+ try:
109
+ return self.parser.parse(fp, headersonly)
110
+ finally:
111
+ fp.detach()
112
+
113
+
114
+ def parsebytes(self, text, headersonly=False):
115
+ """Create a message structure from a byte string.
116
+
117
+ Returns the root of the message structure. Optional headersonly is a
118
+ flag specifying whether to stop parsing after reading the headers or
119
+ not. The default is False, meaning it parses the entire contents of
120
+ the file.
121
+ """
122
+ text = text.decode('ASCII', errors='surrogateescape')
123
+ return self.parser.parsestr(text, headersonly)
124
+
125
+
126
+ class BytesHeaderParser(BytesParser):
127
+ def parse(self, fp, headersonly=True):
128
+ return BytesParser.parse(self, fp, headersonly=True)
129
+
130
+ def parsebytes(self, text, headersonly=True):
131
+ return BytesParser.parsebytes(self, text, headersonly=True)
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/policy.py ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """This will be the home for the policy that hooks in the new
2
+ code that adds all the email6 features.
3
+ """
4
+
5
+ import re
6
+ import sys
7
+ from email._policybase import Policy, Compat32, compat32, _extend_docstrings
8
+ from email.utils import _has_surrogates
9
+ from email.headerregistry import HeaderRegistry as HeaderRegistry
10
+ from email.contentmanager import raw_data_manager
11
+ from email.message import EmailMessage
12
+
13
+ __all__ = [
14
+ 'Compat32',
15
+ 'compat32',
16
+ 'Policy',
17
+ 'EmailPolicy',
18
+ 'default',
19
+ 'strict',
20
+ 'SMTP',
21
+ 'HTTP',
22
+ ]
23
+
24
+ linesep_splitter = re.compile(r'\n|\r')
25
+
26
+ @_extend_docstrings
27
+ class EmailPolicy(Policy):
28
+
29
+ """+
30
+ PROVISIONAL
31
+
32
+ The API extensions enabled by this policy are currently provisional.
33
+ Refer to the documentation for details.
34
+
35
+ This policy adds new header parsing and folding algorithms. Instead of
36
+ simple strings, headers are custom objects with custom attributes
37
+ depending on the type of the field. The folding algorithm fully
38
+ implements RFCs 2047 and 5322.
39
+
40
+ In addition to the settable attributes listed above that apply to
41
+ all Policies, this policy adds the following additional attributes:
42
+
43
+ utf8 -- if False (the default) message headers will be
44
+ serialized as ASCII, using encoded words to encode
45
+ any non-ASCII characters in the source strings. If
46
+ True, the message headers will be serialized using
47
+ utf8 and will not contain encoded words (see RFC
48
+ 6532 for more on this serialization format).
49
+
50
+ refold_source -- if the value for a header in the Message object
51
+ came from the parsing of some source, this attribute
52
+ indicates whether or not a generator should refold
53
+ that value when transforming the message back into
54
+ stream form. The possible values are:
55
+
56
+ none -- all source values use original folding
57
+ long -- source values that have any line that is
58
+ longer than max_line_length will be
59
+ refolded
60
+ all -- all values are refolded.
61
+
62
+ The default is 'long'.
63
+
64
+ header_factory -- a callable that takes two arguments, 'name' and
65
+ 'value', where 'name' is a header field name and
66
+ 'value' is an unfolded header field value, and
67
+ returns a string-like object that represents that
68
+ header. A default header_factory is provided that
69
+ understands some of the RFC5322 header field types.
70
+ (Currently address fields and date fields have
71
+ special treatment, while all other fields are
72
+ treated as unstructured. This list will be
73
+ completed before the extension is marked stable.)
74
+
75
+ content_manager -- an object with at least two methods: get_content
76
+ and set_content. When the get_content or
77
+ set_content method of a Message object is called,
78
+ it calls the corresponding method of this object,
79
+ passing it the message object as its first argument,
80
+ and any arguments or keywords that were passed to
81
+ it as additional arguments. The default
82
+ content_manager is
83
+ :data:`~email.contentmanager.raw_data_manager`.
84
+
85
+ """
86
+
87
+ message_factory = EmailMessage
88
+ utf8 = False
89
+ refold_source = 'long'
90
+ header_factory = HeaderRegistry()
91
+ content_manager = raw_data_manager
92
+
93
+ def __init__(self, **kw):
94
+ # Ensure that each new instance gets a unique header factory
95
+ # (as opposed to clones, which share the factory).
96
+ if 'header_factory' not in kw:
97
+ object.__setattr__(self, 'header_factory', HeaderRegistry())
98
+ super().__init__(**kw)
99
+
100
+ def header_max_count(self, name):
101
+ """+
102
+ The implementation for this class returns the max_count attribute from
103
+ the specialized header class that would be used to construct a header
104
+ of type 'name'.
105
+ """
106
+ return self.header_factory[name].max_count
107
+
108
+ # The logic of the next three methods is chosen such that it is possible to
109
+ # switch a Message object between a Compat32 policy and a policy derived
110
+ # from this class and have the results stay consistent. This allows a
111
+ # Message object constructed with this policy to be passed to a library
112
+ # that only handles Compat32 objects, or to receive such an object and
113
+ # convert it to use the newer style by just changing its policy. It is
114
+ # also chosen because it postpones the relatively expensive full rfc5322
115
+ # parse until as late as possible when parsing from source, since in many
116
+ # applications only a few headers will actually be inspected.
117
+
118
+ def header_source_parse(self, sourcelines):
119
+ """+
120
+ The name is parsed as everything up to the ':' and returned unmodified.
121
+ The value is determined by stripping leading whitespace off the
122
+ remainder of the first line, joining all subsequent lines together, and
123
+ stripping any trailing carriage return or linefeed characters. (This
124
+ is the same as Compat32).
125
+
126
+ """
127
+ name, value = sourcelines[0].split(':', 1)
128
+ value = value.lstrip(' \t') + ''.join(sourcelines[1:])
129
+ return (name, value.rstrip('\r\n'))
130
+
131
+ def header_store_parse(self, name, value):
132
+ """+
133
+ The name is returned unchanged. If the input value has a 'name'
134
+ attribute and it matches the name ignoring case, the value is returned
135
+ unchanged. Otherwise the name and value are passed to header_factory
136
+ method, and the resulting custom header object is returned as the
137
+ value. In this case a ValueError is raised if the input value contains
138
+ CR or LF characters.
139
+
140
+ """
141
+ if hasattr(value, 'name') and value.name.lower() == name.lower():
142
+ return (name, value)
143
+ if isinstance(value, str) and len(value.splitlines())>1:
144
+ # XXX this error message isn't quite right when we use splitlines
145
+ # (see issue 22233), but I'm not sure what should happen here.
146
+ raise ValueError("Header values may not contain linefeed "
147
+ "or carriage return characters")
148
+ return (name, self.header_factory(name, value))
149
+
150
+ def header_fetch_parse(self, name, value):
151
+ """+
152
+ If the value has a 'name' attribute, it is returned to unmodified.
153
+ Otherwise the name and the value with any linesep characters removed
154
+ are passed to the header_factory method, and the resulting custom
155
+ header object is returned. Any surrogateescaped bytes get turned
156
+ into the unicode unknown-character glyph.
157
+
158
+ """
159
+ if hasattr(value, 'name'):
160
+ return value
161
+ # We can't use splitlines here because it splits on more than \r and \n.
162
+ value = ''.join(linesep_splitter.split(value))
163
+ return self.header_factory(name, value)
164
+
165
+ def fold(self, name, value):
166
+ """+
167
+ Header folding is controlled by the refold_source policy setting. A
168
+ value is considered to be a 'source value' if and only if it does not
169
+ have a 'name' attribute (having a 'name' attribute means it is a header
170
+ object of some sort). If a source value needs to be refolded according
171
+ to the policy, it is converted into a custom header object by passing
172
+ the name and the value with any linesep characters removed to the
173
+ header_factory method. Folding of a custom header object is done by
174
+ calling its fold method with the current policy.
175
+
176
+ Source values are split into lines using splitlines. If the value is
177
+ not to be refolded, the lines are rejoined using the linesep from the
178
+ policy and returned. The exception is lines containing non-ascii
179
+ binary data. In that case the value is refolded regardless of the
180
+ refold_source setting, which causes the binary data to be CTE encoded
181
+ using the unknown-8bit charset.
182
+
183
+ """
184
+ return self._fold(name, value, refold_binary=True)
185
+
186
+ def fold_binary(self, name, value):
187
+ """+
188
+ The same as fold if cte_type is 7bit, except that the returned value is
189
+ bytes.
190
+
191
+ If cte_type is 8bit, non-ASCII binary data is converted back into
192
+ bytes. Headers with binary data are not refolded, regardless of the
193
+ refold_header setting, since there is no way to know whether the binary
194
+ data consists of single byte characters or multibyte characters.
195
+
196
+ If utf8 is true, headers are encoded to utf8, otherwise to ascii with
197
+ non-ASCII unicode rendered as encoded words.
198
+
199
+ """
200
+ folded = self._fold(name, value, refold_binary=self.cte_type=='7bit')
201
+ charset = 'utf8' if self.utf8 else 'ascii'
202
+ return folded.encode(charset, 'surrogateescape')
203
+
204
+ def _fold(self, name, value, refold_binary=False):
205
+ if hasattr(value, 'name'):
206
+ return value.fold(policy=self)
207
+ maxlen = self.max_line_length if self.max_line_length else sys.maxsize
208
+ lines = value.splitlines()
209
+ refold = (self.refold_source == 'all' or
210
+ self.refold_source == 'long' and
211
+ (lines and len(lines[0])+len(name)+2 > maxlen or
212
+ any(len(x) > maxlen for x in lines[1:])))
213
+ if refold or refold_binary and _has_surrogates(value):
214
+ return self.header_factory(name, ''.join(lines)).fold(policy=self)
215
+ return name + ': ' + self.linesep.join(lines) + self.linesep
216
+
217
+
218
+ default = EmailPolicy()
219
+ # Make the default policy use the class default header_factory
220
+ del default.header_factory
221
+ strict = default.clone(raise_on_defect=True)
222
+ SMTP = default.clone(linesep='\r\n')
223
+ HTTP = default.clone(linesep='\r\n', max_line_length=None)
224
+ SMTPUTF8 = SMTP.clone(utf8=True)
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/quoprimime.py ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2006 Python Software Foundation
2
+ # Author: Ben Gertzfield
3
+ # Contact: email-sig@python.org
4
+
5
+ """Quoted-printable content transfer encoding per RFCs 2045-2047.
6
+
7
+ This module handles the content transfer encoding method defined in RFC 2045
8
+ to encode US ASCII-like 8-bit data called `quoted-printable'. It is used to
9
+ safely encode text that is in a character set similar to the 7-bit US ASCII
10
+ character set, but that includes some 8-bit characters that are normally not
11
+ allowed in email bodies or headers.
12
+
13
+ Quoted-printable is very space-inefficient for encoding binary files; use the
14
+ email.base64mime module for that instead.
15
+
16
+ This module provides an interface to encode and decode both headers and bodies
17
+ with quoted-printable encoding.
18
+
19
+ RFC 2045 defines a method for including character set information in an
20
+ `encoded-word' in a header. This method is commonly used for 8-bit real names
21
+ in To:/From:/Cc: etc. fields, as well as Subject: lines.
22
+
23
+ This module does not do the line wrapping or end-of-line character
24
+ conversion necessary for proper internationalized headers; it only
25
+ does dumb encoding and decoding. To deal with the various line
26
+ wrapping issues, use the email.header module.
27
+ """
28
+
29
+ __all__ = [
30
+ 'body_decode',
31
+ 'body_encode',
32
+ 'body_length',
33
+ 'decode',
34
+ 'decodestring',
35
+ 'header_decode',
36
+ 'header_encode',
37
+ 'header_length',
38
+ 'quote',
39
+ 'unquote',
40
+ ]
41
+
42
+ import re
43
+
44
+ from string import ascii_letters, digits, hexdigits
45
+
46
+ CRLF = '\r\n'
47
+ NL = '\n'
48
+ EMPTYSTRING = ''
49
+
50
+ # Build a mapping of octets to the expansion of that octet. Since we're only
51
+ # going to have 256 of these things, this isn't terribly inefficient
52
+ # space-wise. Remember that headers and bodies have different sets of safe
53
+ # characters. Initialize both maps with the full expansion, and then override
54
+ # the safe bytes with the more compact form.
55
+ _QUOPRI_MAP = ['=%02X' % c for c in range(256)]
56
+ _QUOPRI_HEADER_MAP = _QUOPRI_MAP[:]
57
+ _QUOPRI_BODY_MAP = _QUOPRI_MAP[:]
58
+
59
+ # Safe header bytes which need no encoding.
60
+ for c in b'-!*+/' + ascii_letters.encode('ascii') + digits.encode('ascii'):
61
+ _QUOPRI_HEADER_MAP[c] = chr(c)
62
+ # Headers have one other special encoding; spaces become underscores.
63
+ _QUOPRI_HEADER_MAP[ord(' ')] = '_'
64
+
65
+ # Safe body bytes which need no encoding.
66
+ for c in (b' !"#$%&\'()*+,-./0123456789:;<>'
67
+ b'?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`'
68
+ b'abcdefghijklmnopqrstuvwxyz{|}~\t'):
69
+ _QUOPRI_BODY_MAP[c] = chr(c)
70
+
71
+
72
+
73
+ # Helpers
74
+ def header_check(octet):
75
+ """Return True if the octet should be escaped with header quopri."""
76
+ return chr(octet) != _QUOPRI_HEADER_MAP[octet]
77
+
78
+
79
+ def body_check(octet):
80
+ """Return True if the octet should be escaped with body quopri."""
81
+ return chr(octet) != _QUOPRI_BODY_MAP[octet]
82
+
83
+
84
+ def header_length(bytearray):
85
+ """Return a header quoted-printable encoding length.
86
+
87
+ Note that this does not include any RFC 2047 chrome added by
88
+ `header_encode()`.
89
+
90
+ :param bytearray: An array of bytes (a.k.a. octets).
91
+ :return: The length in bytes of the byte array when it is encoded with
92
+ quoted-printable for headers.
93
+ """
94
+ return sum(len(_QUOPRI_HEADER_MAP[octet]) for octet in bytearray)
95
+
96
+
97
+ def body_length(bytearray):
98
+ """Return a body quoted-printable encoding length.
99
+
100
+ :param bytearray: An array of bytes (a.k.a. octets).
101
+ :return: The length in bytes of the byte array when it is encoded with
102
+ quoted-printable for bodies.
103
+ """
104
+ return sum(len(_QUOPRI_BODY_MAP[octet]) for octet in bytearray)
105
+
106
+
107
+ def _max_append(L, s, maxlen, extra=''):
108
+ if not isinstance(s, str):
109
+ s = chr(s)
110
+ if not L:
111
+ L.append(s.lstrip())
112
+ elif len(L[-1]) + len(s) <= maxlen:
113
+ L[-1] += extra + s
114
+ else:
115
+ L.append(s.lstrip())
116
+
117
+
118
+ def unquote(s):
119
+ """Turn a string in the form =AB to the ASCII character with value 0xab"""
120
+ return chr(int(s[1:3], 16))
121
+
122
+
123
+ def quote(c):
124
+ return _QUOPRI_MAP[ord(c)]
125
+
126
+
127
+ def header_encode(header_bytes, charset='iso-8859-1'):
128
+ """Encode a single header line with quoted-printable (like) encoding.
129
+
130
+ Defined in RFC 2045, this `Q' encoding is similar to quoted-printable, but
131
+ used specifically for email header fields to allow charsets with mostly 7
132
+ bit characters (and some 8 bit) to remain more or less readable in non-RFC
133
+ 2045 aware mail clients.
134
+
135
+ charset names the character set to use in the RFC 2046 header. It
136
+ defaults to iso-8859-1.
137
+ """
138
+ # Return empty headers as an empty string.
139
+ if not header_bytes:
140
+ return ''
141
+ # Iterate over every byte, encoding if necessary.
142
+ encoded = header_bytes.decode('latin1').translate(_QUOPRI_HEADER_MAP)
143
+ # Now add the RFC chrome to each encoded chunk and glue the chunks
144
+ # together.
145
+ return '=?%s?q?%s?=' % (charset, encoded)
146
+
147
+
148
+ _QUOPRI_BODY_ENCODE_MAP = _QUOPRI_BODY_MAP[:]
149
+ for c in b'\r\n':
150
+ _QUOPRI_BODY_ENCODE_MAP[c] = chr(c)
151
+
152
+ def body_encode(body, maxlinelen=76, eol=NL):
153
+ """Encode with quoted-printable, wrapping at maxlinelen characters.
154
+
155
+ Each line of encoded text will end with eol, which defaults to "\\n". Set
156
+ this to "\\r\\n" if you will be using the result of this function directly
157
+ in an email.
158
+
159
+ Each line will be wrapped at, at most, maxlinelen characters before the
160
+ eol string (maxlinelen defaults to 76 characters, the maximum value
161
+ permitted by RFC 2045). Long lines will have the 'soft line break'
162
+ quoted-printable character "=" appended to them, so the decoded text will
163
+ be identical to the original text.
164
+
165
+ The minimum maxlinelen is 4 to have room for a quoted character ("=XX")
166
+ followed by a soft line break. Smaller values will generate a
167
+ ValueError.
168
+
169
+ """
170
+
171
+ if maxlinelen < 4:
172
+ raise ValueError("maxlinelen must be at least 4")
173
+ if not body:
174
+ return body
175
+
176
+ # quote special characters
177
+ body = body.translate(_QUOPRI_BODY_ENCODE_MAP)
178
+
179
+ soft_break = '=' + eol
180
+ # leave space for the '=' at the end of a line
181
+ maxlinelen1 = maxlinelen - 1
182
+
183
+ encoded_body = []
184
+ append = encoded_body.append
185
+
186
+ for line in body.splitlines():
187
+ # break up the line into pieces no longer than maxlinelen - 1
188
+ start = 0
189
+ laststart = len(line) - 1 - maxlinelen
190
+ while start <= laststart:
191
+ stop = start + maxlinelen1
192
+ # make sure we don't break up an escape sequence
193
+ if line[stop - 2] == '=':
194
+ append(line[start:stop - 1])
195
+ start = stop - 2
196
+ elif line[stop - 1] == '=':
197
+ append(line[start:stop])
198
+ start = stop - 1
199
+ else:
200
+ append(line[start:stop] + '=')
201
+ start = stop
202
+
203
+ # handle rest of line, special case if line ends in whitespace
204
+ if line and line[-1] in ' \t':
205
+ room = start - laststart
206
+ if room >= 3:
207
+ # It's a whitespace character at end-of-line, and we have room
208
+ # for the three-character quoted encoding.
209
+ q = quote(line[-1])
210
+ elif room == 2:
211
+ # There's room for the whitespace character and a soft break.
212
+ q = line[-1] + soft_break
213
+ else:
214
+ # There's room only for a soft break. The quoted whitespace
215
+ # will be the only content on the subsequent line.
216
+ q = soft_break + quote(line[-1])
217
+ append(line[start:-1] + q)
218
+ else:
219
+ append(line[start:])
220
+
221
+ # add back final newline if present
222
+ if body[-1] in CRLF:
223
+ append('')
224
+
225
+ return eol.join(encoded_body)
226
+
227
+
228
+
229
+ # BAW: I'm not sure if the intent was for the signature of this function to be
230
+ # the same as base64MIME.decode() or not...
231
+ def decode(encoded, eol=NL):
232
+ """Decode a quoted-printable string.
233
+
234
+ Lines are separated with eol, which defaults to \\n.
235
+ """
236
+ if not encoded:
237
+ return encoded
238
+ # BAW: see comment in encode() above. Again, we're building up the
239
+ # decoded string with string concatenation, which could be done much more
240
+ # efficiently.
241
+ decoded = ''
242
+
243
+ for line in encoded.splitlines():
244
+ line = line.rstrip()
245
+ if not line:
246
+ decoded += eol
247
+ continue
248
+
249
+ i = 0
250
+ n = len(line)
251
+ while i < n:
252
+ c = line[i]
253
+ if c != '=':
254
+ decoded += c
255
+ i += 1
256
+ # Otherwise, c == "=". Are we at the end of the line? If so, add
257
+ # a soft line break.
258
+ elif i+1 == n:
259
+ i += 1
260
+ continue
261
+ # Decode if in form =AB
262
+ elif i+2 < n and line[i+1] in hexdigits and line[i+2] in hexdigits:
263
+ decoded += unquote(line[i:i+3])
264
+ i += 3
265
+ # Otherwise, not in form =AB, pass literally
266
+ else:
267
+ decoded += c
268
+ i += 1
269
+
270
+ if i == n:
271
+ decoded += eol
272
+ # Special case if original string did not end with eol
273
+ if encoded[-1] not in '\r\n' and decoded.endswith(eol):
274
+ decoded = decoded[:-1]
275
+ return decoded
276
+
277
+
278
+ # For convenience and backwards compatibility w/ standard base64 module
279
+ body_decode = decode
280
+ decodestring = decode
281
+
282
+
283
+
284
+ def _unquote_match(match):
285
+ """Turn a match in the form =AB to the ASCII character with value 0xab"""
286
+ s = match.group(0)
287
+ return unquote(s)
288
+
289
+
290
+ # Header decoding is done a bit differently
291
+ def header_decode(s):
292
+ """Decode a string encoded with RFC 2045 MIME header `Q' encoding.
293
+
294
+ This function does not parse a full MIME header value encoded with
295
+ quoted-printable (like =?iso-8859-1?q?Hello_World?=) -- please use
296
+ the high level email.header class for that functionality.
297
+ """
298
+ s = s.replace('_', ' ')
299
+ return re.sub(r'=[a-fA-F0-9]{2}', _unquote_match, s, flags=re.ASCII)
my_container_sandbox/workspace/anaconda3/lib/python3.8/email/utils.py ADDED
@@ -0,0 +1,376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2001-2010 Python Software Foundation
2
+ # Author: Barry Warsaw
3
+ # Contact: email-sig@python.org
4
+
5
+ """Miscellaneous utilities."""
6
+
7
+ __all__ = [
8
+ 'collapse_rfc2231_value',
9
+ 'decode_params',
10
+ 'decode_rfc2231',
11
+ 'encode_rfc2231',
12
+ 'formataddr',
13
+ 'formatdate',
14
+ 'format_datetime',
15
+ 'getaddresses',
16
+ 'make_msgid',
17
+ 'mktime_tz',
18
+ 'parseaddr',
19
+ 'parsedate',
20
+ 'parsedate_tz',
21
+ 'parsedate_to_datetime',
22
+ 'unquote',
23
+ ]
24
+
25
+ import os
26
+ import re
27
+ import time
28
+ import random
29
+ import socket
30
+ import datetime
31
+ import urllib.parse
32
+
33
+ from email._parseaddr import quote
34
+ from email._parseaddr import AddressList as _AddressList
35
+ from email._parseaddr import mktime_tz
36
+
37
+ from email._parseaddr import parsedate, parsedate_tz, _parsedate_tz
38
+
39
+ # Intrapackage imports
40
+ from email.charset import Charset
41
+
42
+ COMMASPACE = ', '
43
+ EMPTYSTRING = ''
44
+ UEMPTYSTRING = ''
45
+ CRLF = '\r\n'
46
+ TICK = "'"
47
+
48
+ specialsre = re.compile(r'[][\\()<>@,:;".]')
49
+ escapesre = re.compile(r'[\\"]')
50
+
51
+ def _has_surrogates(s):
52
+ """Return True if s contains surrogate-escaped binary data."""
53
+ # This check is based on the fact that unless there are surrogates, utf8
54
+ # (Python's default encoding) can encode any string. This is the fastest
55
+ # way to check for surrogates, see issue 11454 for timings.
56
+ try:
57
+ s.encode()
58
+ return False
59
+ except UnicodeEncodeError:
60
+ return True
61
+
62
+ # How to deal with a string containing bytes before handing it to the
63
+ # application through the 'normal' interface.
64
+ def _sanitize(string):
65
+ # Turn any escaped bytes into unicode 'unknown' char. If the escaped
66
+ # bytes happen to be utf-8 they will instead get decoded, even if they
67
+ # were invalid in the charset the source was supposed to be in. This
68
+ # seems like it is not a bad thing; a defect was still registered.
69
+ original_bytes = string.encode('utf-8', 'surrogateescape')
70
+ return original_bytes.decode('utf-8', 'replace')
71
+
72
+
73
+
74
+ # Helpers
75
+
76
+ def formataddr(pair, charset='utf-8'):
77
+ """The inverse of parseaddr(), this takes a 2-tuple of the form
78
+ (realname, email_address) and returns the string value suitable
79
+ for an RFC 2822 From, To or Cc header.
80
+
81
+ If the first element of pair is false, then the second element is
82
+ returned unmodified.
83
+
84
+ The optional charset is the character set that is used to encode
85
+ realname in case realname is not ASCII safe. Can be an instance of str or
86
+ a Charset-like object which has a header_encode method. Default is
87
+ 'utf-8'.
88
+ """
89
+ name, address = pair
90
+ # The address MUST (per RFC) be ascii, so raise a UnicodeError if it isn't.
91
+ address.encode('ascii')
92
+ if name:
93
+ try:
94
+ name.encode('ascii')
95
+ except UnicodeEncodeError:
96
+ if isinstance(charset, str):
97
+ charset = Charset(charset)
98
+ encoded_name = charset.header_encode(name)
99
+ return "%s <%s>" % (encoded_name, address)
100
+ else:
101
+ quotes = ''
102
+ if specialsre.search(name):
103
+ quotes = '"'
104
+ name = escapesre.sub(r'\\\g<0>', name)
105
+ return '%s%s%s <%s>' % (quotes, name, quotes, address)
106
+ return address
107
+
108
+
109
+
110
+ def getaddresses(fieldvalues):
111
+ """Return a list of (REALNAME, EMAIL) for each fieldvalue."""
112
+ all = COMMASPACE.join(fieldvalues)
113
+ a = _AddressList(all)
114
+ return a.addresslist
115
+
116
+
117
+ def _format_timetuple_and_zone(timetuple, zone):
118
+ return '%s, %02d %s %04d %02d:%02d:%02d %s' % (
119
+ ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][timetuple[6]],
120
+ timetuple[2],
121
+ ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
122
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][timetuple[1] - 1],
123
+ timetuple[0], timetuple[3], timetuple[4], timetuple[5],
124
+ zone)
125
+
126
+ def formatdate(timeval=None, localtime=False, usegmt=False):
127
+ """Returns a date string as specified by RFC 2822, e.g.:
128
+
129
+ Fri, 09 Nov 2001 01:08:47 -0000
130
+
131
+ Optional timeval if given is a floating point time value as accepted by
132
+ gmtime() and localtime(), otherwise the current time is used.
133
+
134
+ Optional localtime is a flag that when True, interprets timeval, and
135
+ returns a date relative to the local timezone instead of UTC, properly
136
+ taking daylight savings time into account.
137
+
138
+ Optional argument usegmt means that the timezone is written out as
139
+ an ascii string, not numeric one (so "GMT" instead of "+0000"). This
140
+ is needed for HTTP, and is only used when localtime==False.
141
+ """
142
+ # Note: we cannot use strftime() because that honors the locale and RFC
143
+ # 2822 requires that day and month names be the English abbreviations.
144
+ if timeval is None:
145
+ timeval = time.time()
146
+ if localtime or usegmt:
147
+ dt = datetime.datetime.fromtimestamp(timeval, datetime.timezone.utc)
148
+ else:
149
+ dt = datetime.datetime.utcfromtimestamp(timeval)
150
+ if localtime:
151
+ dt = dt.astimezone()
152
+ usegmt = False
153
+ return format_datetime(dt, usegmt)
154
+
155
+ def format_datetime(dt, usegmt=False):
156
+ """Turn a datetime into a date string as specified in RFC 2822.
157
+
158
+ If usegmt is True, dt must be an aware datetime with an offset of zero. In
159
+ this case 'GMT' will be rendered instead of the normal +0000 required by
160
+ RFC2822. This is to support HTTP headers involving date stamps.
161
+ """
162
+ now = dt.timetuple()
163
+ if usegmt:
164
+ if dt.tzinfo is None or dt.tzinfo != datetime.timezone.utc:
165
+ raise ValueError("usegmt option requires a UTC datetime")
166
+ zone = 'GMT'
167
+ elif dt.tzinfo is None:
168
+ zone = '-0000'
169
+ else:
170
+ zone = dt.strftime("%z")
171
+ return _format_timetuple_and_zone(now, zone)
172
+
173
+
174
+ def make_msgid(idstring=None, domain=None):
175
+ """Returns a string suitable for RFC 2822 compliant Message-ID, e.g:
176
+
177
+ <142480216486.20800.16526388040877946887@nightshade.la.mastaler.com>
178
+
179
+ Optional idstring if given is a string used to strengthen the
180
+ uniqueness of the message id. Optional domain if given provides the
181
+ portion of the message id after the '@'. It defaults to the locally
182
+ defined hostname.
183
+ """
184
+ timeval = int(time.time()*100)
185
+ pid = os.getpid()
186
+ randint = random.getrandbits(64)
187
+ if idstring is None:
188
+ idstring = ''
189
+ else:
190
+ idstring = '.' + idstring
191
+ if domain is None:
192
+ domain = socket.getfqdn()
193
+ msgid = '<%d.%d.%d%s@%s>' % (timeval, pid, randint, idstring, domain)
194
+ return msgid
195
+
196
+
197
+ def parsedate_to_datetime(data):
198
+ *dtuple, tz = _parsedate_tz(data)
199
+ if tz is None:
200
+ return datetime.datetime(*dtuple[:6])
201
+ return datetime.datetime(*dtuple[:6],
202
+ tzinfo=datetime.timezone(datetime.timedelta(seconds=tz)))
203
+
204
+
205
+ def parseaddr(addr):
206
+ """
207
+ Parse addr into its constituent realname and email address parts.
208
+
209
+ Return a tuple of realname and email address, unless the parse fails, in
210
+ which case return a 2-tuple of ('', '').
211
+ """
212
+ addrs = _AddressList(addr).addresslist
213
+ if not addrs:
214
+ return '', ''
215
+ return addrs[0]
216
+
217
+
218
+ # rfc822.unquote() doesn't properly de-backslash-ify in Python pre-2.3.
219
+ def unquote(str):
220
+ """Remove quotes from a string."""
221
+ if len(str) > 1:
222
+ if str.startswith('"') and str.endswith('"'):
223
+ return str[1:-1].replace('\\\\', '\\').replace('\\"', '"')
224
+ if str.startswith('<') and str.endswith('>'):
225
+ return str[1:-1]
226
+ return str
227
+
228
+
229
+
230
+ # RFC2231-related functions - parameter encoding and decoding
231
+ def decode_rfc2231(s):
232
+ """Decode string according to RFC 2231"""
233
+ parts = s.split(TICK, 2)
234
+ if len(parts) <= 2:
235
+ return None, None, s
236
+ return parts
237
+
238
+
239
+ def encode_rfc2231(s, charset=None, language=None):
240
+ """Encode string according to RFC 2231.
241
+
242
+ If neither charset nor language is given, then s is returned as-is. If
243
+ charset is given but not language, the string is encoded using the empty
244
+ string for language.
245
+ """
246
+ s = urllib.parse.quote(s, safe='', encoding=charset or 'ascii')
247
+ if charset is None and language is None:
248
+ return s
249
+ if language is None:
250
+ language = ''
251
+ return "%s'%s'%s" % (charset, language, s)
252
+
253
+
254
+ rfc2231_continuation = re.compile(r'^(?P<name>\w+)\*((?P<num>[0-9]+)\*?)?$',
255
+ re.ASCII)
256
+
257
+ def decode_params(params):
258
+ """Decode parameters list according to RFC 2231.
259
+
260
+ params is a sequence of 2-tuples containing (param name, string value).
261
+ """
262
+ # Copy params so we don't mess with the original
263
+ params = params[:]
264
+ new_params = []
265
+ # Map parameter's name to a list of continuations. The values are a
266
+ # 3-tuple of the continuation number, the string value, and a flag
267
+ # specifying whether a particular segment is %-encoded.
268
+ rfc2231_params = {}
269
+ name, value = params.pop(0)
270
+ new_params.append((name, value))
271
+ while params:
272
+ name, value = params.pop(0)
273
+ if name.endswith('*'):
274
+ encoded = True
275
+ else:
276
+ encoded = False
277
+ value = unquote(value)
278
+ mo = rfc2231_continuation.match(name)
279
+ if mo:
280
+ name, num = mo.group('name', 'num')
281
+ if num is not None:
282
+ num = int(num)
283
+ rfc2231_params.setdefault(name, []).append((num, value, encoded))
284
+ else:
285
+ new_params.append((name, '"%s"' % quote(value)))
286
+ if rfc2231_params:
287
+ for name, continuations in rfc2231_params.items():
288
+ value = []
289
+ extended = False
290
+ # Sort by number
291
+ continuations.sort()
292
+ # And now append all values in numerical order, converting
293
+ # %-encodings for the encoded segments. If any of the
294
+ # continuation names ends in a *, then the entire string, after
295
+ # decoding segments and concatenating, must have the charset and
296
+ # language specifiers at the beginning of the string.
297
+ for num, s, encoded in continuations:
298
+ if encoded:
299
+ # Decode as "latin-1", so the characters in s directly
300
+ # represent the percent-encoded octet values.
301
+ # collapse_rfc2231_value treats this as an octet sequence.
302
+ s = urllib.parse.unquote(s, encoding="latin-1")
303
+ extended = True
304
+ value.append(s)
305
+ value = quote(EMPTYSTRING.join(value))
306
+ if extended:
307
+ charset, language, value = decode_rfc2231(value)
308
+ new_params.append((name, (charset, language, '"%s"' % value)))
309
+ else:
310
+ new_params.append((name, '"%s"' % value))
311
+ return new_params
312
+
313
+ def collapse_rfc2231_value(value, errors='replace',
314
+ fallback_charset='us-ascii'):
315
+ if not isinstance(value, tuple) or len(value) != 3:
316
+ return unquote(value)
317
+ # While value comes to us as a unicode string, we need it to be a bytes
318
+ # object. We do not want bytes() normal utf-8 decoder, we want a straight
319
+ # interpretation of the string as character bytes.
320
+ charset, language, text = value
321
+ if charset is None:
322
+ # Issue 17369: if charset/lang is None, decode_rfc2231 couldn't parse
323
+ # the value, so use the fallback_charset.
324
+ charset = fallback_charset
325
+ rawbytes = bytes(text, 'raw-unicode-escape')
326
+ try:
327
+ return str(rawbytes, charset, errors)
328
+ except LookupError:
329
+ # charset is not a known codec.
330
+ return unquote(text)
331
+
332
+
333
+ #
334
+ # datetime doesn't provide a localtime function yet, so provide one. Code
335
+ # adapted from the patch in issue 9527. This may not be perfect, but it is
336
+ # better than not having it.
337
+ #
338
+
339
+ def localtime(dt=None, isdst=-1):
340
+ """Return local time as an aware datetime object.
341
+
342
+ If called without arguments, return current time. Otherwise *dt*
343
+ argument should be a datetime instance, and it is converted to the
344
+ local time zone according to the system time zone database. If *dt* is
345
+ naive (that is, dt.tzinfo is None), it is assumed to be in local time.
346
+ In this case, a positive or zero value for *isdst* causes localtime to
347
+ presume initially that summer time (for example, Daylight Saving Time)
348
+ is or is not (respectively) in effect for the specified time. A
349
+ negative value for *isdst* causes the localtime() function to attempt
350
+ to divine whether summer time is in effect for the specified time.
351
+
352
+ """
353
+ if dt is None:
354
+ return datetime.datetime.now(datetime.timezone.utc).astimezone()
355
+ if dt.tzinfo is not None:
356
+ return dt.astimezone()
357
+ # We have a naive datetime. Convert to a (localtime) timetuple and pass to
358
+ # system mktime together with the isdst hint. System mktime will return
359
+ # seconds since epoch.
360
+ tm = dt.timetuple()[:-1] + (isdst,)
361
+ seconds = time.mktime(tm)
362
+ localtm = time.localtime(seconds)
363
+ try:
364
+ delta = datetime.timedelta(seconds=localtm.tm_gmtoff)
365
+ tz = datetime.timezone(delta, localtm.tm_zone)
366
+ except AttributeError:
367
+ # Compute UTC offset and compare with the value implied by tm_isdst.
368
+ # If the values match, use the zone name implied by tm_isdst.
369
+ delta = dt - datetime.datetime(*time.gmtime(seconds)[:6])
370
+ dst = time.daylight and localtm.tm_isdst > 0
371
+ gmtoff = -(time.altzone if dst else time.timezone)
372
+ if delta == datetime.timedelta(seconds=gmtoff):
373
+ tz = datetime.timezone(delta, time.tzname[dst])
374
+ else:
375
+ tz = datetime.timezone(delta)
376
+ return dt.replace(tzinfo=tz)
my_container_sandbox/workspace/anaconda3/lib/python3.8/json/__init__.py ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ r"""JSON (JavaScript Object Notation) <http://json.org> is a subset of
2
+ JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
3
+ interchange format.
4
+
5
+ :mod:`json` exposes an API familiar to users of the standard library
6
+ :mod:`marshal` and :mod:`pickle` modules. It is derived from a
7
+ version of the externally maintained simplejson library.
8
+
9
+ Encoding basic Python object hierarchies::
10
+
11
+ >>> import json
12
+ >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
13
+ '["foo", {"bar": ["baz", null, 1.0, 2]}]'
14
+ >>> print(json.dumps("\"foo\bar"))
15
+ "\"foo\bar"
16
+ >>> print(json.dumps('\u1234'))
17
+ "\u1234"
18
+ >>> print(json.dumps('\\'))
19
+ "\\"
20
+ >>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
21
+ {"a": 0, "b": 0, "c": 0}
22
+ >>> from io import StringIO
23
+ >>> io = StringIO()
24
+ >>> json.dump(['streaming API'], io)
25
+ >>> io.getvalue()
26
+ '["streaming API"]'
27
+
28
+ Compact encoding::
29
+
30
+ >>> import json
31
+ >>> mydict = {'4': 5, '6': 7}
32
+ >>> json.dumps([1,2,3,mydict], separators=(',', ':'))
33
+ '[1,2,3,{"4":5,"6":7}]'
34
+
35
+ Pretty printing::
36
+
37
+ >>> import json
38
+ >>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4))
39
+ {
40
+ "4": 5,
41
+ "6": 7
42
+ }
43
+
44
+ Decoding JSON::
45
+
46
+ >>> import json
47
+ >>> obj = ['foo', {'bar': ['baz', None, 1.0, 2]}]
48
+ >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj
49
+ True
50
+ >>> json.loads('"\\"foo\\bar"') == '"foo\x08ar'
51
+ True
52
+ >>> from io import StringIO
53
+ >>> io = StringIO('["streaming API"]')
54
+ >>> json.load(io)[0] == 'streaming API'
55
+ True
56
+
57
+ Specializing JSON object decoding::
58
+
59
+ >>> import json
60
+ >>> def as_complex(dct):
61
+ ... if '__complex__' in dct:
62
+ ... return complex(dct['real'], dct['imag'])
63
+ ... return dct
64
+ ...
65
+ >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
66
+ ... object_hook=as_complex)
67
+ (1+2j)
68
+ >>> from decimal import Decimal
69
+ >>> json.loads('1.1', parse_float=Decimal) == Decimal('1.1')
70
+ True
71
+
72
+ Specializing JSON object encoding::
73
+
74
+ >>> import json
75
+ >>> def encode_complex(obj):
76
+ ... if isinstance(obj, complex):
77
+ ... return [obj.real, obj.imag]
78
+ ... raise TypeError(f'Object of type {obj.__class__.__name__} '
79
+ ... f'is not JSON serializable')
80
+ ...
81
+ >>> json.dumps(2 + 1j, default=encode_complex)
82
+ '[2.0, 1.0]'
83
+ >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j)
84
+ '[2.0, 1.0]'
85
+ >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j))
86
+ '[2.0, 1.0]'
87
+
88
+
89
+ Using json.tool from the shell to validate and pretty-print::
90
+
91
+ $ echo '{"json":"obj"}' | python -m json.tool
92
+ {
93
+ "json": "obj"
94
+ }
95
+ $ echo '{ 1.2:3.4}' | python -m json.tool
96
+ Expecting property name enclosed in double quotes: line 1 column 3 (char 2)
97
+ """
98
+ __version__ = '2.0.9'
99
+ __all__ = [
100
+ 'dump', 'dumps', 'load', 'loads',
101
+ 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder',
102
+ ]
103
+
104
+ __author__ = 'Bob Ippolito <bob@redivi.com>'
105
+
106
+ from .decoder import JSONDecoder, JSONDecodeError
107
+ from .encoder import JSONEncoder
108
+ import codecs
109
+
110
+ _default_encoder = JSONEncoder(
111
+ skipkeys=False,
112
+ ensure_ascii=True,
113
+ check_circular=True,
114
+ allow_nan=True,
115
+ indent=None,
116
+ separators=None,
117
+ default=None,
118
+ )
119
+
120
+ def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True,
121
+ allow_nan=True, cls=None, indent=None, separators=None,
122
+ default=None, sort_keys=False, **kw):
123
+ """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
124
+ ``.write()``-supporting file-like object).
125
+
126
+ If ``skipkeys`` is true then ``dict`` keys that are not basic types
127
+ (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
128
+ instead of raising a ``TypeError``.
129
+
130
+ If ``ensure_ascii`` is false, then the strings written to ``fp`` can
131
+ contain non-ASCII characters if they appear in strings contained in
132
+ ``obj``. Otherwise, all such characters are escaped in JSON strings.
133
+
134
+ If ``check_circular`` is false, then the circular reference check
135
+ for container types will be skipped and a circular reference will
136
+ result in an ``OverflowError`` (or worse).
137
+
138
+ If ``allow_nan`` is false, then it will be a ``ValueError`` to
139
+ serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
140
+ in strict compliance of the JSON specification, instead of using the
141
+ JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
142
+
143
+ If ``indent`` is a non-negative integer, then JSON array elements and
144
+ object members will be pretty-printed with that indent level. An indent
145
+ level of 0 will only insert newlines. ``None`` is the most compact
146
+ representation.
147
+
148
+ If specified, ``separators`` should be an ``(item_separator, key_separator)``
149
+ tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
150
+ ``(',', ': ')`` otherwise. To get the most compact JSON representation,
151
+ you should specify ``(',', ':')`` to eliminate whitespace.
152
+
153
+ ``default(obj)`` is a function that should return a serializable version
154
+ of obj or raise TypeError. The default simply raises TypeError.
155
+
156
+ If *sort_keys* is true (default: ``False``), then the output of
157
+ dictionaries will be sorted by key.
158
+
159
+ To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
160
+ ``.default()`` method to serialize additional types), specify it with
161
+ the ``cls`` kwarg; otherwise ``JSONEncoder`` is used.
162
+
163
+ """
164
+ # cached encoder
165
+ if (not skipkeys and ensure_ascii and
166
+ check_circular and allow_nan and
167
+ cls is None and indent is None and separators is None and
168
+ default is None and not sort_keys and not kw):
169
+ iterable = _default_encoder.iterencode(obj)
170
+ else:
171
+ if cls is None:
172
+ cls = JSONEncoder
173
+ iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
174
+ check_circular=check_circular, allow_nan=allow_nan, indent=indent,
175
+ separators=separators,
176
+ default=default, sort_keys=sort_keys, **kw).iterencode(obj)
177
+ # could accelerate with writelines in some versions of Python, at
178
+ # a debuggability cost
179
+ for chunk in iterable:
180
+ fp.write(chunk)
181
+
182
+
183
+ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
184
+ allow_nan=True, cls=None, indent=None, separators=None,
185
+ default=None, sort_keys=False, **kw):
186
+ """Serialize ``obj`` to a JSON formatted ``str``.
187
+
188
+ If ``skipkeys`` is true then ``dict`` keys that are not basic types
189
+ (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
190
+ instead of raising a ``TypeError``.
191
+
192
+ If ``ensure_ascii`` is false, then the return value can contain non-ASCII
193
+ characters if they appear in strings contained in ``obj``. Otherwise, all
194
+ such characters are escaped in JSON strings.
195
+
196
+ If ``check_circular`` is false, then the circular reference check
197
+ for container types will be skipped and a circular reference will
198
+ result in an ``OverflowError`` (or worse).
199
+
200
+ If ``allow_nan`` is false, then it will be a ``ValueError`` to
201
+ serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
202
+ strict compliance of the JSON specification, instead of using the
203
+ JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
204
+
205
+ If ``indent`` is a non-negative integer, then JSON array elements and
206
+ object members will be pretty-printed with that indent level. An indent
207
+ level of 0 will only insert newlines. ``None`` is the most compact
208
+ representation.
209
+
210
+ If specified, ``separators`` should be an ``(item_separator, key_separator)``
211
+ tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
212
+ ``(',', ': ')`` otherwise. To get the most compact JSON representation,
213
+ you should specify ``(',', ':')`` to eliminate whitespace.
214
+
215
+ ``default(obj)`` is a function that should return a serializable version
216
+ of obj or raise TypeError. The default simply raises TypeError.
217
+
218
+ If *sort_keys* is true (default: ``False``), then the output of
219
+ dictionaries will be sorted by key.
220
+
221
+ To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
222
+ ``.default()`` method to serialize additional types), specify it with
223
+ the ``cls`` kwarg; otherwise ``JSONEncoder`` is used.
224
+
225
+ """
226
+ # cached encoder
227
+ if (not skipkeys and ensure_ascii and
228
+ check_circular and allow_nan and
229
+ cls is None and indent is None and separators is None and
230
+ default is None and not sort_keys and not kw):
231
+ return _default_encoder.encode(obj)
232
+ if cls is None:
233
+ cls = JSONEncoder
234
+ return cls(
235
+ skipkeys=skipkeys, ensure_ascii=ensure_ascii,
236
+ check_circular=check_circular, allow_nan=allow_nan, indent=indent,
237
+ separators=separators, default=default, sort_keys=sort_keys,
238
+ **kw).encode(obj)
239
+
240
+
241
+ _default_decoder = JSONDecoder(object_hook=None, object_pairs_hook=None)
242
+
243
+
244
+ def detect_encoding(b):
245
+ bstartswith = b.startswith
246
+ if bstartswith((codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE)):
247
+ return 'utf-32'
248
+ if bstartswith((codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE)):
249
+ return 'utf-16'
250
+ if bstartswith(codecs.BOM_UTF8):
251
+ return 'utf-8-sig'
252
+
253
+ if len(b) >= 4:
254
+ if not b[0]:
255
+ # 00 00 -- -- - utf-32-be
256
+ # 00 XX -- -- - utf-16-be
257
+ return 'utf-16-be' if b[1] else 'utf-32-be'
258
+ if not b[1]:
259
+ # XX 00 00 00 - utf-32-le
260
+ # XX 00 00 XX - utf-16-le
261
+ # XX 00 XX -- - utf-16-le
262
+ return 'utf-16-le' if b[2] or b[3] else 'utf-32-le'
263
+ elif len(b) == 2:
264
+ if not b[0]:
265
+ # 00 XX - utf-16-be
266
+ return 'utf-16-be'
267
+ if not b[1]:
268
+ # XX 00 - utf-16-le
269
+ return 'utf-16-le'
270
+ # default
271
+ return 'utf-8'
272
+
273
+
274
+ def load(fp, *, cls=None, object_hook=None, parse_float=None,
275
+ parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
276
+ """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
277
+ a JSON document) to a Python object.
278
+
279
+ ``object_hook`` is an optional function that will be called with the
280
+ result of any object literal decode (a ``dict``). The return value of
281
+ ``object_hook`` will be used instead of the ``dict``. This feature
282
+ can be used to implement custom decoders (e.g. JSON-RPC class hinting).
283
+
284
+ ``object_pairs_hook`` is an optional function that will be called with the
285
+ result of any object literal decoded with an ordered list of pairs. The
286
+ return value of ``object_pairs_hook`` will be used instead of the ``dict``.
287
+ This feature can be used to implement custom decoders. If ``object_hook``
288
+ is also defined, the ``object_pairs_hook`` takes priority.
289
+
290
+ To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
291
+ kwarg; otherwise ``JSONDecoder`` is used.
292
+ """
293
+ return loads(fp.read(),
294
+ cls=cls, object_hook=object_hook,
295
+ parse_float=parse_float, parse_int=parse_int,
296
+ parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
297
+
298
+
299
+ def loads(s, *, cls=None, object_hook=None, parse_float=None,
300
+ parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
301
+ """Deserialize ``s`` (a ``str``, ``bytes`` or ``bytearray`` instance
302
+ containing a JSON document) to a Python object.
303
+
304
+ ``object_hook`` is an optional function that will be called with the
305
+ result of any object literal decode (a ``dict``). The return value of
306
+ ``object_hook`` will be used instead of the ``dict``. This feature
307
+ can be used to implement custom decoders (e.g. JSON-RPC class hinting).
308
+
309
+ ``object_pairs_hook`` is an optional function that will be called with the
310
+ result of any object literal decoded with an ordered list of pairs. The
311
+ return value of ``object_pairs_hook`` will be used instead of the ``dict``.
312
+ This feature can be used to implement custom decoders. If ``object_hook``
313
+ is also defined, the ``object_pairs_hook`` takes priority.
314
+
315
+ ``parse_float``, if specified, will be called with the string
316
+ of every JSON float to be decoded. By default this is equivalent to
317
+ float(num_str). This can be used to use another datatype or parser
318
+ for JSON floats (e.g. decimal.Decimal).
319
+
320
+ ``parse_int``, if specified, will be called with the string
321
+ of every JSON int to be decoded. By default this is equivalent to
322
+ int(num_str). This can be used to use another datatype or parser
323
+ for JSON integers (e.g. float).
324
+
325
+ ``parse_constant``, if specified, will be called with one of the
326
+ following strings: -Infinity, Infinity, NaN.
327
+ This can be used to raise an exception if invalid JSON numbers
328
+ are encountered.
329
+
330
+ To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
331
+ kwarg; otherwise ``JSONDecoder`` is used.
332
+
333
+ The ``encoding`` argument is ignored and deprecated since Python 3.1.
334
+ """
335
+ if isinstance(s, str):
336
+ if s.startswith('\ufeff'):
337
+ raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)",
338
+ s, 0)
339
+ else:
340
+ if not isinstance(s, (bytes, bytearray)):
341
+ raise TypeError(f'the JSON object must be str, bytes or bytearray, '
342
+ f'not {s.__class__.__name__}')
343
+ s = s.decode(detect_encoding(s), 'surrogatepass')
344
+
345
+ if "encoding" in kw:
346
+ import warnings
347
+ warnings.warn(
348
+ "'encoding' is ignored and deprecated. It will be removed in Python 3.9",
349
+ DeprecationWarning,
350
+ stacklevel=2
351
+ )
352
+ del kw['encoding']
353
+
354
+ if (cls is None and object_hook is None and
355
+ parse_int is None and parse_float is None and
356
+ parse_constant is None and object_pairs_hook is None and not kw):
357
+ return _default_decoder.decode(s)
358
+ if cls is None:
359
+ cls = JSONDecoder
360
+ if object_hook is not None:
361
+ kw['object_hook'] = object_hook
362
+ if object_pairs_hook is not None:
363
+ kw['object_pairs_hook'] = object_pairs_hook
364
+ if parse_float is not None:
365
+ kw['parse_float'] = parse_float
366
+ if parse_int is not None:
367
+ kw['parse_int'] = parse_int
368
+ if parse_constant is not None:
369
+ kw['parse_constant'] = parse_constant
370
+ return cls(**kw).decode(s)
my_container_sandbox/workspace/anaconda3/lib/python3.8/json/decoder.py ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of JSONDecoder
2
+ """
3
+ import re
4
+
5
+ from json import scanner
6
+ try:
7
+ from _json import scanstring as c_scanstring
8
+ except ImportError:
9
+ c_scanstring = None
10
+
11
+ __all__ = ['JSONDecoder', 'JSONDecodeError']
12
+
13
+ FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
14
+
15
+ NaN = float('nan')
16
+ PosInf = float('inf')
17
+ NegInf = float('-inf')
18
+
19
+
20
+ class JSONDecodeError(ValueError):
21
+ """Subclass of ValueError with the following additional properties:
22
+
23
+ msg: The unformatted error message
24
+ doc: The JSON document being parsed
25
+ pos: The start index of doc where parsing failed
26
+ lineno: The line corresponding to pos
27
+ colno: The column corresponding to pos
28
+
29
+ """
30
+ # Note that this exception is used from _json
31
+ def __init__(self, msg, doc, pos):
32
+ lineno = doc.count('\n', 0, pos) + 1
33
+ colno = pos - doc.rfind('\n', 0, pos)
34
+ errmsg = '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos)
35
+ ValueError.__init__(self, errmsg)
36
+ self.msg = msg
37
+ self.doc = doc
38
+ self.pos = pos
39
+ self.lineno = lineno
40
+ self.colno = colno
41
+
42
+ def __reduce__(self):
43
+ return self.__class__, (self.msg, self.doc, self.pos)
44
+
45
+
46
+ _CONSTANTS = {
47
+ '-Infinity': NegInf,
48
+ 'Infinity': PosInf,
49
+ 'NaN': NaN,
50
+ }
51
+
52
+
53
+ STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)
54
+ BACKSLASH = {
55
+ '"': '"', '\\': '\\', '/': '/',
56
+ 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t',
57
+ }
58
+
59
+ def _decode_uXXXX(s, pos):
60
+ esc = s[pos + 1:pos + 5]
61
+ if len(esc) == 4 and esc[1] not in 'xX':
62
+ try:
63
+ return int(esc, 16)
64
+ except ValueError:
65
+ pass
66
+ msg = "Invalid \\uXXXX escape"
67
+ raise JSONDecodeError(msg, s, pos)
68
+
69
+ def py_scanstring(s, end, strict=True,
70
+ _b=BACKSLASH, _m=STRINGCHUNK.match):
71
+ """Scan the string s for a JSON string. End is the index of the
72
+ character in s after the quote that started the JSON string.
73
+ Unescapes all valid JSON string escape sequences and raises ValueError
74
+ on attempt to decode an invalid string. If strict is False then literal
75
+ control characters are allowed in the string.
76
+
77
+ Returns a tuple of the decoded string and the index of the character in s
78
+ after the end quote."""
79
+ chunks = []
80
+ _append = chunks.append
81
+ begin = end - 1
82
+ while 1:
83
+ chunk = _m(s, end)
84
+ if chunk is None:
85
+ raise JSONDecodeError("Unterminated string starting at", s, begin)
86
+ end = chunk.end()
87
+ content, terminator = chunk.groups()
88
+ # Content is contains zero or more unescaped string characters
89
+ if content:
90
+ _append(content)
91
+ # Terminator is the end of string, a literal control character,
92
+ # or a backslash denoting that an escape sequence follows
93
+ if terminator == '"':
94
+ break
95
+ elif terminator != '\\':
96
+ if strict:
97
+ #msg = "Invalid control character %r at" % (terminator,)
98
+ msg = "Invalid control character {0!r} at".format(terminator)
99
+ raise JSONDecodeError(msg, s, end)
100
+ else:
101
+ _append(terminator)
102
+ continue
103
+ try:
104
+ esc = s[end]
105
+ except IndexError:
106
+ raise JSONDecodeError("Unterminated string starting at",
107
+ s, begin) from None
108
+ # If not a unicode escape sequence, must be in the lookup table
109
+ if esc != 'u':
110
+ try:
111
+ char = _b[esc]
112
+ except KeyError:
113
+ msg = "Invalid \\escape: {0!r}".format(esc)
114
+ raise JSONDecodeError(msg, s, end)
115
+ end += 1
116
+ else:
117
+ uni = _decode_uXXXX(s, end)
118
+ end += 5
119
+ if 0xd800 <= uni <= 0xdbff and s[end:end + 2] == '\\u':
120
+ uni2 = _decode_uXXXX(s, end + 1)
121
+ if 0xdc00 <= uni2 <= 0xdfff:
122
+ uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))
123
+ end += 6
124
+ char = chr(uni)
125
+ _append(char)
126
+ return ''.join(chunks), end
127
+
128
+
129
+ # Use speedup if available
130
+ scanstring = c_scanstring or py_scanstring
131
+
132
+ WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS)
133
+ WHITESPACE_STR = ' \t\n\r'
134
+
135
+
136
+ def JSONObject(s_and_end, strict, scan_once, object_hook, object_pairs_hook,
137
+ memo=None, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
138
+ s, end = s_and_end
139
+ pairs = []
140
+ pairs_append = pairs.append
141
+ # Backwards compatibility
142
+ if memo is None:
143
+ memo = {}
144
+ memo_get = memo.setdefault
145
+ # Use a slice to prevent IndexError from being raised, the following
146
+ # check will raise a more specific ValueError if the string is empty
147
+ nextchar = s[end:end + 1]
148
+ # Normally we expect nextchar == '"'
149
+ if nextchar != '"':
150
+ if nextchar in _ws:
151
+ end = _w(s, end).end()
152
+ nextchar = s[end:end + 1]
153
+ # Trivial empty object
154
+ if nextchar == '}':
155
+ if object_pairs_hook is not None:
156
+ result = object_pairs_hook(pairs)
157
+ return result, end + 1
158
+ pairs = {}
159
+ if object_hook is not None:
160
+ pairs = object_hook(pairs)
161
+ return pairs, end + 1
162
+ elif nextchar != '"':
163
+ raise JSONDecodeError(
164
+ "Expecting property name enclosed in double quotes", s, end)
165
+ end += 1
166
+ while True:
167
+ key, end = scanstring(s, end, strict)
168
+ key = memo_get(key, key)
169
+ # To skip some function call overhead we optimize the fast paths where
170
+ # the JSON key separator is ": " or just ":".
171
+ if s[end:end + 1] != ':':
172
+ end = _w(s, end).end()
173
+ if s[end:end + 1] != ':':
174
+ raise JSONDecodeError("Expecting ':' delimiter", s, end)
175
+ end += 1
176
+
177
+ try:
178
+ if s[end] in _ws:
179
+ end += 1
180
+ if s[end] in _ws:
181
+ end = _w(s, end + 1).end()
182
+ except IndexError:
183
+ pass
184
+
185
+ try:
186
+ value, end = scan_once(s, end)
187
+ except StopIteration as err:
188
+ raise JSONDecodeError("Expecting value", s, err.value) from None
189
+ pairs_append((key, value))
190
+ try:
191
+ nextchar = s[end]
192
+ if nextchar in _ws:
193
+ end = _w(s, end + 1).end()
194
+ nextchar = s[end]
195
+ except IndexError:
196
+ nextchar = ''
197
+ end += 1
198
+
199
+ if nextchar == '}':
200
+ break
201
+ elif nextchar != ',':
202
+ raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
203
+ end = _w(s, end).end()
204
+ nextchar = s[end:end + 1]
205
+ end += 1
206
+ if nextchar != '"':
207
+ raise JSONDecodeError(
208
+ "Expecting property name enclosed in double quotes", s, end - 1)
209
+ if object_pairs_hook is not None:
210
+ result = object_pairs_hook(pairs)
211
+ return result, end
212
+ pairs = dict(pairs)
213
+ if object_hook is not None:
214
+ pairs = object_hook(pairs)
215
+ return pairs, end
216
+
217
+ def JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
218
+ s, end = s_and_end
219
+ values = []
220
+ nextchar = s[end:end + 1]
221
+ if nextchar in _ws:
222
+ end = _w(s, end + 1).end()
223
+ nextchar = s[end:end + 1]
224
+ # Look-ahead for trivial empty array
225
+ if nextchar == ']':
226
+ return values, end + 1
227
+ _append = values.append
228
+ while True:
229
+ try:
230
+ value, end = scan_once(s, end)
231
+ except StopIteration as err:
232
+ raise JSONDecodeError("Expecting value", s, err.value) from None
233
+ _append(value)
234
+ nextchar = s[end:end + 1]
235
+ if nextchar in _ws:
236
+ end = _w(s, end + 1).end()
237
+ nextchar = s[end:end + 1]
238
+ end += 1
239
+ if nextchar == ']':
240
+ break
241
+ elif nextchar != ',':
242
+ raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
243
+ try:
244
+ if s[end] in _ws:
245
+ end += 1
246
+ if s[end] in _ws:
247
+ end = _w(s, end + 1).end()
248
+ except IndexError:
249
+ pass
250
+
251
+ return values, end
252
+
253
+
254
+ class JSONDecoder(object):
255
+ """Simple JSON <http://json.org> decoder
256
+
257
+ Performs the following translations in decoding by default:
258
+
259
+ +---------------+-------------------+
260
+ | JSON | Python |
261
+ +===============+===================+
262
+ | object | dict |
263
+ +---------------+-------------------+
264
+ | array | list |
265
+ +---------------+-------------------+
266
+ | string | str |
267
+ +---------------+-------------------+
268
+ | number (int) | int |
269
+ +---------------+-------------------+
270
+ | number (real) | float |
271
+ +---------------+-------------------+
272
+ | true | True |
273
+ +---------------+-------------------+
274
+ | false | False |
275
+ +---------------+-------------------+
276
+ | null | None |
277
+ +---------------+-------------------+
278
+
279
+ It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
280
+ their corresponding ``float`` values, which is outside the JSON spec.
281
+
282
+ """
283
+
284
+ def __init__(self, *, object_hook=None, parse_float=None,
285
+ parse_int=None, parse_constant=None, strict=True,
286
+ object_pairs_hook=None):
287
+ """``object_hook``, if specified, will be called with the result
288
+ of every JSON object decoded and its return value will be used in
289
+ place of the given ``dict``. This can be used to provide custom
290
+ deserializations (e.g. to support JSON-RPC class hinting).
291
+
292
+ ``object_pairs_hook``, if specified will be called with the result of
293
+ every JSON object decoded with an ordered list of pairs. The return
294
+ value of ``object_pairs_hook`` will be used instead of the ``dict``.
295
+ This feature can be used to implement custom decoders.
296
+ If ``object_hook`` is also defined, the ``object_pairs_hook`` takes
297
+ priority.
298
+
299
+ ``parse_float``, if specified, will be called with the string
300
+ of every JSON float to be decoded. By default this is equivalent to
301
+ float(num_str). This can be used to use another datatype or parser
302
+ for JSON floats (e.g. decimal.Decimal).
303
+
304
+ ``parse_int``, if specified, will be called with the string
305
+ of every JSON int to be decoded. By default this is equivalent to
306
+ int(num_str). This can be used to use another datatype or parser
307
+ for JSON integers (e.g. float).
308
+
309
+ ``parse_constant``, if specified, will be called with one of the
310
+ following strings: -Infinity, Infinity, NaN.
311
+ This can be used to raise an exception if invalid JSON numbers
312
+ are encountered.
313
+
314
+ If ``strict`` is false (true is the default), then control
315
+ characters will be allowed inside strings. Control characters in
316
+ this context are those with character codes in the 0-31 range,
317
+ including ``'\\t'`` (tab), ``'\\n'``, ``'\\r'`` and ``'\\0'``.
318
+ """
319
+ self.object_hook = object_hook
320
+ self.parse_float = parse_float or float
321
+ self.parse_int = parse_int or int
322
+ self.parse_constant = parse_constant or _CONSTANTS.__getitem__
323
+ self.strict = strict
324
+ self.object_pairs_hook = object_pairs_hook
325
+ self.parse_object = JSONObject
326
+ self.parse_array = JSONArray
327
+ self.parse_string = scanstring
328
+ self.memo = {}
329
+ self.scan_once = scanner.make_scanner(self)
330
+
331
+
332
+ def decode(self, s, _w=WHITESPACE.match):
333
+ """Return the Python representation of ``s`` (a ``str`` instance
334
+ containing a JSON document).
335
+
336
+ """
337
+ obj, end = self.raw_decode(s, idx=_w(s, 0).end())
338
+ end = _w(s, end).end()
339
+ if end != len(s):
340
+ raise JSONDecodeError("Extra data", s, end)
341
+ return obj
342
+
343
+ def raw_decode(self, s, idx=0):
344
+ """Decode a JSON document from ``s`` (a ``str`` beginning with
345
+ a JSON document) and return a 2-tuple of the Python
346
+ representation and the index in ``s`` where the document ended.
347
+
348
+ This can be used to decode a JSON document from a string that may
349
+ have extraneous data at the end.
350
+
351
+ """
352
+ try:
353
+ obj, end = self.scan_once(s, idx)
354
+ except StopIteration as err:
355
+ raise JSONDecodeError("Expecting value", s, err.value) from None
356
+ return obj, end
my_container_sandbox/workspace/anaconda3/lib/python3.8/json/encoder.py ADDED
@@ -0,0 +1,442 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of JSONEncoder
2
+ """
3
+ import re
4
+
5
+ try:
6
+ from _json import encode_basestring_ascii as c_encode_basestring_ascii
7
+ except ImportError:
8
+ c_encode_basestring_ascii = None
9
+ try:
10
+ from _json import encode_basestring as c_encode_basestring
11
+ except ImportError:
12
+ c_encode_basestring = None
13
+ try:
14
+ from _json import make_encoder as c_make_encoder
15
+ except ImportError:
16
+ c_make_encoder = None
17
+
18
+ ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
19
+ ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
20
+ HAS_UTF8 = re.compile(b'[\x80-\xff]')
21
+ ESCAPE_DCT = {
22
+ '\\': '\\\\',
23
+ '"': '\\"',
24
+ '\b': '\\b',
25
+ '\f': '\\f',
26
+ '\n': '\\n',
27
+ '\r': '\\r',
28
+ '\t': '\\t',
29
+ }
30
+ for i in range(0x20):
31
+ ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i))
32
+ #ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
33
+
34
+ INFINITY = float('inf')
35
+
36
+ def py_encode_basestring(s):
37
+ """Return a JSON representation of a Python string
38
+
39
+ """
40
+ def replace(match):
41
+ return ESCAPE_DCT[match.group(0)]
42
+ return '"' + ESCAPE.sub(replace, s) + '"'
43
+
44
+
45
+ encode_basestring = (c_encode_basestring or py_encode_basestring)
46
+
47
+
48
+ def py_encode_basestring_ascii(s):
49
+ """Return an ASCII-only JSON representation of a Python string
50
+
51
+ """
52
+ def replace(match):
53
+ s = match.group(0)
54
+ try:
55
+ return ESCAPE_DCT[s]
56
+ except KeyError:
57
+ n = ord(s)
58
+ if n < 0x10000:
59
+ return '\\u{0:04x}'.format(n)
60
+ #return '\\u%04x' % (n,)
61
+ else:
62
+ # surrogate pair
63
+ n -= 0x10000
64
+ s1 = 0xd800 | ((n >> 10) & 0x3ff)
65
+ s2 = 0xdc00 | (n & 0x3ff)
66
+ return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
67
+ return '"' + ESCAPE_ASCII.sub(replace, s) + '"'
68
+
69
+
70
+ encode_basestring_ascii = (
71
+ c_encode_basestring_ascii or py_encode_basestring_ascii)
72
+
73
+ class JSONEncoder(object):
74
+ """Extensible JSON <http://json.org> encoder for Python data structures.
75
+
76
+ Supports the following objects and types by default:
77
+
78
+ +-------------------+---------------+
79
+ | Python | JSON |
80
+ +===================+===============+
81
+ | dict | object |
82
+ +-------------------+---------------+
83
+ | list, tuple | array |
84
+ +-------------------+---------------+
85
+ | str | string |
86
+ +-------------------+---------------+
87
+ | int, float | number |
88
+ +-------------------+---------------+
89
+ | True | true |
90
+ +-------------------+---------------+
91
+ | False | false |
92
+ +-------------------+---------------+
93
+ | None | null |
94
+ +-------------------+---------------+
95
+
96
+ To extend this to recognize other objects, subclass and implement a
97
+ ``.default()`` method with another method that returns a serializable
98
+ object for ``o`` if possible, otherwise it should call the superclass
99
+ implementation (to raise ``TypeError``).
100
+
101
+ """
102
+ item_separator = ', '
103
+ key_separator = ': '
104
+ def __init__(self, *, skipkeys=False, ensure_ascii=True,
105
+ check_circular=True, allow_nan=True, sort_keys=False,
106
+ indent=None, separators=None, default=None):
107
+ """Constructor for JSONEncoder, with sensible defaults.
108
+
109
+ If skipkeys is false, then it is a TypeError to attempt
110
+ encoding of keys that are not str, int, float or None. If
111
+ skipkeys is True, such items are simply skipped.
112
+
113
+ If ensure_ascii is true, the output is guaranteed to be str
114
+ objects with all incoming non-ASCII characters escaped. If
115
+ ensure_ascii is false, the output can contain non-ASCII characters.
116
+
117
+ If check_circular is true, then lists, dicts, and custom encoded
118
+ objects will be checked for circular references during encoding to
119
+ prevent an infinite recursion (which would cause an OverflowError).
120
+ Otherwise, no such check takes place.
121
+
122
+ If allow_nan is true, then NaN, Infinity, and -Infinity will be
123
+ encoded as such. This behavior is not JSON specification compliant,
124
+ but is consistent with most JavaScript based encoders and decoders.
125
+ Otherwise, it will be a ValueError to encode such floats.
126
+
127
+ If sort_keys is true, then the output of dictionaries will be
128
+ sorted by key; this is useful for regression tests to ensure
129
+ that JSON serializations can be compared on a day-to-day basis.
130
+
131
+ If indent is a non-negative integer, then JSON array
132
+ elements and object members will be pretty-printed with that
133
+ indent level. An indent level of 0 will only insert newlines.
134
+ None is the most compact representation.
135
+
136
+ If specified, separators should be an (item_separator, key_separator)
137
+ tuple. The default is (', ', ': ') if *indent* is ``None`` and
138
+ (',', ': ') otherwise. To get the most compact JSON representation,
139
+ you should specify (',', ':') to eliminate whitespace.
140
+
141
+ If specified, default is a function that gets called for objects
142
+ that can't otherwise be serialized. It should return a JSON encodable
143
+ version of the object or raise a ``TypeError``.
144
+
145
+ """
146
+
147
+ self.skipkeys = skipkeys
148
+ self.ensure_ascii = ensure_ascii
149
+ self.check_circular = check_circular
150
+ self.allow_nan = allow_nan
151
+ self.sort_keys = sort_keys
152
+ self.indent = indent
153
+ if separators is not None:
154
+ self.item_separator, self.key_separator = separators
155
+ elif indent is not None:
156
+ self.item_separator = ','
157
+ if default is not None:
158
+ self.default = default
159
+
160
+ def default(self, o):
161
+ """Implement this method in a subclass such that it returns
162
+ a serializable object for ``o``, or calls the base implementation
163
+ (to raise a ``TypeError``).
164
+
165
+ For example, to support arbitrary iterators, you could
166
+ implement default like this::
167
+
168
+ def default(self, o):
169
+ try:
170
+ iterable = iter(o)
171
+ except TypeError:
172
+ pass
173
+ else:
174
+ return list(iterable)
175
+ # Let the base class default method raise the TypeError
176
+ return JSONEncoder.default(self, o)
177
+
178
+ """
179
+ raise TypeError(f'Object of type {o.__class__.__name__} '
180
+ f'is not JSON serializable')
181
+
182
+ def encode(self, o):
183
+ """Return a JSON string representation of a Python data structure.
184
+
185
+ >>> from json.encoder import JSONEncoder
186
+ >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
187
+ '{"foo": ["bar", "baz"]}'
188
+
189
+ """
190
+ # This is for extremely simple cases and benchmarks.
191
+ if isinstance(o, str):
192
+ if self.ensure_ascii:
193
+ return encode_basestring_ascii(o)
194
+ else:
195
+ return encode_basestring(o)
196
+ # This doesn't pass the iterator directly to ''.join() because the
197
+ # exceptions aren't as detailed. The list call should be roughly
198
+ # equivalent to the PySequence_Fast that ''.join() would do.
199
+ chunks = self.iterencode(o, _one_shot=True)
200
+ if not isinstance(chunks, (list, tuple)):
201
+ chunks = list(chunks)
202
+ return ''.join(chunks)
203
+
204
+ def iterencode(self, o, _one_shot=False):
205
+ """Encode the given object and yield each string
206
+ representation as available.
207
+
208
+ For example::
209
+
210
+ for chunk in JSONEncoder().iterencode(bigobject):
211
+ mysocket.write(chunk)
212
+
213
+ """
214
+ if self.check_circular:
215
+ markers = {}
216
+ else:
217
+ markers = None
218
+ if self.ensure_ascii:
219
+ _encoder = encode_basestring_ascii
220
+ else:
221
+ _encoder = encode_basestring
222
+
223
+ def floatstr(o, allow_nan=self.allow_nan,
224
+ _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY):
225
+ # Check for specials. Note that this type of test is processor
226
+ # and/or platform-specific, so do tests which don't depend on the
227
+ # internals.
228
+
229
+ if o != o:
230
+ text = 'NaN'
231
+ elif o == _inf:
232
+ text = 'Infinity'
233
+ elif o == _neginf:
234
+ text = '-Infinity'
235
+ else:
236
+ return _repr(o)
237
+
238
+ if not allow_nan:
239
+ raise ValueError(
240
+ "Out of range float values are not JSON compliant: " +
241
+ repr(o))
242
+
243
+ return text
244
+
245
+
246
+ if (_one_shot and c_make_encoder is not None
247
+ and self.indent is None):
248
+ _iterencode = c_make_encoder(
249
+ markers, self.default, _encoder, self.indent,
250
+ self.key_separator, self.item_separator, self.sort_keys,
251
+ self.skipkeys, self.allow_nan)
252
+ else:
253
+ _iterencode = _make_iterencode(
254
+ markers, self.default, _encoder, self.indent, floatstr,
255
+ self.key_separator, self.item_separator, self.sort_keys,
256
+ self.skipkeys, _one_shot)
257
+ return _iterencode(o, 0)
258
+
259
+ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
260
+ _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
261
+ ## HACK: hand-optimized bytecode; turn globals into locals
262
+ ValueError=ValueError,
263
+ dict=dict,
264
+ float=float,
265
+ id=id,
266
+ int=int,
267
+ isinstance=isinstance,
268
+ list=list,
269
+ str=str,
270
+ tuple=tuple,
271
+ _intstr=int.__repr__,
272
+ ):
273
+
274
+ if _indent is not None and not isinstance(_indent, str):
275
+ _indent = ' ' * _indent
276
+
277
+ def _iterencode_list(lst, _current_indent_level):
278
+ if not lst:
279
+ yield '[]'
280
+ return
281
+ if markers is not None:
282
+ markerid = id(lst)
283
+ if markerid in markers:
284
+ raise ValueError("Circular reference detected")
285
+ markers[markerid] = lst
286
+ buf = '['
287
+ if _indent is not None:
288
+ _current_indent_level += 1
289
+ newline_indent = '\n' + _indent * _current_indent_level
290
+ separator = _item_separator + newline_indent
291
+ buf += newline_indent
292
+ else:
293
+ newline_indent = None
294
+ separator = _item_separator
295
+ first = True
296
+ for value in lst:
297
+ if first:
298
+ first = False
299
+ else:
300
+ buf = separator
301
+ if isinstance(value, str):
302
+ yield buf + _encoder(value)
303
+ elif value is None:
304
+ yield buf + 'null'
305
+ elif value is True:
306
+ yield buf + 'true'
307
+ elif value is False:
308
+ yield buf + 'false'
309
+ elif isinstance(value, int):
310
+ # Subclasses of int/float may override __repr__, but we still
311
+ # want to encode them as integers/floats in JSON. One example
312
+ # within the standard library is IntEnum.
313
+ yield buf + _intstr(value)
314
+ elif isinstance(value, float):
315
+ # see comment above for int
316
+ yield buf + _floatstr(value)
317
+ else:
318
+ yield buf
319
+ if isinstance(value, (list, tuple)):
320
+ chunks = _iterencode_list(value, _current_indent_level)
321
+ elif isinstance(value, dict):
322
+ chunks = _iterencode_dict(value, _current_indent_level)
323
+ else:
324
+ chunks = _iterencode(value, _current_indent_level)
325
+ yield from chunks
326
+ if newline_indent is not None:
327
+ _current_indent_level -= 1
328
+ yield '\n' + _indent * _current_indent_level
329
+ yield ']'
330
+ if markers is not None:
331
+ del markers[markerid]
332
+
333
+ def _iterencode_dict(dct, _current_indent_level):
334
+ if not dct:
335
+ yield '{}'
336
+ return
337
+ if markers is not None:
338
+ markerid = id(dct)
339
+ if markerid in markers:
340
+ raise ValueError("Circular reference detected")
341
+ markers[markerid] = dct
342
+ yield '{'
343
+ if _indent is not None:
344
+ _current_indent_level += 1
345
+ newline_indent = '\n' + _indent * _current_indent_level
346
+ item_separator = _item_separator + newline_indent
347
+ yield newline_indent
348
+ else:
349
+ newline_indent = None
350
+ item_separator = _item_separator
351
+ first = True
352
+ if _sort_keys:
353
+ items = sorted(dct.items())
354
+ else:
355
+ items = dct.items()
356
+ for key, value in items:
357
+ if isinstance(key, str):
358
+ pass
359
+ # JavaScript is weakly typed for these, so it makes sense to
360
+ # also allow them. Many encoders seem to do something like this.
361
+ elif isinstance(key, float):
362
+ # see comment for int/float in _make_iterencode
363
+ key = _floatstr(key)
364
+ elif key is True:
365
+ key = 'true'
366
+ elif key is False:
367
+ key = 'false'
368
+ elif key is None:
369
+ key = 'null'
370
+ elif isinstance(key, int):
371
+ # see comment for int/float in _make_iterencode
372
+ key = _intstr(key)
373
+ elif _skipkeys:
374
+ continue
375
+ else:
376
+ raise TypeError(f'keys must be str, int, float, bool or None, '
377
+ f'not {key.__class__.__name__}')
378
+ if first:
379
+ first = False
380
+ else:
381
+ yield item_separator
382
+ yield _encoder(key)
383
+ yield _key_separator
384
+ if isinstance(value, str):
385
+ yield _encoder(value)
386
+ elif value is None:
387
+ yield 'null'
388
+ elif value is True:
389
+ yield 'true'
390
+ elif value is False:
391
+ yield 'false'
392
+ elif isinstance(value, int):
393
+ # see comment for int/float in _make_iterencode
394
+ yield _intstr(value)
395
+ elif isinstance(value, float):
396
+ # see comment for int/float in _make_iterencode
397
+ yield _floatstr(value)
398
+ else:
399
+ if isinstance(value, (list, tuple)):
400
+ chunks = _iterencode_list(value, _current_indent_level)
401
+ elif isinstance(value, dict):
402
+ chunks = _iterencode_dict(value, _current_indent_level)
403
+ else:
404
+ chunks = _iterencode(value, _current_indent_level)
405
+ yield from chunks
406
+ if newline_indent is not None:
407
+ _current_indent_level -= 1
408
+ yield '\n' + _indent * _current_indent_level
409
+ yield '}'
410
+ if markers is not None:
411
+ del markers[markerid]
412
+
413
+ def _iterencode(o, _current_indent_level):
414
+ if isinstance(o, str):
415
+ yield _encoder(o)
416
+ elif o is None:
417
+ yield 'null'
418
+ elif o is True:
419
+ yield 'true'
420
+ elif o is False:
421
+ yield 'false'
422
+ elif isinstance(o, int):
423
+ # see comment for int/float in _make_iterencode
424
+ yield _intstr(o)
425
+ elif isinstance(o, float):
426
+ # see comment for int/float in _make_iterencode
427
+ yield _floatstr(o)
428
+ elif isinstance(o, (list, tuple)):
429
+ yield from _iterencode_list(o, _current_indent_level)
430
+ elif isinstance(o, dict):
431
+ yield from _iterencode_dict(o, _current_indent_level)
432
+ else:
433
+ if markers is not None:
434
+ markerid = id(o)
435
+ if markerid in markers:
436
+ raise ValueError("Circular reference detected")
437
+ markers[markerid] = o
438
+ o = _default(o)
439
+ yield from _iterencode(o, _current_indent_level)
440
+ if markers is not None:
441
+ del markers[markerid]
442
+ return _iterencode
my_container_sandbox/workspace/anaconda3/lib/python3.8/json/scanner.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """JSON token scanner
2
+ """
3
+ import re
4
+ try:
5
+ from _json import make_scanner as c_make_scanner
6
+ except ImportError:
7
+ c_make_scanner = None
8
+
9
+ __all__ = ['make_scanner']
10
+
11
+ NUMBER_RE = re.compile(
12
+ r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?',
13
+ (re.VERBOSE | re.MULTILINE | re.DOTALL))
14
+
15
+ def py_make_scanner(context):
16
+ parse_object = context.parse_object
17
+ parse_array = context.parse_array
18
+ parse_string = context.parse_string
19
+ match_number = NUMBER_RE.match
20
+ strict = context.strict
21
+ parse_float = context.parse_float
22
+ parse_int = context.parse_int
23
+ parse_constant = context.parse_constant
24
+ object_hook = context.object_hook
25
+ object_pairs_hook = context.object_pairs_hook
26
+ memo = context.memo
27
+
28
+ def _scan_once(string, idx):
29
+ try:
30
+ nextchar = string[idx]
31
+ except IndexError:
32
+ raise StopIteration(idx) from None
33
+
34
+ if nextchar == '"':
35
+ return parse_string(string, idx + 1, strict)
36
+ elif nextchar == '{':
37
+ return parse_object((string, idx + 1), strict,
38
+ _scan_once, object_hook, object_pairs_hook, memo)
39
+ elif nextchar == '[':
40
+ return parse_array((string, idx + 1), _scan_once)
41
+ elif nextchar == 'n' and string[idx:idx + 4] == 'null':
42
+ return None, idx + 4
43
+ elif nextchar == 't' and string[idx:idx + 4] == 'true':
44
+ return True, idx + 4
45
+ elif nextchar == 'f' and string[idx:idx + 5] == 'false':
46
+ return False, idx + 5
47
+
48
+ m = match_number(string, idx)
49
+ if m is not None:
50
+ integer, frac, exp = m.groups()
51
+ if frac or exp:
52
+ res = parse_float(integer + (frac or '') + (exp or ''))
53
+ else:
54
+ res = parse_int(integer)
55
+ return res, m.end()
56
+ elif nextchar == 'N' and string[idx:idx + 3] == 'NaN':
57
+ return parse_constant('NaN'), idx + 3
58
+ elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity':
59
+ return parse_constant('Infinity'), idx + 8
60
+ elif nextchar == '-' and string[idx:idx + 9] == '-Infinity':
61
+ return parse_constant('-Infinity'), idx + 9
62
+ else:
63
+ raise StopIteration(idx)
64
+
65
+ def scan_once(string, idx):
66
+ try:
67
+ return _scan_once(string, idx)
68
+ finally:
69
+ memo.clear()
70
+
71
+ return scan_once
72
+
73
+ make_scanner = c_make_scanner or py_make_scanner
my_container_sandbox/workspace/anaconda3/lib/python3.8/json/tool.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ r"""Command-line tool to validate and pretty-print JSON
2
+
3
+ Usage::
4
+
5
+ $ echo '{"json":"obj"}' | python -m json.tool
6
+ {
7
+ "json": "obj"
8
+ }
9
+ $ echo '{ 1.2:3.4}' | python -m json.tool
10
+ Expecting property name enclosed in double quotes: line 1 column 3 (char 2)
11
+
12
+ """
13
+ import argparse
14
+ import json
15
+ import sys
16
+
17
+
18
+ def main():
19
+ prog = 'python -m json.tool'
20
+ description = ('A simple command line interface for json module '
21
+ 'to validate and pretty-print JSON objects.')
22
+ parser = argparse.ArgumentParser(prog=prog, description=description)
23
+ parser.add_argument('infile', nargs='?',
24
+ type=argparse.FileType(encoding="utf-8"),
25
+ help='a JSON file to be validated or pretty-printed',
26
+ default=sys.stdin)
27
+ parser.add_argument('outfile', nargs='?',
28
+ type=argparse.FileType('w', encoding="utf-8"),
29
+ help='write the output of infile to outfile',
30
+ default=sys.stdout)
31
+ parser.add_argument('--sort-keys', action='store_true', default=False,
32
+ help='sort the output of dictionaries alphabetically by key')
33
+ parser.add_argument('--json-lines', action='store_true', default=False,
34
+ help='parse input using the jsonlines format')
35
+ options = parser.parse_args()
36
+
37
+ infile = options.infile
38
+ outfile = options.outfile
39
+ sort_keys = options.sort_keys
40
+ json_lines = options.json_lines
41
+ with infile, outfile:
42
+ try:
43
+ if json_lines:
44
+ objs = (json.loads(line) for line in infile)
45
+ else:
46
+ objs = (json.load(infile), )
47
+ for obj in objs:
48
+ json.dump(obj, outfile, sort_keys=sort_keys, indent=4)
49
+ outfile.write('\n')
50
+ except ValueError as e:
51
+ raise SystemExit(e)
52
+
53
+
54
+ if __name__ == '__main__':
55
+ try:
56
+ main()
57
+ except BrokenPipeError as exc:
58
+ sys.exit(exc.errno)
my_container_sandbox/workspace/anaconda3/lib/python3.8/sqlite3/dbapi2.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # pysqlite2/dbapi2.py: the DB-API 2.0 interface
2
+ #
3
+ # Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
4
+ #
5
+ # This file is part of pysqlite.
6
+ #
7
+ # This software is provided 'as-is', without any express or implied
8
+ # warranty. In no event will the authors be held liable for any damages
9
+ # arising from the use of this software.
10
+ #
11
+ # Permission is granted to anyone to use this software for any purpose,
12
+ # including commercial applications, and to alter it and redistribute it
13
+ # freely, subject to the following restrictions:
14
+ #
15
+ # 1. The origin of this software must not be misrepresented; you must not
16
+ # claim that you wrote the original software. If you use this software
17
+ # in a product, an acknowledgment in the product documentation would be
18
+ # appreciated but is not required.
19
+ # 2. Altered source versions must be plainly marked as such, and must not be
20
+ # misrepresented as being the original software.
21
+ # 3. This notice may not be removed or altered from any source distribution.
22
+
23
+ import datetime
24
+ import time
25
+ import collections.abc
26
+
27
+ from _sqlite3 import *
28
+
29
+ paramstyle = "qmark"
30
+
31
+ threadsafety = 1
32
+
33
+ apilevel = "2.0"
34
+
35
+ Date = datetime.date
36
+
37
+ Time = datetime.time
38
+
39
+ Timestamp = datetime.datetime
40
+
41
+ def DateFromTicks(ticks):
42
+ return Date(*time.localtime(ticks)[:3])
43
+
44
+ def TimeFromTicks(ticks):
45
+ return Time(*time.localtime(ticks)[3:6])
46
+
47
+ def TimestampFromTicks(ticks):
48
+ return Timestamp(*time.localtime(ticks)[:6])
49
+
50
+ version_info = tuple([int(x) for x in version.split(".")])
51
+ sqlite_version_info = tuple([int(x) for x in sqlite_version.split(".")])
52
+
53
+ Binary = memoryview
54
+ collections.abc.Sequence.register(Row)
55
+
56
+ def register_adapters_and_converters():
57
+ def adapt_date(val):
58
+ return val.isoformat()
59
+
60
+ def adapt_datetime(val):
61
+ return val.isoformat(" ")
62
+
63
+ def convert_date(val):
64
+ return datetime.date(*map(int, val.split(b"-")))
65
+
66
+ def convert_timestamp(val):
67
+ datepart, timepart = val.split(b" ")
68
+ year, month, day = map(int, datepart.split(b"-"))
69
+ timepart_full = timepart.split(b".")
70
+ hours, minutes, seconds = map(int, timepart_full[0].split(b":"))
71
+ if len(timepart_full) == 2:
72
+ microseconds = int('{:0<6.6}'.format(timepart_full[1].decode()))
73
+ else:
74
+ microseconds = 0
75
+
76
+ val = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds)
77
+ return val
78
+
79
+
80
+ register_adapter(datetime.date, adapt_date)
81
+ register_adapter(datetime.datetime, adapt_datetime)
82
+ register_converter("date", convert_date)
83
+ register_converter("timestamp", convert_timestamp)
84
+
85
+ register_adapters_and_converters()
86
+
87
+ # Clean up namespace
88
+
89
+ del(register_adapters_and_converters)
my_container_sandbox/workspace/anaconda3/lib/python3.8/test/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Dummy file to make this directory a package.
my_container_sandbox/workspace/anaconda3/lib/python3.8/test/test_script_helper.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Unittests for test.support.script_helper. Who tests the test helper?"""
2
+
3
+ import subprocess
4
+ import sys
5
+ import os
6
+ from test.support import script_helper
7
+ import unittest
8
+ from unittest import mock
9
+
10
+
11
+ class TestScriptHelper(unittest.TestCase):
12
+
13
+ def test_assert_python_ok(self):
14
+ t = script_helper.assert_python_ok('-c', 'import sys; sys.exit(0)')
15
+ self.assertEqual(0, t[0], 'return code was not 0')
16
+
17
+ def test_assert_python_failure(self):
18
+ # I didn't import the sys module so this child will fail.
19
+ rc, out, err = script_helper.assert_python_failure('-c', 'sys.exit(0)')
20
+ self.assertNotEqual(0, rc, 'return code should not be 0')
21
+
22
+ def test_assert_python_ok_raises(self):
23
+ # I didn't import the sys module so this child will fail.
24
+ with self.assertRaises(AssertionError) as error_context:
25
+ script_helper.assert_python_ok('-c', 'sys.exit(0)')
26
+ error_msg = str(error_context.exception)
27
+ self.assertIn('command line:', error_msg)
28
+ self.assertIn('sys.exit(0)', error_msg, msg='unexpected command line')
29
+
30
+ def test_assert_python_failure_raises(self):
31
+ with self.assertRaises(AssertionError) as error_context:
32
+ script_helper.assert_python_failure('-c', 'import sys; sys.exit(0)')
33
+ error_msg = str(error_context.exception)
34
+ self.assertIn('Process return code is 0\n', error_msg)
35
+ self.assertIn('import sys; sys.exit(0)', error_msg,
36
+ msg='unexpected command line.')
37
+
38
+ @mock.patch('subprocess.Popen')
39
+ def test_assert_python_isolated_when_env_not_required(self, mock_popen):
40
+ with mock.patch.object(script_helper,
41
+ 'interpreter_requires_environment',
42
+ return_value=False) as mock_ire_func:
43
+ mock_popen.side_effect = RuntimeError('bail out of unittest')
44
+ try:
45
+ script_helper._assert_python(True, '-c', 'None')
46
+ except RuntimeError as err:
47
+ self.assertEqual('bail out of unittest', err.args[0])
48
+ self.assertEqual(1, mock_popen.call_count)
49
+ self.assertEqual(1, mock_ire_func.call_count)
50
+ popen_command = mock_popen.call_args[0][0]
51
+ self.assertEqual(sys.executable, popen_command[0])
52
+ self.assertIn('None', popen_command)
53
+ self.assertIn('-I', popen_command)
54
+ self.assertNotIn('-E', popen_command) # -I overrides this
55
+
56
+ @mock.patch('subprocess.Popen')
57
+ def test_assert_python_not_isolated_when_env_is_required(self, mock_popen):
58
+ """Ensure that -I is not passed when the environment is required."""
59
+ with mock.patch.object(script_helper,
60
+ 'interpreter_requires_environment',
61
+ return_value=True) as mock_ire_func:
62
+ mock_popen.side_effect = RuntimeError('bail out of unittest')
63
+ try:
64
+ script_helper._assert_python(True, '-c', 'None')
65
+ except RuntimeError as err:
66
+ self.assertEqual('bail out of unittest', err.args[0])
67
+ popen_command = mock_popen.call_args[0][0]
68
+ self.assertNotIn('-I', popen_command)
69
+ self.assertNotIn('-E', popen_command)
70
+
71
+
72
+ class TestScriptHelperEnvironment(unittest.TestCase):
73
+ """Code coverage for interpreter_requires_environment()."""
74
+
75
+ def setUp(self):
76
+ self.assertTrue(
77
+ hasattr(script_helper, '__cached_interp_requires_environment'))
78
+ # Reset the private cached state.
79
+ script_helper.__dict__['__cached_interp_requires_environment'] = None
80
+
81
+ def tearDown(self):
82
+ # Reset the private cached state.
83
+ script_helper.__dict__['__cached_interp_requires_environment'] = None
84
+
85
+ @mock.patch('subprocess.check_call')
86
+ def test_interpreter_requires_environment_true(self, mock_check_call):
87
+ with mock.patch.dict(os.environ):
88
+ os.environ.pop('PYTHONHOME', None)
89
+ mock_check_call.side_effect = subprocess.CalledProcessError('', '')
90
+ self.assertTrue(script_helper.interpreter_requires_environment())
91
+ self.assertTrue(script_helper.interpreter_requires_environment())
92
+ self.assertEqual(1, mock_check_call.call_count)
93
+
94
+ @mock.patch('subprocess.check_call')
95
+ def test_interpreter_requires_environment_false(self, mock_check_call):
96
+ with mock.patch.dict(os.environ):
97
+ os.environ.pop('PYTHONHOME', None)
98
+ # The mocked subprocess.check_call fakes a no-error process.
99
+ script_helper.interpreter_requires_environment()
100
+ self.assertFalse(script_helper.interpreter_requires_environment())
101
+ self.assertEqual(1, mock_check_call.call_count)
102
+
103
+ @mock.patch('subprocess.check_call')
104
+ def test_interpreter_requires_environment_details(self, mock_check_call):
105
+ with mock.patch.dict(os.environ):
106
+ os.environ.pop('PYTHONHOME', None)
107
+ script_helper.interpreter_requires_environment()
108
+ self.assertFalse(script_helper.interpreter_requires_environment())
109
+ self.assertFalse(script_helper.interpreter_requires_environment())
110
+ self.assertEqual(1, mock_check_call.call_count)
111
+ check_call_command = mock_check_call.call_args[0][0]
112
+ self.assertEqual(sys.executable, check_call_command[0])
113
+ self.assertIn('-E', check_call_command)
114
+
115
+ @mock.patch('subprocess.check_call')
116
+ def test_interpreter_requires_environment_with_pythonhome(self, mock_check_call):
117
+ with mock.patch.dict(os.environ):
118
+ os.environ['PYTHONHOME'] = 'MockedHome'
119
+ self.assertTrue(script_helper.interpreter_requires_environment())
120
+ self.assertTrue(script_helper.interpreter_requires_environment())
121
+ self.assertEqual(0, mock_check_call.call_count)
122
+
123
+
124
+ if __name__ == '__main__':
125
+ unittest.main()
my_container_sandbox/workspace/anaconda3/lib/python3.8/test/test_support.py ADDED
@@ -0,0 +1,689 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import contextlib
2
+ import errno
3
+ import importlib
4
+ import io
5
+ import os
6
+ import shutil
7
+ import socket
8
+ import stat
9
+ import subprocess
10
+ import sys
11
+ import tempfile
12
+ import textwrap
13
+ import time
14
+ import unittest
15
+ from test import support
16
+ from test.support import script_helper
17
+
18
+ TESTFN = support.TESTFN
19
+
20
+
21
+ class TestSupport(unittest.TestCase):
22
+
23
+ def test_import_module(self):
24
+ support.import_module("ftplib")
25
+ self.assertRaises(unittest.SkipTest, support.import_module, "foo")
26
+
27
+ def test_import_fresh_module(self):
28
+ support.import_fresh_module("ftplib")
29
+
30
+ def test_get_attribute(self):
31
+ self.assertEqual(support.get_attribute(self, "test_get_attribute"),
32
+ self.test_get_attribute)
33
+ self.assertRaises(unittest.SkipTest, support.get_attribute, self, "foo")
34
+
35
+ @unittest.skip("failing buildbots")
36
+ def test_get_original_stdout(self):
37
+ self.assertEqual(support.get_original_stdout(), sys.stdout)
38
+
39
+ def test_unload(self):
40
+ import sched
41
+ self.assertIn("sched", sys.modules)
42
+ support.unload("sched")
43
+ self.assertNotIn("sched", sys.modules)
44
+
45
+ def test_unlink(self):
46
+ with open(TESTFN, "w") as f:
47
+ pass
48
+ support.unlink(TESTFN)
49
+ self.assertFalse(os.path.exists(TESTFN))
50
+ support.unlink(TESTFN)
51
+
52
+ def test_rmtree(self):
53
+ dirpath = support.TESTFN + 'd'
54
+ subdirpath = os.path.join(dirpath, 'subdir')
55
+ os.mkdir(dirpath)
56
+ os.mkdir(subdirpath)
57
+ support.rmtree(dirpath)
58
+ self.assertFalse(os.path.exists(dirpath))
59
+ with support.swap_attr(support, 'verbose', 0):
60
+ support.rmtree(dirpath)
61
+
62
+ os.mkdir(dirpath)
63
+ os.mkdir(subdirpath)
64
+ os.chmod(dirpath, stat.S_IRUSR|stat.S_IXUSR)
65
+ with support.swap_attr(support, 'verbose', 0):
66
+ support.rmtree(dirpath)
67
+ self.assertFalse(os.path.exists(dirpath))
68
+
69
+ os.mkdir(dirpath)
70
+ os.mkdir(subdirpath)
71
+ os.chmod(dirpath, 0)
72
+ with support.swap_attr(support, 'verbose', 0):
73
+ support.rmtree(dirpath)
74
+ self.assertFalse(os.path.exists(dirpath))
75
+
76
+ def test_forget(self):
77
+ mod_filename = TESTFN + '.py'
78
+ with open(mod_filename, 'w') as f:
79
+ print('foo = 1', file=f)
80
+ sys.path.insert(0, os.curdir)
81
+ importlib.invalidate_caches()
82
+ try:
83
+ mod = __import__(TESTFN)
84
+ self.assertIn(TESTFN, sys.modules)
85
+
86
+ support.forget(TESTFN)
87
+ self.assertNotIn(TESTFN, sys.modules)
88
+ finally:
89
+ del sys.path[0]
90
+ support.unlink(mod_filename)
91
+ support.rmtree('__pycache__')
92
+
93
+ def test_HOST(self):
94
+ s = socket.create_server((support.HOST, 0))
95
+ s.close()
96
+
97
+ def test_find_unused_port(self):
98
+ port = support.find_unused_port()
99
+ s = socket.create_server((support.HOST, port))
100
+ s.close()
101
+
102
+ def test_bind_port(self):
103
+ s = socket.socket()
104
+ support.bind_port(s)
105
+ s.listen()
106
+ s.close()
107
+
108
+ # Tests for temp_dir()
109
+
110
+ def test_temp_dir(self):
111
+ """Test that temp_dir() creates and destroys its directory."""
112
+ parent_dir = tempfile.mkdtemp()
113
+ parent_dir = os.path.realpath(parent_dir)
114
+
115
+ try:
116
+ path = os.path.join(parent_dir, 'temp')
117
+ self.assertFalse(os.path.isdir(path))
118
+ with support.temp_dir(path) as temp_path:
119
+ self.assertEqual(temp_path, path)
120
+ self.assertTrue(os.path.isdir(path))
121
+ self.assertFalse(os.path.isdir(path))
122
+ finally:
123
+ support.rmtree(parent_dir)
124
+
125
+ def test_temp_dir__path_none(self):
126
+ """Test passing no path."""
127
+ with support.temp_dir() as temp_path:
128
+ self.assertTrue(os.path.isdir(temp_path))
129
+ self.assertFalse(os.path.isdir(temp_path))
130
+
131
+ def test_temp_dir__existing_dir__quiet_default(self):
132
+ """Test passing a directory that already exists."""
133
+ def call_temp_dir(path):
134
+ with support.temp_dir(path) as temp_path:
135
+ raise Exception("should not get here")
136
+
137
+ path = tempfile.mkdtemp()
138
+ path = os.path.realpath(path)
139
+ try:
140
+ self.assertTrue(os.path.isdir(path))
141
+ self.assertRaises(FileExistsError, call_temp_dir, path)
142
+ # Make sure temp_dir did not delete the original directory.
143
+ self.assertTrue(os.path.isdir(path))
144
+ finally:
145
+ shutil.rmtree(path)
146
+
147
+ def test_temp_dir__existing_dir__quiet_true(self):
148
+ """Test passing a directory that already exists with quiet=True."""
149
+ path = tempfile.mkdtemp()
150
+ path = os.path.realpath(path)
151
+
152
+ try:
153
+ with support.check_warnings() as recorder:
154
+ with support.temp_dir(path, quiet=True) as temp_path:
155
+ self.assertEqual(path, temp_path)
156
+ warnings = [str(w.message) for w in recorder.warnings]
157
+ # Make sure temp_dir did not delete the original directory.
158
+ self.assertTrue(os.path.isdir(path))
159
+ finally:
160
+ shutil.rmtree(path)
161
+
162
+ self.assertEqual(len(warnings), 1, warnings)
163
+ warn = warnings[0]
164
+ self.assertTrue(warn.startswith(f'tests may fail, unable to create '
165
+ f'temporary directory {path!r}: '),
166
+ warn)
167
+
168
+ @unittest.skipUnless(hasattr(os, "fork"), "test requires os.fork")
169
+ def test_temp_dir__forked_child(self):
170
+ """Test that a forked child process does not remove the directory."""
171
+ # See bpo-30028 for details.
172
+ # Run the test as an external script, because it uses fork.
173
+ script_helper.assert_python_ok("-c", textwrap.dedent("""
174
+ import os
175
+ from test import support
176
+ with support.temp_cwd() as temp_path:
177
+ pid = os.fork()
178
+ if pid != 0:
179
+ # parent process (child has pid == 0)
180
+
181
+ # wait for the child to terminate
182
+ (pid, status) = os.waitpid(pid, 0)
183
+ if status != 0:
184
+ raise AssertionError(f"Child process failed with exit "
185
+ f"status indication 0x{status:x}.")
186
+
187
+ # Make sure that temp_path is still present. When the child
188
+ # process leaves the 'temp_cwd'-context, the __exit__()-
189
+ # method of the context must not remove the temporary
190
+ # directory.
191
+ if not os.path.isdir(temp_path):
192
+ raise AssertionError("Child removed temp_path.")
193
+ """))
194
+
195
+ # Tests for change_cwd()
196
+
197
+ def test_change_cwd(self):
198
+ original_cwd = os.getcwd()
199
+
200
+ with support.temp_dir() as temp_path:
201
+ with support.change_cwd(temp_path) as new_cwd:
202
+ self.assertEqual(new_cwd, temp_path)
203
+ self.assertEqual(os.getcwd(), new_cwd)
204
+
205
+ self.assertEqual(os.getcwd(), original_cwd)
206
+
207
+ def test_change_cwd__non_existent_dir(self):
208
+ """Test passing a non-existent directory."""
209
+ original_cwd = os.getcwd()
210
+
211
+ def call_change_cwd(path):
212
+ with support.change_cwd(path) as new_cwd:
213
+ raise Exception("should not get here")
214
+
215
+ with support.temp_dir() as parent_dir:
216
+ non_existent_dir = os.path.join(parent_dir, 'does_not_exist')
217
+ self.assertRaises(FileNotFoundError, call_change_cwd,
218
+ non_existent_dir)
219
+
220
+ self.assertEqual(os.getcwd(), original_cwd)
221
+
222
+ def test_change_cwd__non_existent_dir__quiet_true(self):
223
+ """Test passing a non-existent directory with quiet=True."""
224
+ original_cwd = os.getcwd()
225
+
226
+ with support.temp_dir() as parent_dir:
227
+ bad_dir = os.path.join(parent_dir, 'does_not_exist')
228
+ with support.check_warnings() as recorder:
229
+ with support.change_cwd(bad_dir, quiet=True) as new_cwd:
230
+ self.assertEqual(new_cwd, original_cwd)
231
+ self.assertEqual(os.getcwd(), new_cwd)
232
+ warnings = [str(w.message) for w in recorder.warnings]
233
+
234
+ self.assertEqual(len(warnings), 1, warnings)
235
+ warn = warnings[0]
236
+ self.assertTrue(warn.startswith(f'tests may fail, unable to change '
237
+ f'the current working directory '
238
+ f'to {bad_dir!r}: '),
239
+ warn)
240
+
241
+ # Tests for change_cwd()
242
+
243
+ def test_change_cwd__chdir_warning(self):
244
+ """Check the warning message when os.chdir() fails."""
245
+ path = TESTFN + '_does_not_exist'
246
+ with support.check_warnings() as recorder:
247
+ with support.change_cwd(path=path, quiet=True):
248
+ pass
249
+ messages = [str(w.message) for w in recorder.warnings]
250
+
251
+ self.assertEqual(len(messages), 1, messages)
252
+ msg = messages[0]
253
+ self.assertTrue(msg.startswith(f'tests may fail, unable to change '
254
+ f'the current working directory '
255
+ f'to {path!r}: '),
256
+ msg)
257
+
258
+ # Tests for temp_cwd()
259
+
260
+ def test_temp_cwd(self):
261
+ here = os.getcwd()
262
+ with support.temp_cwd(name=TESTFN):
263
+ self.assertEqual(os.path.basename(os.getcwd()), TESTFN)
264
+ self.assertFalse(os.path.exists(TESTFN))
265
+ self.assertEqual(os.getcwd(), here)
266
+
267
+
268
+ def test_temp_cwd__name_none(self):
269
+ """Test passing None to temp_cwd()."""
270
+ original_cwd = os.getcwd()
271
+ with support.temp_cwd(name=None) as new_cwd:
272
+ self.assertNotEqual(new_cwd, original_cwd)
273
+ self.assertTrue(os.path.isdir(new_cwd))
274
+ self.assertEqual(os.getcwd(), new_cwd)
275
+ self.assertEqual(os.getcwd(), original_cwd)
276
+
277
+ def test_sortdict(self):
278
+ self.assertEqual(support.sortdict({3:3, 2:2, 1:1}), "{1: 1, 2: 2, 3: 3}")
279
+
280
+ def test_make_bad_fd(self):
281
+ fd = support.make_bad_fd()
282
+ with self.assertRaises(OSError) as cm:
283
+ os.write(fd, b"foo")
284
+ self.assertEqual(cm.exception.errno, errno.EBADF)
285
+
286
+ def test_check_syntax_error(self):
287
+ support.check_syntax_error(self, "def class", lineno=1, offset=5)
288
+ with self.assertRaises(AssertionError):
289
+ support.check_syntax_error(self, "x=1")
290
+
291
+ def test_CleanImport(self):
292
+ import importlib
293
+ with support.CleanImport("asyncore"):
294
+ importlib.import_module("asyncore")
295
+
296
+ def test_DirsOnSysPath(self):
297
+ with support.DirsOnSysPath('foo', 'bar'):
298
+ self.assertIn("foo", sys.path)
299
+ self.assertIn("bar", sys.path)
300
+ self.assertNotIn("foo", sys.path)
301
+ self.assertNotIn("bar", sys.path)
302
+
303
+ def test_captured_stdout(self):
304
+ with support.captured_stdout() as stdout:
305
+ print("hello")
306
+ self.assertEqual(stdout.getvalue(), "hello\n")
307
+
308
+ def test_captured_stderr(self):
309
+ with support.captured_stderr() as stderr:
310
+ print("hello", file=sys.stderr)
311
+ self.assertEqual(stderr.getvalue(), "hello\n")
312
+
313
+ def test_captured_stdin(self):
314
+ with support.captured_stdin() as stdin:
315
+ stdin.write('hello\n')
316
+ stdin.seek(0)
317
+ # call test code that consumes from sys.stdin
318
+ captured = input()
319
+ self.assertEqual(captured, "hello")
320
+
321
+ def test_gc_collect(self):
322
+ support.gc_collect()
323
+
324
+ def test_python_is_optimized(self):
325
+ self.assertIsInstance(support.python_is_optimized(), bool)
326
+
327
+ def test_swap_attr(self):
328
+ class Obj:
329
+ pass
330
+ obj = Obj()
331
+ obj.x = 1
332
+ with support.swap_attr(obj, "x", 5) as x:
333
+ self.assertEqual(obj.x, 5)
334
+ self.assertEqual(x, 1)
335
+ self.assertEqual(obj.x, 1)
336
+ with support.swap_attr(obj, "y", 5) as y:
337
+ self.assertEqual(obj.y, 5)
338
+ self.assertIsNone(y)
339
+ self.assertFalse(hasattr(obj, 'y'))
340
+ with support.swap_attr(obj, "y", 5):
341
+ del obj.y
342
+ self.assertFalse(hasattr(obj, 'y'))
343
+
344
+ def test_swap_item(self):
345
+ D = {"x":1}
346
+ with support.swap_item(D, "x", 5) as x:
347
+ self.assertEqual(D["x"], 5)
348
+ self.assertEqual(x, 1)
349
+ self.assertEqual(D["x"], 1)
350
+ with support.swap_item(D, "y", 5) as y:
351
+ self.assertEqual(D["y"], 5)
352
+ self.assertIsNone(y)
353
+ self.assertNotIn("y", D)
354
+ with support.swap_item(D, "y", 5):
355
+ del D["y"]
356
+ self.assertNotIn("y", D)
357
+
358
+ class RefClass:
359
+ attribute1 = None
360
+ attribute2 = None
361
+ _hidden_attribute1 = None
362
+ __magic_1__ = None
363
+
364
+ class OtherClass:
365
+ attribute2 = None
366
+ attribute3 = None
367
+ __magic_1__ = None
368
+ __magic_2__ = None
369
+
370
+ def test_detect_api_mismatch(self):
371
+ missing_items = support.detect_api_mismatch(self.RefClass,
372
+ self.OtherClass)
373
+ self.assertEqual({'attribute1'}, missing_items)
374
+
375
+ missing_items = support.detect_api_mismatch(self.OtherClass,
376
+ self.RefClass)
377
+ self.assertEqual({'attribute3', '__magic_2__'}, missing_items)
378
+
379
+ def test_detect_api_mismatch__ignore(self):
380
+ ignore = ['attribute1', 'attribute3', '__magic_2__', 'not_in_either']
381
+
382
+ missing_items = support.detect_api_mismatch(
383
+ self.RefClass, self.OtherClass, ignore=ignore)
384
+ self.assertEqual(set(), missing_items)
385
+
386
+ missing_items = support.detect_api_mismatch(
387
+ self.OtherClass, self.RefClass, ignore=ignore)
388
+ self.assertEqual(set(), missing_items)
389
+
390
+ def test_check__all__(self):
391
+ extra = {'tempdir'}
392
+ blacklist = {'template'}
393
+ support.check__all__(self,
394
+ tempfile,
395
+ extra=extra,
396
+ blacklist=blacklist)
397
+
398
+ extra = {'TextTestResult', 'installHandler'}
399
+ blacklist = {'load_tests', "TestProgram", "BaseTestSuite"}
400
+
401
+ support.check__all__(self,
402
+ unittest,
403
+ ("unittest.result", "unittest.case",
404
+ "unittest.suite", "unittest.loader",
405
+ "unittest.main", "unittest.runner",
406
+ "unittest.signals", "unittest.async_case"),
407
+ extra=extra,
408
+ blacklist=blacklist)
409
+
410
+ self.assertRaises(AssertionError, support.check__all__, self, unittest)
411
+
412
+ @unittest.skipUnless(hasattr(os, 'waitpid') and hasattr(os, 'WNOHANG'),
413
+ 'need os.waitpid() and os.WNOHANG')
414
+ def test_reap_children(self):
415
+ # Make sure that there is no other pending child process
416
+ support.reap_children()
417
+
418
+ # Create a child process
419
+ pid = os.fork()
420
+ if pid == 0:
421
+ # child process: do nothing, just exit
422
+ os._exit(0)
423
+
424
+ t0 = time.monotonic()
425
+ deadline = time.monotonic() + 60.0
426
+
427
+ was_altered = support.environment_altered
428
+ try:
429
+ support.environment_altered = False
430
+ stderr = io.StringIO()
431
+
432
+ while True:
433
+ if time.monotonic() > deadline:
434
+ self.fail("timeout")
435
+
436
+ old_stderr = sys.__stderr__
437
+ try:
438
+ sys.__stderr__ = stderr
439
+ support.reap_children()
440
+ finally:
441
+ sys.__stderr__ = old_stderr
442
+
443
+ # Use environment_altered to check if reap_children() found
444
+ # the child process
445
+ if support.environment_altered:
446
+ break
447
+
448
+ # loop until the child process completed
449
+ time.sleep(0.100)
450
+
451
+ msg = "Warning -- reap_children() reaped child process %s" % pid
452
+ self.assertIn(msg, stderr.getvalue())
453
+ self.assertTrue(support.environment_altered)
454
+ finally:
455
+ support.environment_altered = was_altered
456
+
457
+ # Just in case, check again that there is no other
458
+ # pending child process
459
+ support.reap_children()
460
+
461
+ def check_options(self, args, func, expected=None):
462
+ code = f'from test.support import {func}; print(repr({func}()))'
463
+ cmd = [sys.executable, *args, '-c', code]
464
+ env = {key: value for key, value in os.environ.items()
465
+ if not key.startswith('PYTHON')}
466
+ proc = subprocess.run(cmd,
467
+ stdout=subprocess.PIPE,
468
+ stderr=subprocess.DEVNULL,
469
+ universal_newlines=True,
470
+ env=env)
471
+ if expected is None:
472
+ expected = args
473
+ self.assertEqual(proc.stdout.rstrip(), repr(expected))
474
+ self.assertEqual(proc.returncode, 0)
475
+
476
+ def test_args_from_interpreter_flags(self):
477
+ # Test test.support.args_from_interpreter_flags()
478
+ for opts in (
479
+ # no option
480
+ [],
481
+ # single option
482
+ ['-B'],
483
+ ['-s'],
484
+ ['-S'],
485
+ ['-E'],
486
+ ['-v'],
487
+ ['-b'],
488
+ ['-q'],
489
+ ['-I'],
490
+ # same option multiple times
491
+ ['-bb'],
492
+ ['-vvv'],
493
+ # -W options
494
+ ['-Wignore'],
495
+ # -X options
496
+ ['-X', 'dev'],
497
+ ['-Wignore', '-X', 'dev'],
498
+ ['-X', 'faulthandler'],
499
+ ['-X', 'importtime'],
500
+ ['-X', 'showalloccount'],
501
+ ['-X', 'showrefcount'],
502
+ ['-X', 'tracemalloc'],
503
+ ['-X', 'tracemalloc=3'],
504
+ ):
505
+ with self.subTest(opts=opts):
506
+ self.check_options(opts, 'args_from_interpreter_flags')
507
+
508
+ self.check_options(['-I', '-E', '-s'], 'args_from_interpreter_flags',
509
+ ['-I'])
510
+
511
+ def test_optim_args_from_interpreter_flags(self):
512
+ # Test test.support.optim_args_from_interpreter_flags()
513
+ for opts in (
514
+ # no option
515
+ [],
516
+ ['-O'],
517
+ ['-OO'],
518
+ ['-OOOO'],
519
+ ):
520
+ with self.subTest(opts=opts):
521
+ self.check_options(opts, 'optim_args_from_interpreter_flags')
522
+
523
+ def test_match_test(self):
524
+ class Test:
525
+ def __init__(self, test_id):
526
+ self.test_id = test_id
527
+
528
+ def id(self):
529
+ return self.test_id
530
+
531
+ test_access = Test('test.test_os.FileTests.test_access')
532
+ test_chdir = Test('test.test_os.Win32ErrorTests.test_chdir')
533
+
534
+ # Test acceptance
535
+ with support.swap_attr(support, '_match_test_func', None):
536
+ # match all
537
+ support.set_match_tests([])
538
+ self.assertTrue(support.match_test(test_access))
539
+ self.assertTrue(support.match_test(test_chdir))
540
+
541
+ # match all using None
542
+ support.set_match_tests(None, None)
543
+ self.assertTrue(support.match_test(test_access))
544
+ self.assertTrue(support.match_test(test_chdir))
545
+
546
+ # match the full test identifier
547
+ support.set_match_tests([test_access.id()], None)
548
+ self.assertTrue(support.match_test(test_access))
549
+ self.assertFalse(support.match_test(test_chdir))
550
+
551
+ # match the module name
552
+ support.set_match_tests(['test_os'], None)
553
+ self.assertTrue(support.match_test(test_access))
554
+ self.assertTrue(support.match_test(test_chdir))
555
+
556
+ # Test '*' pattern
557
+ support.set_match_tests(['test_*'], None)
558
+ self.assertTrue(support.match_test(test_access))
559
+ self.assertTrue(support.match_test(test_chdir))
560
+
561
+ # Test case sensitivity
562
+ support.set_match_tests(['filetests'], None)
563
+ self.assertFalse(support.match_test(test_access))
564
+ support.set_match_tests(['FileTests'], None)
565
+ self.assertTrue(support.match_test(test_access))
566
+
567
+ # Test pattern containing '.' and a '*' metacharacter
568
+ support.set_match_tests(['*test_os.*.test_*'], None)
569
+ self.assertTrue(support.match_test(test_access))
570
+ self.assertTrue(support.match_test(test_chdir))
571
+
572
+ # Multiple patterns
573
+ support.set_match_tests([test_access.id(), test_chdir.id()], None)
574
+ self.assertTrue(support.match_test(test_access))
575
+ self.assertTrue(support.match_test(test_chdir))
576
+
577
+ support.set_match_tests(['test_access', 'DONTMATCH'], None)
578
+ self.assertTrue(support.match_test(test_access))
579
+ self.assertFalse(support.match_test(test_chdir))
580
+
581
+ # Test rejection
582
+ with support.swap_attr(support, '_match_test_func', None):
583
+ # match all
584
+ support.set_match_tests(ignore_patterns=[])
585
+ self.assertTrue(support.match_test(test_access))
586
+ self.assertTrue(support.match_test(test_chdir))
587
+
588
+ # match all using None
589
+ support.set_match_tests(None, None)
590
+ self.assertTrue(support.match_test(test_access))
591
+ self.assertTrue(support.match_test(test_chdir))
592
+
593
+ # match the full test identifier
594
+ support.set_match_tests(None, [test_access.id()])
595
+ self.assertFalse(support.match_test(test_access))
596
+ self.assertTrue(support.match_test(test_chdir))
597
+
598
+ # match the module name
599
+ support.set_match_tests(None, ['test_os'])
600
+ self.assertFalse(support.match_test(test_access))
601
+ self.assertFalse(support.match_test(test_chdir))
602
+
603
+ # Test '*' pattern
604
+ support.set_match_tests(None, ['test_*'])
605
+ self.assertFalse(support.match_test(test_access))
606
+ self.assertFalse(support.match_test(test_chdir))
607
+
608
+ # Test case sensitivity
609
+ support.set_match_tests(None, ['filetests'])
610
+ self.assertTrue(support.match_test(test_access))
611
+ support.set_match_tests(None, ['FileTests'])
612
+ self.assertFalse(support.match_test(test_access))
613
+
614
+ # Test pattern containing '.' and a '*' metacharacter
615
+ support.set_match_tests(None, ['*test_os.*.test_*'])
616
+ self.assertFalse(support.match_test(test_access))
617
+ self.assertFalse(support.match_test(test_chdir))
618
+
619
+ # Multiple patterns
620
+ support.set_match_tests(None, [test_access.id(), test_chdir.id()])
621
+ self.assertFalse(support.match_test(test_access))
622
+ self.assertFalse(support.match_test(test_chdir))
623
+
624
+ support.set_match_tests(None, ['test_access', 'DONTMATCH'])
625
+ self.assertFalse(support.match_test(test_access))
626
+ self.assertTrue(support.match_test(test_chdir))
627
+
628
+ def test_fd_count(self):
629
+ # We cannot test the absolute value of fd_count(): on old Linux
630
+ # kernel or glibc versions, os.urandom() keeps a FD open on
631
+ # /dev/urandom device and Python has 4 FD opens instead of 3.
632
+ start = support.fd_count()
633
+ fd = os.open(__file__, os.O_RDONLY)
634
+ try:
635
+ more = support.fd_count()
636
+ finally:
637
+ os.close(fd)
638
+ self.assertEqual(more - start, 1)
639
+
640
+ def check_print_warning(self, msg, expected):
641
+ stderr = io.StringIO()
642
+
643
+ old_stderr = sys.__stderr__
644
+ try:
645
+ sys.__stderr__ = stderr
646
+ support.print_warning(msg)
647
+ finally:
648
+ sys.__stderr__ = old_stderr
649
+
650
+ self.assertEqual(stderr.getvalue(), expected)
651
+
652
+ def test_print_warning(self):
653
+ self.check_print_warning("msg",
654
+ "Warning -- msg\n")
655
+ self.check_print_warning("a\nb",
656
+ 'Warning -- a\nWarning -- b\n')
657
+
658
+ # XXX -follows a list of untested API
659
+ # make_legacy_pyc
660
+ # is_resource_enabled
661
+ # requires
662
+ # fcmp
663
+ # umaks
664
+ # findfile
665
+ # check_warnings
666
+ # EnvironmentVarGuard
667
+ # TransientResource
668
+ # transient_internet
669
+ # run_with_locale
670
+ # set_memlimit
671
+ # bigmemtest
672
+ # precisionbigmemtest
673
+ # bigaddrspacetest
674
+ # requires_resource
675
+ # run_doctest
676
+ # threading_cleanup
677
+ # reap_threads
678
+ # strip_python_stderr
679
+ # can_symlink
680
+ # skip_unless_symlink
681
+ # SuppressCrashReport
682
+
683
+
684
+ def test_main():
685
+ tests = [TestSupport]
686
+ support.run_unittest(*tests)
687
+
688
+ if __name__ == '__main__':
689
+ test_main()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ --------------------------------------
3
+ About this viewer
4
+ --------------------------------------
5
+
6
+ Tiny demo viewer to view turtle graphics example scripts.
7
+
8
+ Quickly and dirtyly assembled by Gregor Lingl.
9
+ June, 2006
10
+
11
+ For more information see: turtledemo - Help
12
+
13
+ Have fun!
14
+ """
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/__main__.py ADDED
@@ -0,0 +1,386 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ ----------------------------------------------
5
+ turtleDemo - Help
6
+ ----------------------------------------------
7
+
8
+ This document has two sections:
9
+
10
+ (1) How to use the demo viewer
11
+ (2) How to add your own demos to the demo repository
12
+
13
+
14
+ (1) How to use the demo viewer.
15
+
16
+ Select a demoscript from the example menu.
17
+ The (syntax colored) source code appears in the left
18
+ source code window. IT CANNOT BE EDITED, but ONLY VIEWED!
19
+
20
+ The demo viewer windows can be resized. The divider between text
21
+ and canvas can be moved by grabbing it with the mouse. The text font
22
+ size can be changed from the menu and with Control/Command '-'/'+'.
23
+ It can also be changed on most systems with Control-mousewheel
24
+ when the mouse is over the text.
25
+
26
+ Press START button to start the demo.
27
+ Stop execution by pressing the STOP button.
28
+ Clear screen by pressing the CLEAR button.
29
+ Restart by pressing the START button again.
30
+
31
+ SPECIAL demos, such as clock.py are those which run EVENTDRIVEN.
32
+
33
+ Press START button to start the demo.
34
+
35
+ - Until the EVENTLOOP is entered everything works
36
+ as in an ordinary demo script.
37
+
38
+ - When the EVENTLOOP is entered, you control the
39
+ application by using the mouse and/or keys (or it's
40
+ controlled by some timer events)
41
+ To stop it you can and must press the STOP button.
42
+
43
+ While the EVENTLOOP is running, the examples menu is disabled.
44
+
45
+ - Only after having pressed the STOP button, you may
46
+ restart it or choose another example script.
47
+
48
+ * * * * * * * *
49
+ In some rare situations there may occur interferences/conflicts
50
+ between events concerning the demo script and those concerning the
51
+ demo-viewer. (They run in the same process.) Strange behaviour may be
52
+ the consequence and in the worst case you must close and restart the
53
+ viewer.
54
+ * * * * * * * *
55
+
56
+
57
+ (2) How to add your own demos to the demo repository
58
+
59
+ - Place the file in the same directory as turtledemo/__main__.py
60
+ IMPORTANT! When imported, the demo should not modify the system
61
+ by calling functions in other modules, such as sys, tkinter, or
62
+ turtle. Global variables should be initialized in main().
63
+
64
+ - The code must contain a main() function which will
65
+ be executed by the viewer (see provided example scripts).
66
+ It may return a string which will be displayed in the Label below
67
+ the source code window (when execution has finished.)
68
+
69
+ - In order to run mydemo.py by itself, such as during development,
70
+ add the following at the end of the file:
71
+
72
+ if __name__ == '__main__':
73
+ main()
74
+ mainloop() # keep window open
75
+
76
+ python -m turtledemo.mydemo # will then run it
77
+
78
+ - If the demo is EVENT DRIVEN, main must return the string
79
+ "EVENTLOOP". This informs the demo viewer that the script is
80
+ still running and must be stopped by the user!
81
+
82
+ If an "EVENTLOOP" demo runs by itself, as with clock, which uses
83
+ ontimer, or minimal_hanoi, which loops by recursion, then the
84
+ code should catch the turtle.Terminator exception that will be
85
+ raised when the user presses the STOP button. (Paint is not such
86
+ a demo; it only acts in response to mouse clicks and movements.)
87
+ """
88
+ import sys
89
+ import os
90
+
91
+ from tkinter import *
92
+ from idlelib.colorizer import ColorDelegator, color_config
93
+ from idlelib.percolator import Percolator
94
+ from idlelib.textview import view_text
95
+ from turtledemo import __doc__ as about_turtledemo
96
+
97
+ import turtle
98
+
99
+ demo_dir = os.path.dirname(os.path.abspath(__file__))
100
+ darwin = sys.platform == 'darwin'
101
+
102
+ STARTUP = 1
103
+ READY = 2
104
+ RUNNING = 3
105
+ DONE = 4
106
+ EVENTDRIVEN = 5
107
+
108
+ menufont = ("Arial", 12, NORMAL)
109
+ btnfont = ("Arial", 12, 'bold')
110
+ txtfont = ['Lucida Console', 10, 'normal']
111
+
112
+ MINIMUM_FONT_SIZE = 6
113
+ MAXIMUM_FONT_SIZE = 100
114
+ font_sizes = [8, 9, 10, 11, 12, 14, 18, 20, 22, 24, 30]
115
+
116
+ def getExampleEntries():
117
+ return [entry[:-3] for entry in os.listdir(demo_dir) if
118
+ entry.endswith(".py") and entry[0] != '_']
119
+
120
+ help_entries = ( # (help_label, help_doc)
121
+ ('Turtledemo help', __doc__),
122
+ ('About turtledemo', about_turtledemo),
123
+ ('About turtle module', turtle.__doc__),
124
+ )
125
+
126
+
127
+
128
+ class DemoWindow(object):
129
+
130
+ def __init__(self, filename=None):
131
+ self.root = root = turtle._root = Tk()
132
+ root.title('Python turtle-graphics examples')
133
+ root.wm_protocol("WM_DELETE_WINDOW", self._destroy)
134
+
135
+ if darwin:
136
+ import subprocess
137
+ # Make sure we are the currently activated OS X application
138
+ # so that our menu bar appears.
139
+ subprocess.run(
140
+ [
141
+ 'osascript',
142
+ '-e', 'tell application "System Events"',
143
+ '-e', 'set frontmost of the first process whose '
144
+ 'unix id is {} to true'.format(os.getpid()),
145
+ '-e', 'end tell',
146
+ ],
147
+ stderr=subprocess.DEVNULL,
148
+ stdout=subprocess.DEVNULL,)
149
+
150
+ root.grid_rowconfigure(0, weight=1)
151
+ root.grid_columnconfigure(0, weight=1)
152
+ root.grid_columnconfigure(1, minsize=90, weight=1)
153
+ root.grid_columnconfigure(2, minsize=90, weight=1)
154
+ root.grid_columnconfigure(3, minsize=90, weight=1)
155
+
156
+ self.mBar = Menu(root, relief=RAISED, borderwidth=2)
157
+ self.mBar.add_cascade(menu=self.makeLoadDemoMenu(self.mBar),
158
+ label='Examples', underline=0)
159
+ self.mBar.add_cascade(menu=self.makeFontMenu(self.mBar),
160
+ label='Fontsize', underline=0)
161
+ self.mBar.add_cascade(menu=self.makeHelpMenu(self.mBar),
162
+ label='Help', underline=0)
163
+ root['menu'] = self.mBar
164
+
165
+ pane = PanedWindow(orient=HORIZONTAL, sashwidth=5,
166
+ sashrelief=SOLID, bg='#ddd')
167
+ pane.add(self.makeTextFrame(pane))
168
+ pane.add(self.makeGraphFrame(pane))
169
+ pane.grid(row=0, columnspan=4, sticky='news')
170
+
171
+ self.output_lbl = Label(root, height= 1, text=" --- ", bg="#ddf",
172
+ font=("Arial", 16, 'normal'), borderwidth=2,
173
+ relief=RIDGE)
174
+ self.start_btn = Button(root, text=" START ", font=btnfont,
175
+ fg="white", disabledforeground = "#fed",
176
+ command=self.startDemo)
177
+ self.stop_btn = Button(root, text=" STOP ", font=btnfont,
178
+ fg="white", disabledforeground = "#fed",
179
+ command=self.stopIt)
180
+ self.clear_btn = Button(root, text=" CLEAR ", font=btnfont,
181
+ fg="white", disabledforeground="#fed",
182
+ command = self.clearCanvas)
183
+ self.output_lbl.grid(row=1, column=0, sticky='news', padx=(0,5))
184
+ self.start_btn.grid(row=1, column=1, sticky='ew')
185
+ self.stop_btn.grid(row=1, column=2, sticky='ew')
186
+ self.clear_btn.grid(row=1, column=3, sticky='ew')
187
+
188
+ Percolator(self.text).insertfilter(ColorDelegator())
189
+ self.dirty = False
190
+ self.exitflag = False
191
+ if filename:
192
+ self.loadfile(filename)
193
+ self.configGUI(DISABLED, DISABLED, DISABLED,
194
+ "Choose example from menu", "black")
195
+ self.state = STARTUP
196
+
197
+
198
+ def onResize(self, event):
199
+ cwidth = self._canvas.winfo_width()
200
+ cheight = self._canvas.winfo_height()
201
+ self._canvas.xview_moveto(0.5*(self.canvwidth-cwidth)/self.canvwidth)
202
+ self._canvas.yview_moveto(0.5*(self.canvheight-cheight)/self.canvheight)
203
+
204
+ def makeTextFrame(self, root):
205
+ self.text_frame = text_frame = Frame(root)
206
+ self.text = text = Text(text_frame, name='text', padx=5,
207
+ wrap='none', width=45)
208
+ color_config(text)
209
+
210
+ self.vbar = vbar = Scrollbar(text_frame, name='vbar')
211
+ vbar['command'] = text.yview
212
+ vbar.pack(side=LEFT, fill=Y)
213
+ self.hbar = hbar = Scrollbar(text_frame, name='hbar', orient=HORIZONTAL)
214
+ hbar['command'] = text.xview
215
+ hbar.pack(side=BOTTOM, fill=X)
216
+ text['yscrollcommand'] = vbar.set
217
+ text['xscrollcommand'] = hbar.set
218
+
219
+ text['font'] = tuple(txtfont)
220
+ shortcut = 'Command' if darwin else 'Control'
221
+ text.bind_all('<%s-minus>' % shortcut, self.decrease_size)
222
+ text.bind_all('<%s-underscore>' % shortcut, self.decrease_size)
223
+ text.bind_all('<%s-equal>' % shortcut, self.increase_size)
224
+ text.bind_all('<%s-plus>' % shortcut, self.increase_size)
225
+ text.bind('<Control-MouseWheel>', self.update_mousewheel)
226
+ text.bind('<Control-Button-4>', self.increase_size)
227
+ text.bind('<Control-Button-5>', self.decrease_size)
228
+
229
+ text.pack(side=LEFT, fill=BOTH, expand=1)
230
+ return text_frame
231
+
232
+ def makeGraphFrame(self, root):
233
+ turtle._Screen._root = root
234
+ self.canvwidth = 1000
235
+ self.canvheight = 800
236
+ turtle._Screen._canvas = self._canvas = canvas = turtle.ScrolledCanvas(
237
+ root, 800, 600, self.canvwidth, self.canvheight)
238
+ canvas.adjustScrolls()
239
+ canvas._rootwindow.bind('<Configure>', self.onResize)
240
+ canvas._canvas['borderwidth'] = 0
241
+
242
+ self.screen = _s_ = turtle.Screen()
243
+ turtle.TurtleScreen.__init__(_s_, _s_._canvas)
244
+ self.scanvas = _s_._canvas
245
+ turtle.RawTurtle.screens = [_s_]
246
+ return canvas
247
+
248
+ def set_txtsize(self, size):
249
+ txtfont[1] = size
250
+ self.text['font'] = tuple(txtfont)
251
+ self.output_lbl['text'] = 'Font size %d' % size
252
+
253
+ def decrease_size(self, dummy=None):
254
+ self.set_txtsize(max(txtfont[1] - 1, MINIMUM_FONT_SIZE))
255
+ return 'break'
256
+
257
+ def increase_size(self, dummy=None):
258
+ self.set_txtsize(min(txtfont[1] + 1, MAXIMUM_FONT_SIZE))
259
+ return 'break'
260
+
261
+ def update_mousewheel(self, event):
262
+ # For wheel up, event.delta = 120 on Windows, -1 on darwin.
263
+ # X-11 sends Control-Button-4 event instead.
264
+ if (event.delta < 0) == (not darwin):
265
+ return self.decrease_size()
266
+ else:
267
+ return self.increase_size()
268
+
269
+ def configGUI(self, start, stop, clear, txt="", color="blue"):
270
+ self.start_btn.config(state=start,
271
+ bg="#d00" if start == NORMAL else "#fca")
272
+ self.stop_btn.config(state=stop,
273
+ bg="#d00" if stop == NORMAL else "#fca")
274
+ self.clear_btn.config(state=clear,
275
+ bg="#d00" if clear == NORMAL else "#fca")
276
+ self.output_lbl.config(text=txt, fg=color)
277
+
278
+ def makeLoadDemoMenu(self, master):
279
+ menu = Menu(master)
280
+
281
+ for entry in getExampleEntries():
282
+ def load(entry=entry):
283
+ self.loadfile(entry)
284
+ menu.add_command(label=entry, underline=0,
285
+ font=menufont, command=load)
286
+ return menu
287
+
288
+ def makeFontMenu(self, master):
289
+ menu = Menu(master)
290
+ menu.add_command(label="Decrease (C-'-')", command=self.decrease_size,
291
+ font=menufont)
292
+ menu.add_command(label="Increase (C-'+')", command=self.increase_size,
293
+ font=menufont)
294
+ menu.add_separator()
295
+
296
+ for size in font_sizes:
297
+ def resize(size=size):
298
+ self.set_txtsize(size)
299
+ menu.add_command(label=str(size), underline=0,
300
+ font=menufont, command=resize)
301
+ return menu
302
+
303
+ def makeHelpMenu(self, master):
304
+ menu = Menu(master)
305
+
306
+ for help_label, help_file in help_entries:
307
+ def show(help_label=help_label, help_file=help_file):
308
+ view_text(self.root, help_label, help_file)
309
+ menu.add_command(label=help_label, font=menufont, command=show)
310
+ return menu
311
+
312
+ def refreshCanvas(self):
313
+ if self.dirty:
314
+ self.screen.clear()
315
+ self.dirty=False
316
+
317
+ def loadfile(self, filename):
318
+ self.clearCanvas()
319
+ turtle.TurtleScreen._RUNNING = False
320
+ modname = 'turtledemo.' + filename
321
+ __import__(modname)
322
+ self.module = sys.modules[modname]
323
+ with open(self.module.__file__, 'r') as f:
324
+ chars = f.read()
325
+ self.text.delete("1.0", "end")
326
+ self.text.insert("1.0", chars)
327
+ self.root.title(filename + " - a Python turtle graphics example")
328
+ self.configGUI(NORMAL, DISABLED, DISABLED,
329
+ "Press start button", "red")
330
+ self.state = READY
331
+
332
+ def startDemo(self):
333
+ self.refreshCanvas()
334
+ self.dirty = True
335
+ turtle.TurtleScreen._RUNNING = True
336
+ self.configGUI(DISABLED, NORMAL, DISABLED,
337
+ "demo running...", "black")
338
+ self.screen.clear()
339
+ self.screen.mode("standard")
340
+ self.state = RUNNING
341
+
342
+ try:
343
+ result = self.module.main()
344
+ if result == "EVENTLOOP":
345
+ self.state = EVENTDRIVEN
346
+ else:
347
+ self.state = DONE
348
+ except turtle.Terminator:
349
+ if self.root is None:
350
+ return
351
+ self.state = DONE
352
+ result = "stopped!"
353
+ if self.state == DONE:
354
+ self.configGUI(NORMAL, DISABLED, NORMAL,
355
+ result)
356
+ elif self.state == EVENTDRIVEN:
357
+ self.exitflag = True
358
+ self.configGUI(DISABLED, NORMAL, DISABLED,
359
+ "use mouse/keys or STOP", "red")
360
+
361
+ def clearCanvas(self):
362
+ self.refreshCanvas()
363
+ self.screen._delete("all")
364
+ self.scanvas.config(cursor="")
365
+ self.configGUI(NORMAL, DISABLED, DISABLED)
366
+
367
+ def stopIt(self):
368
+ if self.exitflag:
369
+ self.clearCanvas()
370
+ self.exitflag = False
371
+ self.configGUI(NORMAL, DISABLED, DISABLED,
372
+ "STOPPED!", "red")
373
+ turtle.TurtleScreen._RUNNING = False
374
+
375
+ def _destroy(self):
376
+ turtle.TurtleScreen._RUNNING = False
377
+ self.root.destroy()
378
+ self.root = None
379
+
380
+
381
+ def main():
382
+ demo = DemoWindow()
383
+ demo.root.mainloop()
384
+
385
+ if __name__ == '__main__':
386
+ main()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/bytedesign.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """ turtle-example-suite:
3
+
4
+ tdemo_bytedesign.py
5
+
6
+ An example adapted from the example-suite
7
+ of PythonCard's turtle graphics.
8
+
9
+ It's based on an article in BYTE magazine
10
+ Problem Solving with Logo: Using Turtle
11
+ Graphics to Redraw a Design
12
+ November 1982, p. 118 - 134
13
+
14
+ -------------------------------------------
15
+
16
+ Due to the statement
17
+
18
+ t.delay(0)
19
+
20
+ in line 152, which sets the animation delay
21
+ to 0, this animation runs in "line per line"
22
+ mode as fast as possible.
23
+ """
24
+
25
+ from turtle import Turtle, mainloop
26
+ from time import perf_counter as clock
27
+
28
+ # wrapper for any additional drawing routines
29
+ # that need to know about each other
30
+ class Designer(Turtle):
31
+
32
+ def design(self, homePos, scale):
33
+ self.up()
34
+ for i in range(5):
35
+ self.forward(64.65 * scale)
36
+ self.down()
37
+ self.wheel(self.position(), scale)
38
+ self.up()
39
+ self.backward(64.65 * scale)
40
+ self.right(72)
41
+ self.up()
42
+ self.goto(homePos)
43
+ self.right(36)
44
+ self.forward(24.5 * scale)
45
+ self.right(198)
46
+ self.down()
47
+ self.centerpiece(46 * scale, 143.4, scale)
48
+ self.getscreen().tracer(True)
49
+
50
+ def wheel(self, initpos, scale):
51
+ self.right(54)
52
+ for i in range(4):
53
+ self.pentpiece(initpos, scale)
54
+ self.down()
55
+ self.left(36)
56
+ for i in range(5):
57
+ self.tripiece(initpos, scale)
58
+ self.left(36)
59
+ for i in range(5):
60
+ self.down()
61
+ self.right(72)
62
+ self.forward(28 * scale)
63
+ self.up()
64
+ self.backward(28 * scale)
65
+ self.left(54)
66
+ self.getscreen().update()
67
+
68
+ def tripiece(self, initpos, scale):
69
+ oldh = self.heading()
70
+ self.down()
71
+ self.backward(2.5 * scale)
72
+ self.tripolyr(31.5 * scale, scale)
73
+ self.up()
74
+ self.goto(initpos)
75
+ self.setheading(oldh)
76
+ self.down()
77
+ self.backward(2.5 * scale)
78
+ self.tripolyl(31.5 * scale, scale)
79
+ self.up()
80
+ self.goto(initpos)
81
+ self.setheading(oldh)
82
+ self.left(72)
83
+ self.getscreen().update()
84
+
85
+ def pentpiece(self, initpos, scale):
86
+ oldh = self.heading()
87
+ self.up()
88
+ self.forward(29 * scale)
89
+ self.down()
90
+ for i in range(5):
91
+ self.forward(18 * scale)
92
+ self.right(72)
93
+ self.pentr(18 * scale, 75, scale)
94
+ self.up()
95
+ self.goto(initpos)
96
+ self.setheading(oldh)
97
+ self.forward(29 * scale)
98
+ self.down()
99
+ for i in range(5):
100
+ self.forward(18 * scale)
101
+ self.right(72)
102
+ self.pentl(18 * scale, 75, scale)
103
+ self.up()
104
+ self.goto(initpos)
105
+ self.setheading(oldh)
106
+ self.left(72)
107
+ self.getscreen().update()
108
+
109
+ def pentl(self, side, ang, scale):
110
+ if side < (2 * scale): return
111
+ self.forward(side)
112
+ self.left(ang)
113
+ self.pentl(side - (.38 * scale), ang, scale)
114
+
115
+ def pentr(self, side, ang, scale):
116
+ if side < (2 * scale): return
117
+ self.forward(side)
118
+ self.right(ang)
119
+ self.pentr(side - (.38 * scale), ang, scale)
120
+
121
+ def tripolyr(self, side, scale):
122
+ if side < (4 * scale): return
123
+ self.forward(side)
124
+ self.right(111)
125
+ self.forward(side / 1.78)
126
+ self.right(111)
127
+ self.forward(side / 1.3)
128
+ self.right(146)
129
+ self.tripolyr(side * .75, scale)
130
+
131
+ def tripolyl(self, side, scale):
132
+ if side < (4 * scale): return
133
+ self.forward(side)
134
+ self.left(111)
135
+ self.forward(side / 1.78)
136
+ self.left(111)
137
+ self.forward(side / 1.3)
138
+ self.left(146)
139
+ self.tripolyl(side * .75, scale)
140
+
141
+ def centerpiece(self, s, a, scale):
142
+ self.forward(s); self.left(a)
143
+ if s < (7.5 * scale):
144
+ return
145
+ self.centerpiece(s - (1.2 * scale), a, scale)
146
+
147
+ def main():
148
+ t = Designer()
149
+ t.speed(0)
150
+ t.hideturtle()
151
+ t.getscreen().delay(0)
152
+ t.getscreen().tracer(0)
153
+ at = clock()
154
+ t.design(t.position(), 2)
155
+ et = clock()
156
+ return "runtime: %.2f sec." % (et-at)
157
+
158
+ if __name__ == '__main__':
159
+ msg = main()
160
+ print(msg)
161
+ mainloop()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/chaos.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # File: tdemo_chaos.py
2
+ # Author: Gregor Lingl
3
+ # Date: 2009-06-24
4
+
5
+ # A demonstration of chaos
6
+
7
+ from turtle import *
8
+
9
+ N = 80
10
+
11
+ def f(x):
12
+ return 3.9*x*(1-x)
13
+
14
+ def g(x):
15
+ return 3.9*(x-x**2)
16
+
17
+ def h(x):
18
+ return 3.9*x-3.9*x*x
19
+
20
+ def jumpto(x, y):
21
+ penup(); goto(x,y)
22
+
23
+ def line(x1, y1, x2, y2):
24
+ jumpto(x1, y1)
25
+ pendown()
26
+ goto(x2, y2)
27
+
28
+ def coosys():
29
+ line(-1, 0, N+1, 0)
30
+ line(0, -0.1, 0, 1.1)
31
+
32
+ def plot(fun, start, color):
33
+ pencolor(color)
34
+ x = start
35
+ jumpto(0, x)
36
+ pendown()
37
+ dot(5)
38
+ for i in range(N):
39
+ x=fun(x)
40
+ goto(i+1,x)
41
+ dot(5)
42
+
43
+ def main():
44
+ reset()
45
+ setworldcoordinates(-1.0,-0.1, N+1, 1.1)
46
+ speed(0)
47
+ hideturtle()
48
+ coosys()
49
+ plot(f, 0.35, "blue")
50
+ plot(g, 0.35, "green")
51
+ plot(h, 0.35, "red")
52
+ # Now zoom in:
53
+ for s in range(100):
54
+ setworldcoordinates(0.5*s,-0.1, N+1, 1.1)
55
+ return "Done!"
56
+
57
+ if __name__ == "__main__":
58
+ main()
59
+ mainloop()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/clock.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: cp1252 -*-
3
+ """ turtle-example-suite:
4
+
5
+ tdemo_clock.py
6
+
7
+ Enhanced clock-program, showing date
8
+ and time
9
+ ------------------------------------
10
+ Press STOP to exit the program!
11
+ ------------------------------------
12
+ """
13
+ from turtle import *
14
+ from datetime import datetime
15
+
16
+ def jump(distanz, winkel=0):
17
+ penup()
18
+ right(winkel)
19
+ forward(distanz)
20
+ left(winkel)
21
+ pendown()
22
+
23
+ def hand(laenge, spitze):
24
+ fd(laenge*1.15)
25
+ rt(90)
26
+ fd(spitze/2.0)
27
+ lt(120)
28
+ fd(spitze)
29
+ lt(120)
30
+ fd(spitze)
31
+ lt(120)
32
+ fd(spitze/2.0)
33
+
34
+ def make_hand_shape(name, laenge, spitze):
35
+ reset()
36
+ jump(-laenge*0.15)
37
+ begin_poly()
38
+ hand(laenge, spitze)
39
+ end_poly()
40
+ hand_form = get_poly()
41
+ register_shape(name, hand_form)
42
+
43
+ def clockface(radius):
44
+ reset()
45
+ pensize(7)
46
+ for i in range(60):
47
+ jump(radius)
48
+ if i % 5 == 0:
49
+ fd(25)
50
+ jump(-radius-25)
51
+ else:
52
+ dot(3)
53
+ jump(-radius)
54
+ rt(6)
55
+
56
+ def setup():
57
+ global second_hand, minute_hand, hour_hand, writer
58
+ mode("logo")
59
+ make_hand_shape("second_hand", 125, 25)
60
+ make_hand_shape("minute_hand", 130, 25)
61
+ make_hand_shape("hour_hand", 90, 25)
62
+ clockface(160)
63
+ second_hand = Turtle()
64
+ second_hand.shape("second_hand")
65
+ second_hand.color("gray20", "gray80")
66
+ minute_hand = Turtle()
67
+ minute_hand.shape("minute_hand")
68
+ minute_hand.color("blue1", "red1")
69
+ hour_hand = Turtle()
70
+ hour_hand.shape("hour_hand")
71
+ hour_hand.color("blue3", "red3")
72
+ for hand in second_hand, minute_hand, hour_hand:
73
+ hand.resizemode("user")
74
+ hand.shapesize(1, 1, 3)
75
+ hand.speed(0)
76
+ ht()
77
+ writer = Turtle()
78
+ #writer.mode("logo")
79
+ writer.ht()
80
+ writer.pu()
81
+ writer.bk(85)
82
+
83
+ def wochentag(t):
84
+ wochentag = ["Monday", "Tuesday", "Wednesday",
85
+ "Thursday", "Friday", "Saturday", "Sunday"]
86
+ return wochentag[t.weekday()]
87
+
88
+ def datum(z):
89
+ monat = ["Jan.", "Feb.", "Mar.", "Apr.", "May", "June",
90
+ "July", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."]
91
+ j = z.year
92
+ m = monat[z.month - 1]
93
+ t = z.day
94
+ return "%s %d %d" % (m, t, j)
95
+
96
+ def tick():
97
+ t = datetime.today()
98
+ sekunde = t.second + t.microsecond*0.000001
99
+ minute = t.minute + sekunde/60.0
100
+ stunde = t.hour + minute/60.0
101
+ try:
102
+ tracer(False) # Terminator can occur here
103
+ writer.clear()
104
+ writer.home()
105
+ writer.forward(65)
106
+ writer.write(wochentag(t),
107
+ align="center", font=("Courier", 14, "bold"))
108
+ writer.back(150)
109
+ writer.write(datum(t),
110
+ align="center", font=("Courier", 14, "bold"))
111
+ writer.forward(85)
112
+ tracer(True)
113
+ second_hand.setheading(6*sekunde) # or here
114
+ minute_hand.setheading(6*minute)
115
+ hour_hand.setheading(30*stunde)
116
+ tracer(True)
117
+ ontimer(tick, 100)
118
+ except Terminator:
119
+ pass # turtledemo user pressed STOP
120
+
121
+ def main():
122
+ tracer(False)
123
+ setup()
124
+ tracer(True)
125
+ tick()
126
+ return "EVENTLOOP"
127
+
128
+ if __name__ == "__main__":
129
+ mode("logo")
130
+ msg = main()
131
+ print(msg)
132
+ mainloop()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/colormixer.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # colormixer
2
+
3
+ from turtle import Screen, Turtle, mainloop
4
+
5
+ class ColorTurtle(Turtle):
6
+
7
+ def __init__(self, x, y):
8
+ Turtle.__init__(self)
9
+ self.shape("turtle")
10
+ self.resizemode("user")
11
+ self.shapesize(3,3,5)
12
+ self.pensize(10)
13
+ self._color = [0,0,0]
14
+ self.x = x
15
+ self._color[x] = y
16
+ self.color(self._color)
17
+ self.speed(0)
18
+ self.left(90)
19
+ self.pu()
20
+ self.goto(x,0)
21
+ self.pd()
22
+ self.sety(1)
23
+ self.pu()
24
+ self.sety(y)
25
+ self.pencolor("gray25")
26
+ self.ondrag(self.shift)
27
+
28
+ def shift(self, x, y):
29
+ self.sety(max(0,min(y,1)))
30
+ self._color[self.x] = self.ycor()
31
+ self.fillcolor(self._color)
32
+ setbgcolor()
33
+
34
+ def setbgcolor():
35
+ screen.bgcolor(red.ycor(), green.ycor(), blue.ycor())
36
+
37
+ def main():
38
+ global screen, red, green, blue
39
+ screen = Screen()
40
+ screen.delay(0)
41
+ screen.setworldcoordinates(-1, -0.3, 3, 1.3)
42
+
43
+ red = ColorTurtle(0, .5)
44
+ green = ColorTurtle(1, .5)
45
+ blue = ColorTurtle(2, .5)
46
+ setbgcolor()
47
+
48
+ writer = Turtle()
49
+ writer.ht()
50
+ writer.pu()
51
+ writer.goto(1,1.15)
52
+ writer.write("DRAG!",align="center",font=("Arial",30,("bold","italic")))
53
+ return "EVENTLOOP"
54
+
55
+ if __name__ == "__main__":
56
+ msg = main()
57
+ print(msg)
58
+ mainloop()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/forest.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """ turtlegraphics-example-suite:
3
+
4
+ tdemo_forest.py
5
+
6
+ Displays a 'forest' of 3 breadth-first-trees
7
+ similar to the one in tree.
8
+ For further remarks see tree.py
9
+
10
+ This example is a 'breadth-first'-rewrite of
11
+ a Logo program written by Erich Neuwirth. See
12
+ http://homepage.univie.ac.at/erich.neuwirth/
13
+ """
14
+ from turtle import Turtle, colormode, tracer, mainloop
15
+ from random import randrange
16
+ from time import perf_counter as clock
17
+
18
+ def symRandom(n):
19
+ return randrange(-n,n+1)
20
+
21
+ def randomize( branchlist, angledist, sizedist ):
22
+ return [ (angle+symRandom(angledist),
23
+ sizefactor*1.01**symRandom(sizedist))
24
+ for angle, sizefactor in branchlist ]
25
+
26
+ def randomfd( t, distance, parts, angledist ):
27
+ for i in range(parts):
28
+ t.left(symRandom(angledist))
29
+ t.forward( (1.0 * distance)/parts )
30
+
31
+ def tree(tlist, size, level, widthfactor, branchlists, angledist=10, sizedist=5):
32
+ # benutzt Liste von turtles und Liste von Zweiglisten,
33
+ # fuer jede turtle eine!
34
+ if level > 0:
35
+ lst = []
36
+ brs = []
37
+ for t, branchlist in list(zip(tlist,branchlists)):
38
+ t.pensize( size * widthfactor )
39
+ t.pencolor( 255 - (180 - 11 * level + symRandom(15)),
40
+ 180 - 11 * level + symRandom(15),
41
+ 0 )
42
+ t.pendown()
43
+ randomfd(t, size, level, angledist )
44
+ yield 1
45
+ for angle, sizefactor in branchlist:
46
+ t.left(angle)
47
+ lst.append(t.clone())
48
+ brs.append(randomize(branchlist, angledist, sizedist))
49
+ t.right(angle)
50
+ for x in tree(lst, size*sizefactor, level-1, widthfactor, brs,
51
+ angledist, sizedist):
52
+ yield None
53
+
54
+
55
+ def start(t,x,y):
56
+ colormode(255)
57
+ t.reset()
58
+ t.speed(0)
59
+ t.hideturtle()
60
+ t.left(90)
61
+ t.penup()
62
+ t.setpos(x,y)
63
+ t.pendown()
64
+
65
+ def doit1(level, pen):
66
+ pen.hideturtle()
67
+ start(pen, 20, -208)
68
+ t = tree( [pen], 80, level, 0.1, [[ (45,0.69), (0,0.65), (-45,0.71) ]] )
69
+ return t
70
+
71
+ def doit2(level, pen):
72
+ pen.hideturtle()
73
+ start(pen, -135, -130)
74
+ t = tree( [pen], 120, level, 0.1, [[ (45,0.69), (-45,0.71) ]] )
75
+ return t
76
+
77
+ def doit3(level, pen):
78
+ pen.hideturtle()
79
+ start(pen, 190, -90)
80
+ t = tree( [pen], 100, level, 0.1, [[ (45,0.7), (0,0.72), (-45,0.65) ]] )
81
+ return t
82
+
83
+ # Hier 3 Baumgeneratoren:
84
+ def main():
85
+ p = Turtle()
86
+ p.ht()
87
+ tracer(75,0)
88
+ u = doit1(6, Turtle(undobuffersize=1))
89
+ s = doit2(7, Turtle(undobuffersize=1))
90
+ t = doit3(5, Turtle(undobuffersize=1))
91
+ a = clock()
92
+ while True:
93
+ done = 0
94
+ for b in u,s,t:
95
+ try:
96
+ b.__next__()
97
+ except:
98
+ done += 1
99
+ if done == 3:
100
+ break
101
+
102
+ tracer(1,10)
103
+ b = clock()
104
+ return "runtime: %.2f sec." % (b-a)
105
+
106
+ if __name__ == '__main__':
107
+ main()
108
+ mainloop()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/lindenmayer.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """ turtle-example-suite:
3
+
4
+ xtx_lindenmayer_indian.py
5
+
6
+ Each morning women in Tamil Nadu, in southern
7
+ India, place designs, created by using rice
8
+ flour and known as kolam on the thresholds of
9
+ their homes.
10
+
11
+ These can be described by Lindenmayer systems,
12
+ which can easily be implemented with turtle
13
+ graphics and Python.
14
+
15
+ Two examples are shown here:
16
+ (1) the snake kolam
17
+ (2) anklets of Krishna
18
+
19
+ Taken from Marcia Ascher: Mathematics
20
+ Elsewhere, An Exploration of Ideas Across
21
+ Cultures
22
+
23
+ """
24
+ ################################
25
+ # Mini Lindenmayer tool
26
+ ###############################
27
+
28
+ from turtle import *
29
+
30
+ def replace( seq, replacementRules, n ):
31
+ for i in range(n):
32
+ newseq = ""
33
+ for element in seq:
34
+ newseq = newseq + replacementRules.get(element,element)
35
+ seq = newseq
36
+ return seq
37
+
38
+ def draw( commands, rules ):
39
+ for b in commands:
40
+ try:
41
+ rules[b]()
42
+ except TypeError:
43
+ try:
44
+ draw(rules[b], rules)
45
+ except:
46
+ pass
47
+
48
+
49
+ def main():
50
+ ################################
51
+ # Example 1: Snake kolam
52
+ ################################
53
+
54
+
55
+ def r():
56
+ right(45)
57
+
58
+ def l():
59
+ left(45)
60
+
61
+ def f():
62
+ forward(7.5)
63
+
64
+ snake_rules = {"-":r, "+":l, "f":f, "b":"f+f+f--f--f+f+f"}
65
+ snake_replacementRules = {"b": "b+f+b--f--b+f+b"}
66
+ snake_start = "b--f--b--f"
67
+
68
+ drawing = replace(snake_start, snake_replacementRules, 3)
69
+
70
+ reset()
71
+ speed(3)
72
+ tracer(1,0)
73
+ ht()
74
+ up()
75
+ backward(195)
76
+ down()
77
+ draw(drawing, snake_rules)
78
+
79
+ from time import sleep
80
+ sleep(3)
81
+
82
+ ################################
83
+ # Example 2: Anklets of Krishna
84
+ ################################
85
+
86
+ def A():
87
+ color("red")
88
+ circle(10,90)
89
+
90
+ def B():
91
+ from math import sqrt
92
+ color("black")
93
+ l = 5/sqrt(2)
94
+ forward(l)
95
+ circle(l, 270)
96
+ forward(l)
97
+
98
+ def F():
99
+ color("green")
100
+ forward(10)
101
+
102
+ krishna_rules = {"a":A, "b":B, "f":F}
103
+ krishna_replacementRules = {"a" : "afbfa", "b" : "afbfbfbfa" }
104
+ krishna_start = "fbfbfbfb"
105
+
106
+ reset()
107
+ speed(0)
108
+ tracer(3,0)
109
+ ht()
110
+ left(45)
111
+ drawing = replace(krishna_start, krishna_replacementRules, 3)
112
+ draw(drawing, krishna_rules)
113
+ tracer(1)
114
+ return "Done!"
115
+
116
+ if __name__=='__main__':
117
+ msg = main()
118
+ print(msg)
119
+ mainloop()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/minimal_hanoi.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """ turtle-example-suite:
3
+
4
+ tdemo_minimal_hanoi.py
5
+
6
+ A minimal 'Towers of Hanoi' animation:
7
+ A tower of 6 discs is transferred from the
8
+ left to the right peg.
9
+
10
+ An imho quite elegant and concise
11
+ implementation using a tower class, which
12
+ is derived from the built-in type list.
13
+
14
+ Discs are turtles with shape "square", but
15
+ stretched to rectangles by shapesize()
16
+ ---------------------------------------
17
+ To exit press STOP button
18
+ ---------------------------------------
19
+ """
20
+ from turtle import *
21
+
22
+ class Disc(Turtle):
23
+ def __init__(self, n):
24
+ Turtle.__init__(self, shape="square", visible=False)
25
+ self.pu()
26
+ self.shapesize(1.5, n*1.5, 2) # square-->rectangle
27
+ self.fillcolor(n/6., 0, 1-n/6.)
28
+ self.st()
29
+
30
+ class Tower(list):
31
+ "Hanoi tower, a subclass of built-in type list"
32
+ def __init__(self, x):
33
+ "create an empty tower. x is x-position of peg"
34
+ self.x = x
35
+ def push(self, d):
36
+ d.setx(self.x)
37
+ d.sety(-150+34*len(self))
38
+ self.append(d)
39
+ def pop(self):
40
+ d = list.pop(self)
41
+ d.sety(150)
42
+ return d
43
+
44
+ def hanoi(n, from_, with_, to_):
45
+ if n > 0:
46
+ hanoi(n-1, from_, to_, with_)
47
+ to_.push(from_.pop())
48
+ hanoi(n-1, with_, from_, to_)
49
+
50
+ def play():
51
+ onkey(None,"space")
52
+ clear()
53
+ try:
54
+ hanoi(6, t1, t2, t3)
55
+ write("press STOP button to exit",
56
+ align="center", font=("Courier", 16, "bold"))
57
+ except Terminator:
58
+ pass # turtledemo user pressed STOP
59
+
60
+ def main():
61
+ global t1, t2, t3
62
+ ht(); penup(); goto(0, -225) # writer turtle
63
+ t1 = Tower(-250)
64
+ t2 = Tower(0)
65
+ t3 = Tower(250)
66
+ # make tower of 6 discs
67
+ for i in range(6,0,-1):
68
+ t1.push(Disc(i))
69
+ # prepare spartanic user interface ;-)
70
+ write("press spacebar to start game",
71
+ align="center", font=("Courier", 16, "bold"))
72
+ onkey(play, "space")
73
+ listen()
74
+ return "EVENTLOOP"
75
+
76
+ if __name__=="__main__":
77
+ msg = main()
78
+ print(msg)
79
+ mainloop()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/paint.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """ turtle-example-suite:
3
+
4
+ tdemo_paint.py
5
+
6
+ A simple event-driven paint program
7
+
8
+ - left mouse button moves turtle
9
+ - middle mouse button changes color
10
+ - right mouse button toggles between pen up
11
+ (no line drawn when the turtle moves) and
12
+ pen down (line is drawn). If pen up follows
13
+ at least two pen-down moves, the polygon that
14
+ includes the starting point is filled.
15
+ -------------------------------------------
16
+ Play around by clicking into the canvas
17
+ using all three mouse buttons.
18
+ -------------------------------------------
19
+ To exit press STOP button
20
+ -------------------------------------------
21
+ """
22
+ from turtle import *
23
+
24
+ def switchupdown(x=0, y=0):
25
+ if pen()["pendown"]:
26
+ end_fill()
27
+ up()
28
+ else:
29
+ down()
30
+ begin_fill()
31
+
32
+ def changecolor(x=0, y=0):
33
+ global colors
34
+ colors = colors[1:]+colors[:1]
35
+ color(colors[0])
36
+
37
+ def main():
38
+ global colors
39
+ shape("circle")
40
+ resizemode("user")
41
+ shapesize(.5)
42
+ width(3)
43
+ colors=["red", "green", "blue", "yellow"]
44
+ color(colors[0])
45
+ switchupdown()
46
+ onscreenclick(goto,1)
47
+ onscreenclick(changecolor,2)
48
+ onscreenclick(switchupdown,3)
49
+ return "EVENTLOOP"
50
+
51
+ if __name__ == "__main__":
52
+ msg = main()
53
+ print(msg)
54
+ mainloop()
my_container_sandbox/workspace/anaconda3/lib/python3.8/turtledemo/peace.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """ turtle-example-suite:
3
+
4
+ tdemo_peace.py
5
+
6
+ A simple drawing suitable as a beginner's
7
+ programming example. Aside from the
8
+ peacecolors assignment and the for loop,
9
+ it only uses turtle commands.
10
+ """
11
+
12
+ from turtle import *
13
+
14
+ def main():
15
+ peacecolors = ("red3", "orange", "yellow",
16
+ "seagreen4", "orchid4",
17
+ "royalblue1", "dodgerblue4")
18
+
19
+ reset()
20
+ Screen()
21
+ up()
22
+ goto(-320,-195)
23
+ width(70)
24
+
25
+ for pcolor in peacecolors:
26
+ color(pcolor)
27
+ down()
28
+ forward(640)
29
+ up()
30
+ backward(640)
31
+ left(90)
32
+ forward(66)
33
+ right(90)
34
+
35
+ width(25)
36
+ color("white")
37
+ goto(0,-170)
38
+ down()
39
+
40
+ circle(170)
41
+ left(90)
42
+ forward(340)
43
+ up()
44
+ left(180)
45
+ forward(170)
46
+ right(45)
47
+ down()
48
+ forward(170)
49
+ up()
50
+ backward(170)
51
+ left(90)
52
+ down()
53
+ forward(170)
54
+ up()
55
+
56
+ goto(0,300) # vanish if hideturtle() is not available ;-)
57
+ return "Done!"
58
+
59
+ if __name__ == "__main__":
60
+ main()
61
+ mainloop()