MNghia commited on
Commit
6be3106
·
verified ·
1 Parent(s): a919927

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. lib/cmake/expat-2.7.1/expat-config-version.cmake +65 -0
  2. lib/cmake/expat-2.7.1/expat-config.cmake +99 -0
  3. lib/cmake/expat-2.7.1/expat-noconfig.cmake +19 -0
  4. lib/cmake/expat-2.7.1/expat.cmake +107 -0
  5. lib/cmake/libdeflate/libdeflate-config-version.cmake +43 -0
  6. lib/cmake/libdeflate/libdeflate-config.cmake +27 -0
  7. lib/cmake/libdeflate/libdeflate-targets-release.cmake +19 -0
  8. lib/itcl4.2.4/itcl.tcl +151 -0
  9. lib/itcl4.2.4/itclConfig.sh +67 -0
  10. lib/itcl4.2.4/itclHullCmds.tcl +562 -0
  11. lib/itcl4.2.4/itclWidget.tcl +447 -0
  12. lib/itcl4.2.4/libitclstub4.2.4.a +0 -0
  13. lib/itcl4.2.4/pkgIndex.tcl +14 -0
  14. lib/python3.10/py_compile.py +212 -0
  15. lib/python3.10/pyclbr.py +314 -0
  16. lib/python3.10/pydoc.py +0 -0
  17. lib/python3.10/queue.py +326 -0
  18. lib/python3.10/quopri.py +242 -0
  19. lib/python3.10/random.py +930 -0
  20. lib/python3.10/re.py +383 -0
  21. lib/python3.10/reprlib.py +161 -0
  22. lib/python3.10/rlcompleter.py +219 -0
  23. lib/python3.10/runpy.py +321 -0
  24. lib/python3.10/sched.py +167 -0
  25. lib/python3.10/secrets.py +72 -0
  26. lib/python3.10/selectors.py +619 -0
  27. lib/python3.10/shelve.py +243 -0
  28. lib/python3.10/shlex.py +350 -0
  29. lib/python3.10/shutil.py +1517 -0
  30. lib/python3.10/signal.py +92 -0
  31. lib/python3.10/uu.py +213 -0
  32. lib/python3.10/uuid.py +733 -0
  33. lib/python3.10/warnings.py +549 -0
  34. lib/python3.10/wave.py +513 -0
  35. lib/python3.10/weakref.py +675 -0
  36. lib/sqlite3.44.2/pkgIndex.tcl +12 -0
  37. lib/tcl8.6/auto.tcl +648 -0
  38. lib/tcl8.6/clock.tcl +0 -0
  39. lib/tcl8.6/history.tcl +335 -0
  40. lib/tcl8.6/init.tcl +827 -0
  41. lib/tcl8.6/package.tcl +751 -0
  42. lib/tcl8.6/parray.tcl +28 -0
  43. lib/tcl8.6/safe.tcl +1289 -0
  44. lib/tcl8.6/tclAppInit.c +176 -0
  45. lib/tcl8.6/tclIndex +79 -0
  46. lib/tcl8.6/tm.tcl +380 -0
  47. lib/tcl8.6/word.tcl +154 -0
  48. lib/tdbc1.1.7/libtdbc1.1.7.so +0 -0
  49. lib/tdbc1.1.7/libtdbcstub1.1.7.a +0 -0
  50. lib/tdbc1.1.7/pkgIndex.tcl +26 -0
lib/cmake/expat-2.7.1/expat-config-version.cmake ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This is a basic version file for the Config-mode of find_package().
2
+ # It is used by write_basic_package_version_file() as input file for configure_file()
3
+ # to create a version-file which can be installed along a config.cmake file.
4
+ #
5
+ # The created file sets PACKAGE_VERSION_EXACT if the current version string and
6
+ # the requested version string are exactly the same and it sets
7
+ # PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version,
8
+ # but only if the requested major version is the same as the current one.
9
+ # The variable CVF_VERSION must be set before calling configure_file().
10
+
11
+
12
+ set(PACKAGE_VERSION "2.7.1")
13
+
14
+ if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
15
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
16
+ else()
17
+
18
+ if("2.7.1" MATCHES "^([0-9]+)\\.")
19
+ set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
20
+ if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
21
+ string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
22
+ endif()
23
+ else()
24
+ set(CVF_VERSION_MAJOR "2.7.1")
25
+ endif()
26
+
27
+ if(PACKAGE_FIND_VERSION_RANGE)
28
+ # both endpoints of the range must have the expected major version
29
+ math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1")
30
+ if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR
31
+ OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR)
32
+ OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT)))
33
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
34
+ elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR
35
+ AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX)
36
+ OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX)))
37
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
38
+ else()
39
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
40
+ endif()
41
+ else()
42
+ if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR)
43
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
44
+ else()
45
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
46
+ endif()
47
+
48
+ if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
49
+ set(PACKAGE_VERSION_EXACT TRUE)
50
+ endif()
51
+ endif()
52
+ endif()
53
+
54
+
55
+ # if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
56
+ if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
57
+ return()
58
+ endif()
59
+
60
+ # check that the installed version has the same 32/64bit-ness as the one which is currently searching:
61
+ if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8")
62
+ math(EXPR installedBits "8 * 8")
63
+ set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
64
+ set(PACKAGE_VERSION_UNSUITABLE TRUE)
65
+ endif()
lib/cmake/expat-2.7.1/expat-config.cmake ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # __ __ _
2
+ # ___\ \/ /_ __ __ _| |_
3
+ # / _ \\ /| '_ \ / _` | __|
4
+ # | __// \| |_) | (_| | |_
5
+ # \___/_/\_\ .__/ \__,_|\__|
6
+ # |_| XML parser
7
+ #
8
+ # Copyright (c) 2019 Expat development team
9
+ # Licensed under the MIT license:
10
+ #
11
+ # Permission is hereby granted, free of charge, to any person obtaining
12
+ # a copy of this software and associated documentation files (the
13
+ # "Software"), to deal in the Software without restriction, including
14
+ # without limitation the rights to use, copy, modify, merge, publish,
15
+ # distribute, sublicense, and/or sell copies of the Software, and to permit
16
+ # persons to whom the Software is furnished to do so, subject to the
17
+ # following conditions:
18
+ #
19
+ # The above copyright notice and this permission notice shall be included
20
+ # in all copies or substantial portions of the Software.
21
+ #
22
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
25
+ # NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
26
+ # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
27
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
28
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
29
+ #
30
+ if(NOT _expat_config_included)
31
+ # Protect against multiple inclusion
32
+ set(_expat_config_included TRUE)
33
+
34
+
35
+ include("${CMAKE_CURRENT_LIST_DIR}/expat.cmake")
36
+
37
+
38
+ ####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
39
+ ####### Any changes to this file will be overwritten by the next CMake run ####
40
+ ####### The input file was expat-config.cmake.in ########
41
+
42
+ get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
43
+
44
+ macro(set_and_check _var _file)
45
+ set(${_var} "${_file}")
46
+ if(NOT EXISTS "${_file}")
47
+ message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
48
+ endif()
49
+ endmacro()
50
+
51
+ macro(check_required_components _NAME)
52
+ foreach(comp ${${_NAME}_FIND_COMPONENTS})
53
+ if(NOT ${_NAME}_${comp}_FOUND)
54
+ if(${_NAME}_FIND_REQUIRED_${comp})
55
+ set(${_NAME}_FOUND FALSE)
56
+ endif()
57
+ endif()
58
+ endforeach()
59
+ endmacro()
60
+
61
+ ####################################################################################
62
+
63
+ #
64
+ # Supported components
65
+ #
66
+ macro(expat_register_component _NAME _AVAILABE)
67
+ set(expat_${_NAME}_FOUND ${_AVAILABE})
68
+ endmacro()
69
+
70
+ expat_register_component(attr_info OFF)
71
+ expat_register_component(dtd ON)
72
+ expat_register_component(large_size OFF)
73
+ expat_register_component(min_size OFF)
74
+ expat_register_component(ns ON)
75
+
76
+ if(1024)
77
+ expat_register_component(context_bytes ON)
78
+ else()
79
+ expat_register_component(context_bytes OFF)
80
+ endif()
81
+
82
+ if("char" STREQUAL "char")
83
+ expat_register_component(char ON)
84
+ expat_register_component(ushort OFF)
85
+ expat_register_component(wchar_t OFF)
86
+ elseif("char" STREQUAL "ushort")
87
+ expat_register_component(char OFF)
88
+ expat_register_component(ushort ON)
89
+ expat_register_component(wchar_t OFF)
90
+ elseif("char" STREQUAL "wchar_t")
91
+ expat_register_component(char OFF)
92
+ expat_register_component(ushort OFF)
93
+ expat_register_component(wchar_t ON)
94
+ endif()
95
+
96
+ check_required_components(expat)
97
+
98
+
99
+ endif(NOT _expat_config_included)
lib/cmake/expat-2.7.1/expat-noconfig.cmake ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #----------------------------------------------------------------
2
+ # Generated CMake target import file for configuration "NoConfig".
3
+ #----------------------------------------------------------------
4
+
5
+ # Commands may need to know the format version.
6
+ set(CMAKE_IMPORT_FILE_VERSION 1)
7
+
8
+ # Import target "expat::expat" for configuration "NoConfig"
9
+ set_property(TARGET expat::expat APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
10
+ set_target_properties(expat::expat PROPERTIES
11
+ IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libexpat.so.1.10.2"
12
+ IMPORTED_SONAME_NOCONFIG "libexpat.so.1"
13
+ )
14
+
15
+ list(APPEND _cmake_import_check_targets expat::expat )
16
+ list(APPEND _cmake_import_check_files_for_expat::expat "${_IMPORT_PREFIX}/lib/libexpat.so.1.10.2" )
17
+
18
+ # Commands beyond this point should not need to know the version.
19
+ set(CMAKE_IMPORT_FILE_VERSION)
lib/cmake/expat-2.7.1/expat.cmake ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by CMake
2
+
3
+ if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8)
4
+ message(FATAL_ERROR "CMake >= 2.8.12 required")
5
+ endif()
6
+ if(CMAKE_VERSION VERSION_LESS "2.8.12")
7
+ message(FATAL_ERROR "CMake >= 2.8.12 required")
8
+ endif()
9
+ cmake_policy(PUSH)
10
+ cmake_policy(VERSION 2.8.12...3.29)
11
+ #----------------------------------------------------------------
12
+ # Generated CMake target import file.
13
+ #----------------------------------------------------------------
14
+
15
+ # Commands may need to know the format version.
16
+ set(CMAKE_IMPORT_FILE_VERSION 1)
17
+
18
+ # Protect against multiple inclusion, which would fail when already imported targets are added once more.
19
+ set(_cmake_targets_defined "")
20
+ set(_cmake_targets_not_defined "")
21
+ set(_cmake_expected_targets "")
22
+ foreach(_cmake_expected_target IN ITEMS expat::expat)
23
+ list(APPEND _cmake_expected_targets "${_cmake_expected_target}")
24
+ if(TARGET "${_cmake_expected_target}")
25
+ list(APPEND _cmake_targets_defined "${_cmake_expected_target}")
26
+ else()
27
+ list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}")
28
+ endif()
29
+ endforeach()
30
+ unset(_cmake_expected_target)
31
+ if(_cmake_targets_defined STREQUAL _cmake_expected_targets)
32
+ unset(_cmake_targets_defined)
33
+ unset(_cmake_targets_not_defined)
34
+ unset(_cmake_expected_targets)
35
+ unset(CMAKE_IMPORT_FILE_VERSION)
36
+ cmake_policy(POP)
37
+ return()
38
+ endif()
39
+ if(NOT _cmake_targets_defined STREQUAL "")
40
+ string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}")
41
+ string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}")
42
+ message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n")
43
+ endif()
44
+ unset(_cmake_targets_defined)
45
+ unset(_cmake_targets_not_defined)
46
+ unset(_cmake_expected_targets)
47
+
48
+
49
+ # Compute the installation prefix relative to this file.
50
+ get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
51
+ get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
52
+ get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
53
+ get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
54
+ if(_IMPORT_PREFIX STREQUAL "/")
55
+ set(_IMPORT_PREFIX "")
56
+ endif()
57
+
58
+ # Create imported target expat::expat
59
+ add_library(expat::expat SHARED IMPORTED)
60
+
61
+ set_target_properties(expat::expat PROPERTIES
62
+ INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
63
+ INTERFACE_LINK_LIBRARIES "m"
64
+ )
65
+
66
+ # Load information for each installed configuration.
67
+ file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/expat-*.cmake")
68
+ foreach(_cmake_config_file IN LISTS _cmake_config_files)
69
+ include("${_cmake_config_file}")
70
+ endforeach()
71
+ unset(_cmake_config_file)
72
+ unset(_cmake_config_files)
73
+
74
+ # Cleanup temporary variables.
75
+ set(_IMPORT_PREFIX)
76
+
77
+ # Loop over all imported files and verify that they actually exist
78
+ foreach(_cmake_target IN LISTS _cmake_import_check_targets)
79
+ if(CMAKE_VERSION VERSION_LESS "3.28"
80
+ OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target}
81
+ OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}")
82
+ foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}")
83
+ if(NOT EXISTS "${_cmake_file}")
84
+ message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file
85
+ \"${_cmake_file}\"
86
+ but this file does not exist. Possible reasons include:
87
+ * The file was deleted, renamed, or moved to another location.
88
+ * An install or uninstall procedure did not complete successfully.
89
+ * The installation package was faulty and contained
90
+ \"${CMAKE_CURRENT_LIST_FILE}\"
91
+ but not all the files it references.
92
+ ")
93
+ endif()
94
+ endforeach()
95
+ endif()
96
+ unset(_cmake_file)
97
+ unset("_cmake_import_check_files_for_${_cmake_target}")
98
+ endforeach()
99
+ unset(_cmake_target)
100
+ unset(_cmake_import_check_targets)
101
+
102
+ # This file does not depend on other imported targets which have
103
+ # been exported from the same project but in a separate export set.
104
+
105
+ # Commands beyond this point should not need to know the version.
106
+ set(CMAKE_IMPORT_FILE_VERSION)
107
+ cmake_policy(POP)
lib/cmake/libdeflate/libdeflate-config-version.cmake ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This is a basic version file for the Config-mode of find_package().
2
+ # It is used by write_basic_package_version_file() as input file for configure_file()
3
+ # to create a version-file which can be installed along a config.cmake file.
4
+ #
5
+ # The created file sets PACKAGE_VERSION_EXACT if the current version string and
6
+ # the requested version string are exactly the same and it sets
7
+ # PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version.
8
+ # The variable CVF_VERSION must be set before calling configure_file().
9
+
10
+ set(PACKAGE_VERSION "1.22")
11
+
12
+ if (PACKAGE_FIND_VERSION_RANGE)
13
+ # Package version must be in the requested version range
14
+ if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN)
15
+ OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX)
16
+ OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX)))
17
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
18
+ else()
19
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
20
+ endif()
21
+ else()
22
+ if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
23
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
24
+ else()
25
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
26
+ if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
27
+ set(PACKAGE_VERSION_EXACT TRUE)
28
+ endif()
29
+ endif()
30
+ endif()
31
+
32
+
33
+ # if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
34
+ if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
35
+ return()
36
+ endif()
37
+
38
+ # check that the installed version has the same 32/64bit-ness as the one which is currently searching:
39
+ if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8")
40
+ math(EXPR installedBits "8 * 8")
41
+ set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
42
+ set(PACKAGE_VERSION_UNSUITABLE TRUE)
43
+ endif()
lib/cmake/libdeflate/libdeflate-config.cmake ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ ####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
3
+ ####### Any changes to this file will be overwritten by the next CMake run ####
4
+ ####### The input file was libdeflate-config.cmake.in ########
5
+
6
+ get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
7
+
8
+ macro(set_and_check _var _file)
9
+ set(${_var} "${_file}")
10
+ if(NOT EXISTS "${_file}")
11
+ message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
12
+ endif()
13
+ endmacro()
14
+
15
+ macro(check_required_components _NAME)
16
+ foreach(comp ${${_NAME}_FIND_COMPONENTS})
17
+ if(NOT ${_NAME}_${comp}_FOUND)
18
+ if(${_NAME}_FIND_REQUIRED_${comp})
19
+ set(${_NAME}_FOUND FALSE)
20
+ endif()
21
+ endif()
22
+ endforeach()
23
+ endmacro()
24
+
25
+ ####################################################################################
26
+
27
+ include("${CMAKE_CURRENT_LIST_DIR}/libdeflate-targets.cmake")
lib/cmake/libdeflate/libdeflate-targets-release.cmake ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #----------------------------------------------------------------
2
+ # Generated CMake target import file for configuration "Release".
3
+ #----------------------------------------------------------------
4
+
5
+ # Commands may need to know the format version.
6
+ set(CMAKE_IMPORT_FILE_VERSION 1)
7
+
8
+ # Import target "libdeflate::libdeflate_shared" for configuration "Release"
9
+ set_property(TARGET libdeflate::libdeflate_shared APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
10
+ set_target_properties(libdeflate::libdeflate_shared PROPERTIES
11
+ IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libdeflate.so.0"
12
+ IMPORTED_SONAME_RELEASE "libdeflate.so.0"
13
+ )
14
+
15
+ list(APPEND _cmake_import_check_targets libdeflate::libdeflate_shared )
16
+ list(APPEND _cmake_import_check_files_for_libdeflate::libdeflate_shared "${_IMPORT_PREFIX}/lib/libdeflate.so.0" )
17
+
18
+ # Commands beyond this point should not need to know the version.
19
+ set(CMAKE_IMPORT_FILE_VERSION)
lib/itcl4.2.4/itcl.tcl ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # itcl.tcl
3
+ # ----------------------------------------------------------------------
4
+ # Invoked automatically upon startup to customize the interpreter
5
+ # for [incr Tcl].
6
+ # ----------------------------------------------------------------------
7
+ # AUTHOR: Michael J. McLennan
8
+ # Bell Labs Innovations for Lucent Technologies
9
+ # mmclennan@lucent.com
10
+ # http://www.tcltk.com/itcl
11
+ # ----------------------------------------------------------------------
12
+ # Copyright (c) 1993-1998 Lucent Technologies, Inc.
13
+ # ======================================================================
14
+ # See the file "license.terms" for information on usage and
15
+ # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
+
17
+ proc ::itcl::delete_helper { name args } {
18
+ ::itcl::delete object $name
19
+ }
20
+
21
+ # ----------------------------------------------------------------------
22
+ # USAGE: local <className> <objName> ?<arg> <arg>...?
23
+ #
24
+ # Creates a new object called <objName> in class <className>, passing
25
+ # the remaining <arg>'s to the constructor. Unlike the usual
26
+ # [incr Tcl] objects, however, an object created by this procedure
27
+ # will be automatically deleted when the local call frame is destroyed.
28
+ # This command is useful for creating objects that should only remain
29
+ # alive until a procedure exits.
30
+ # ----------------------------------------------------------------------
31
+ proc ::itcl::local {class name args} {
32
+ set ptr [uplevel [list $class $name] $args]
33
+ uplevel [list set itcl-local-$ptr $ptr]
34
+ set cmd [uplevel namespace which -command $ptr]
35
+ uplevel [list trace add variable itcl-local-$ptr unset \
36
+ "::itcl::delete_helper $cmd"]
37
+ return $ptr
38
+ }
39
+
40
+ # ----------------------------------------------------------------------
41
+ # auto_mkindex
42
+ # ----------------------------------------------------------------------
43
+ # Define Itcl commands that will be recognized by the auto_mkindex
44
+ # parser in Tcl...
45
+ #
46
+
47
+ #
48
+ # USAGE: itcl::class name body
49
+ # Adds an entry for the given class declaration.
50
+ #
51
+ foreach __cmd {itcl::class class itcl::type type ictl::widget widget itcl::widgetadaptor widgetadaptor itcl::extendedclass extendedclass} {
52
+ auto_mkindex_parser::command $__cmd {name body} {
53
+ variable index
54
+ variable scriptFile
55
+ append index "set [list auto_index([fullname $name])]"
56
+ append index " \[list source \[file join \$dir [list $scriptFile]\]\]\n"
57
+
58
+ variable parser
59
+ variable contextStack
60
+ set contextStack [linsert $contextStack 0 $name]
61
+ $parser eval $body
62
+ set contextStack [lrange $contextStack 1 end]
63
+ }
64
+ }
65
+
66
+ #
67
+ # USAGE: itcl::body name arglist body
68
+ # Adds an entry for the given method/proc body.
69
+ #
70
+ foreach __cmd {itcl::body body} {
71
+ auto_mkindex_parser::command $__cmd {name arglist body} {
72
+ variable index
73
+ variable scriptFile
74
+ append index "set [list auto_index([fullname $name])]"
75
+ append index " \[list source \[file join \$dir [list $scriptFile]\]\]\n"
76
+ }
77
+ }
78
+
79
+ #
80
+ # USAGE: itcl::configbody name arglist body
81
+ # Adds an entry for the given method/proc body.
82
+ #
83
+ foreach __cmd {itcl::configbody configbody} {
84
+ auto_mkindex_parser::command $__cmd {name body} {
85
+ variable index
86
+ variable scriptFile
87
+ append index "set [list auto_index([fullname $name])]"
88
+ append index " \[list source \[file join \$dir [list $scriptFile]\]\]\n"
89
+ }
90
+ }
91
+
92
+ #
93
+ # USAGE: ensemble name ?body?
94
+ # Adds an entry to the auto index list for the given ensemble name.
95
+ #
96
+ foreach __cmd {itcl::ensemble ensemble} {
97
+ auto_mkindex_parser::command $__cmd {name {body ""}} {
98
+ variable index
99
+ variable scriptFile
100
+ append index "set [list auto_index([fullname $name])]"
101
+ append index " \[list source \[file join \$dir [list $scriptFile]\]\]\n"
102
+ }
103
+ }
104
+
105
+ #
106
+ # USAGE: public arg ?arg arg...?
107
+ # protected arg ?arg arg...?
108
+ # private arg ?arg arg...?
109
+ #
110
+ # Evaluates the arguments as commands, so we can recognize proc
111
+ # declarations within classes.
112
+ #
113
+ foreach __cmd {public protected private} {
114
+ auto_mkindex_parser::command $__cmd {args} {
115
+ variable parser
116
+ $parser eval $args
117
+ }
118
+ }
119
+
120
+ # SF bug #246 unset variable __cmd to avoid problems in user programs!!
121
+ unset __cmd
122
+
123
+ # ----------------------------------------------------------------------
124
+ # auto_import
125
+ # ----------------------------------------------------------------------
126
+ # This procedure overrides the usual "auto_import" function in the
127
+ # Tcl library. It is invoked during "namespace import" to make see
128
+ # if the imported commands reside in an autoloaded library. If so,
129
+ # stubs are created to represent the commands. Executing a stub
130
+ # later on causes the real implementation to be autoloaded.
131
+ #
132
+ # Arguments -
133
+ # pattern The pattern of commands being imported (like "foo::*")
134
+ # a canonical namespace as returned by [namespace current]
135
+
136
+ proc auto_import {pattern} {
137
+ global auto_index
138
+
139
+ set ns [uplevel namespace current]
140
+ set patternList [auto_qualify $pattern $ns]
141
+
142
+ auto_load_index
143
+
144
+ foreach pattern $patternList {
145
+ foreach name [array names auto_index $pattern] {
146
+ if {"" == [info commands $name]} {
147
+ ::itcl::import::stub create $name
148
+ }
149
+ }
150
+ }
151
+ }
lib/itcl4.2.4/itclConfig.sh ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # itclConfig.sh --
2
+ #
3
+ # This shell script (for sh) is generated automatically by Itcl's
4
+ # configure script. It will create shell variables for most of
5
+ # the configuration options discovered by the configure script.
6
+ # This script is intended to be included by the configure scripts
7
+ # for Itcl extensions so that they don't have to figure this all
8
+ # out for themselves. This file does not duplicate information
9
+ # already provided by tclConfig.sh, so you may need to use that
10
+ # file in addition to this one.
11
+ #
12
+ # The information in this file is specific to a single platform.
13
+
14
+ # Itcl's version number.
15
+ itcl_VERSION='4.2.4'
16
+ ITCL_VERSION='4.2.4'
17
+
18
+ # The name of the Itcl library (may be either a .a file or a shared library):
19
+ itcl_LIB_FILE=libitcl4.2.4.so
20
+ ITCL_LIB_FILE=libitcl4.2.4.so
21
+
22
+ # String to pass to linker to pick up the Itcl library from its
23
+ # build directory.
24
+ itcl_BUILD_LIB_SPEC='-L/croot/tk_1748849386456/work/tcl8.6.14/unix/pkgs/itcl4.2.4 -litcl4.2.4'
25
+ ITCL_BUILD_LIB_SPEC='-L/croot/tk_1748849386456/work/tcl8.6.14/unix/pkgs/itcl4.2.4 -litcl4.2.4'
26
+
27
+ # String to pass to linker to pick up the Itcl library from its
28
+ # installed directory.
29
+ itcl_LIB_SPEC='-L/home/aioz-nghiale/anaconda3/envs/testing_softzoo_pointe/lib/itcl4.2.4 -litcl4.2.4'
30
+ ITCL_LIB_SPEC='-L/home/aioz-nghiale/anaconda3/envs/testing_softzoo_pointe/lib/itcl4.2.4 -litcl4.2.4'
31
+
32
+ # The name of the Itcl stub library (a .a file):
33
+ itcl_STUB_LIB_FILE=libitclstub4.2.4.a
34
+ ITCL_STUB_LIB_FILE=libitclstub4.2.4.a
35
+
36
+ # String to pass to linker to pick up the Itcl stub library from its
37
+ # build directory.
38
+ itcl_BUILD_STUB_LIB_SPEC='-L/croot/tk_1748849386456/work/tcl8.6.14/unix/pkgs/itcl4.2.4 -litclstub4.2.4'
39
+ ITCL_BUILD_STUB_LIB_SPEC='-L/croot/tk_1748849386456/work/tcl8.6.14/unix/pkgs/itcl4.2.4 -litclstub4.2.4'
40
+
41
+ # String to pass to linker to pick up the Itcl stub library from its
42
+ # installed directory.
43
+ itcl_STUB_LIB_SPEC='-L/home/aioz-nghiale/anaconda3/envs/testing_softzoo_pointe/lib/itcl4.2.4 -litclstub4.2.4'
44
+ ITCL_STUB_LIB_SPEC='-L/home/aioz-nghiale/anaconda3/envs/testing_softzoo_pointe/lib/itcl4.2.4 -litclstub4.2.4'
45
+
46
+ # String to pass to linker to pick up the Itcl stub library from its
47
+ # build directory.
48
+ itcl_BUILD_STUB_LIB_PATH='/croot/tk_1748849386456/work/tcl8.6.14/unix/pkgs/itcl4.2.4/libitclstub4.2.4.a'
49
+ ITCL_BUILD_STUB_LIB_PATH='/croot/tk_1748849386456/work/tcl8.6.14/unix/pkgs/itcl4.2.4/libitclstub4.2.4.a'
50
+
51
+ # String to pass to linker to pick up the Itcl stub library from its
52
+ # installed directory.
53
+ itcl_STUB_LIB_PATH='/home/aioz-nghiale/anaconda3/envs/testing_softzoo_pointe/lib/itcl4.2.4/libitclstub4.2.4.a'
54
+ ITCL_STUB_LIB_PATH='/home/aioz-nghiale/anaconda3/envs/testing_softzoo_pointe/lib/itcl4.2.4/libitclstub4.2.4.a'
55
+
56
+ # Location of the top-level source directories from which [incr Tcl]
57
+ # was built. This is the directory that contains generic, unix, etc.
58
+ # If [incr Tcl] was compiled in a different place than the directory
59
+ # containing the source files, this points to the location of the sources,
60
+ # not the location where [incr Tcl] was compiled.
61
+ itcl_SRC_DIR='/croot/tk_1748849386456/work/tcl8.6.14/pkgs/itcl4.2.4'
62
+ ITCL_SRC_DIR='/croot/tk_1748849386456/work/tcl8.6.14/pkgs/itcl4.2.4'
63
+
64
+ # String to pass to the compiler so that an extension can
65
+ # find installed Itcl headers.
66
+ itcl_INCLUDE_SPEC=''
67
+ ITCL_INCLUDE_SPEC=''
lib/itcl4.2.4/itclHullCmds.tcl ADDED
@@ -0,0 +1,562 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # itclHullCmds.tcl
3
+ # ----------------------------------------------------------------------
4
+ # Invoked automatically upon startup to customize the interpreter
5
+ # for [incr Tcl] when one of setupcomponent or createhull is called.
6
+ # ----------------------------------------------------------------------
7
+ # AUTHOR: Arnulf P. Wiedemann
8
+ #
9
+ # ----------------------------------------------------------------------
10
+ # Copyright (c) 2008 Arnulf P. Wiedemann
11
+ # ======================================================================
12
+ # See the file "license.terms" for information on usage and
13
+ # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14
+
15
+ package require Tk 8.6 9
16
+
17
+ namespace eval ::itcl::internal::commands {
18
+
19
+ # ======================= widgetDeleted ===========================
20
+
21
+ proc widgetDeleted {oldName newName op} {
22
+ # The widget is beeing deleted, so we have to delete the object
23
+ # which had the widget as itcl_hull too!
24
+ # We have to get the real name from for example
25
+ # ::itcl::internal::widgets::hull1.lw
26
+ # we need only .lw here
27
+
28
+ #puts stderr "widgetDeleted!$oldName!$newName!$op!"
29
+ set cmdName [namespace tail $oldName]
30
+ set flds [split $cmdName {.}]
31
+ set cmdName .[join [lrange $flds 1 end] {.}]
32
+ #puts stderr "DELWIDGET![namespace current]!$cmdName![::info command $cmdName]!"
33
+ rename $cmdName {}
34
+ }
35
+
36
+ }
37
+
38
+ namespace eval ::itcl::builtin {
39
+
40
+ # ======================= createhull ===========================
41
+ # the hull widget is a tk widget which is the (mega) widget handled behind the itcl
42
+ # extendedclass/itcl widget.
43
+ # It is created be renaming the itcl class object to a temporary name <itcl object name>_
44
+ # creating the widget with the
45
+ # appropriate options and the installing that as the "hull" widget (the container)
46
+ # All the options in args and the options delegated to component itcl_hull are used
47
+ # Then a unique name (hull_widget_name) in the itcl namespace is created for widget:
48
+ # ::itcl::internal::widgets::hull<unique number><namespace tail path>
49
+ # and widget is renamed to that name
50
+ # Finally the <itcl object name>_ is renamed to the original <itcl object name> again
51
+ # Component itcl_hull is created if not existent
52
+ # itcl_hull is set to the hull_widget_name and the <itcl object name>
53
+ # is returned to the caller
54
+ # ==============================================================
55
+
56
+ proc createhull {widget_type path args} {
57
+ variable hullCount
58
+ upvar this this
59
+ upvar win win
60
+
61
+
62
+ #puts stderr "il-1![::info level -1]!$this!"
63
+ #puts stderr "createhull!$widget_type!$path!$args!$this![::info command $this]!"
64
+ #puts stderr "ns1![uplevel 1 namespace current]!"
65
+ #puts stderr "ns2![uplevel 2 namespace current]!"
66
+ #puts stderr "ns3![uplevel 3 namespace current]!"
67
+ #puts stderr "level-1![::info level -1]!"
68
+ #puts stderr "level-2![::info level -2]!"
69
+ # set my_this [namespace tail $this]
70
+ set my_this $this
71
+ set tmp $my_this
72
+ #puts stderr "II![::info command $this]![::info command $tmp]!"
73
+ #puts stderr "rename1!rename $my_this ${tmp}_!"
74
+ rename ::$my_this ${tmp}_
75
+ set options [list]
76
+ foreach {option_name value} $args {
77
+ switch -glob -- $option_name {
78
+ -class {
79
+ lappend options $option_name [namespace tail $value]
80
+ }
81
+ -* {
82
+ lappend options $option_name $value
83
+ }
84
+ default {
85
+ return -code error "bad option name\"$option_name\" options must start with a \"-\""
86
+ }
87
+ }
88
+ }
89
+ set my_win [namespace tail $path]
90
+ set cmd [list $widget_type $my_win]
91
+ #puts stderr "my_win!$my_win!cmd!$cmd!$path!"
92
+ if {[llength $options] > 0} {
93
+ lappend cmd {*}$options
94
+ }
95
+ set widget [uplevel 1 $cmd]
96
+ #puts stderr "widget!$widget!"
97
+ trace add command $widget delete ::itcl::internal::commands::widgetDeleted
98
+ set opts [uplevel 1 info delegated options]
99
+ foreach entry $opts {
100
+ foreach {optName compName} $entry break
101
+ if {$compName eq "itcl_hull"} {
102
+ set optInfos [uplevel 1 info delegated option $optName]
103
+ set realOptName [lindex $optInfos 4]
104
+ # strip off the "-" at the beginning
105
+ set myOptName [string range $realOptName 1 end]
106
+ set my_opt_val [option get $my_win $myOptName *]
107
+ if {$my_opt_val ne ""} {
108
+ $my_win configure -$myOptName $my_opt_val
109
+ }
110
+ }
111
+ }
112
+ set idx 1
113
+ while {1} {
114
+ set widgetName ::itcl::internal::widgets::hull${idx}$my_win
115
+ #puts stderr "widgetName!$widgetName!"
116
+ if {[string length [::info command $widgetName]] == 0} {
117
+ break
118
+ }
119
+ incr idx
120
+ }
121
+ #puts stderr "rename2!rename $widget $widgetName!"
122
+ set dorename 0
123
+ rename $widget $widgetName
124
+ #puts stderr "rename3!rename ${tmp}_ $tmp![::info command ${tmp}_]!my_this!$my_this!"
125
+ rename ${tmp}_ ::$tmp
126
+ set exists [uplevel 1 ::info exists itcl_hull]
127
+ if {!$exists} {
128
+ # that does not yet work, beacause of problems with resolving
129
+ ::itcl::addcomponent $my_this itcl_hull
130
+ }
131
+ upvar itcl_hull itcl_hull
132
+ ::itcl::setcomponent $my_this itcl_hull $widgetName
133
+ #puts stderr "IC![::info command $my_win]!"
134
+ set exists [uplevel 1 ::info exists itcl_interior]
135
+ if {!$exists} {
136
+ # that does not yet work, beacause of problems with resolving
137
+ ::itcl::addcomponent $this itcl_interior
138
+ }
139
+ upvar itcl_interior itcl_interior
140
+ set itcl_interior $my_win
141
+ #puts stderr "hull end!win!$win!itcl_hull!$itcl_hull!itcl_interior!$itcl_interior!"
142
+ return $my_win
143
+ }
144
+
145
+ # ======================= addToItclOptions ===========================
146
+
147
+ proc addToItclOptions {my_class my_win myOptions argsDict} {
148
+ upvar win win
149
+ upvar itcl_hull itcl_hull
150
+
151
+ set opt_lst [list configure]
152
+ foreach opt [lsort $myOptions] {
153
+ #puts stderr "IOPT!$opt!$my_class!$my_win![::itcl::is class $my_class]!"
154
+ set isClass [::itcl::is class $my_class]
155
+ set found 0
156
+ if {$isClass} {
157
+ if {[catch {
158
+ set resource [namespace eval $my_class info option $opt -resource]
159
+ set class [namespace eval $my_class info option $opt -class]
160
+ set default_val [uplevel 2 info option $opt -default]
161
+ set found 1
162
+ } msg]} {
163
+ # puts stderr "MSG!$opt!$my_class!$msg!"
164
+ }
165
+ } else {
166
+ set tmp_win [uplevel #0 $my_class .___xx]
167
+
168
+ set my_info [$tmp_win configure $opt]
169
+ set resource [lindex $my_info 1]
170
+ set class [lindex $my_info 2]
171
+ set default_val [lindex $my_info 3]
172
+ uplevel #0 destroy $tmp_win
173
+ set found 1
174
+ }
175
+ if {$found} {
176
+ if {[catch {
177
+ set val [uplevel #0 ::option get $win $resource $class]
178
+ } msg]} {
179
+ set val ""
180
+ }
181
+ if {[::dict exists $argsDict $opt]} {
182
+ # we have an explicitly set option
183
+ set val [::dict get $argsDict $opt]
184
+ } else {
185
+ if {[string length $val] == 0} {
186
+ set val $default_val
187
+ }
188
+ }
189
+ set ::itcl::internal::variables::${my_win}::itcl_options($opt) $val
190
+ set ::itcl::internal::variables::${my_win}::__itcl_option_infos($opt) [list $resource $class $default_val]
191
+ #puts stderr "OPT1!$opt!$val!"
192
+ # uplevel 1 [list set itcl_options($opt) [list $val]]
193
+ if {[catch {uplevel 1 $win configure $opt [list $val]} msg]} {
194
+ #puts stderr "addToItclOptions ERR!$msg!$my_class!$win!configure!$opt!$val!"
195
+ }
196
+ }
197
+ }
198
+ }
199
+
200
+ # ======================= setupcomponent ===========================
201
+
202
+ proc setupcomponent {comp using widget_type path args} {
203
+ upvar this this
204
+ upvar win win
205
+ upvar itcl_hull itcl_hull
206
+
207
+ #puts stderr "setupcomponent!$comp!$widget_type!$path!$args!$this!$win!$itcl_hull!"
208
+ #puts stderr "CONT![uplevel 1 info context]!"
209
+ #puts stderr "ns1![uplevel 1 namespace current]!"
210
+ #puts stderr "ns2![uplevel 2 namespace current]!"
211
+ #puts stderr "ns3![uplevel 3 namespace current]!"
212
+ set my_comp_object [lindex [uplevel 1 info context] 1]
213
+ if {[::info exists ::itcl::internal::component_objects($my_comp_object)]} {
214
+ set my_comp_object [set ::itcl::internal::component_objects($my_comp_object)]
215
+ } else {
216
+ set ::itcl::internal::component_objects($path) $my_comp_object
217
+ }
218
+ set options [list]
219
+ foreach {option_name value} $args {
220
+ switch -glob -- $option_name {
221
+ -* {
222
+ lappend options $option_name $value
223
+ }
224
+ default {
225
+ return -code error "bad option name\"$option_name\" options must start with a \"-\""
226
+ }
227
+ }
228
+ }
229
+ if {[llength $args]} {
230
+ set argsDict [dict create {*}$args]
231
+ } else {
232
+ set argsDict [dict create]
233
+ }
234
+ set cmd [list $widget_type $path]
235
+ if {[llength $options] > 0} {
236
+ lappend cmd {*}$options
237
+ }
238
+ #puts stderr "cmd0![::info command $widget_type]!$path![::info command $path]!"
239
+ #puts stderr "cmd1!$cmd!"
240
+ # set my_comp [uplevel 3 $cmd]
241
+ set my_comp [uplevel #0 $cmd]
242
+ #puts stderr 111![::info command $path]!
243
+ ::itcl::setcomponent $this $comp $my_comp
244
+ set opts [uplevel 1 info delegated options]
245
+ foreach entry $opts {
246
+ foreach {optName compName} $entry break
247
+ if {$compName eq $my_comp} {
248
+ set optInfos [uplevel 1 info delegated option $optName]
249
+ set realOptName [lindex $optInfos 4]
250
+ # strip off the "-" at the beginning
251
+ set myOptName [string range $realOptName 1 end]
252
+ set my_opt_val [option get $my_win $myOptName *]
253
+ if {$my_opt_val ne ""} {
254
+ $my_comp configure -$myOptName $my_opt_val
255
+ }
256
+ }
257
+ }
258
+ set my_class $widget_type
259
+ set my_parent_class [uplevel 1 namespace current]
260
+ if {[catch {
261
+ set myOptions [namespace eval $my_class {info classoptions}]
262
+ } msg]} {
263
+ set myOptions [list]
264
+ }
265
+ foreach entry [$path configure] {
266
+ foreach {opt dummy1 dummy2 dummy3} $entry break
267
+ lappend myOptions $opt
268
+ }
269
+ #puts stderr "OPTS!$myOptions!"
270
+ addToItclOptions $widget_type $my_comp_object $myOptions $argsDict
271
+ #puts stderr END!$path![::info command $path]!
272
+ }
273
+
274
+ proc itcl_initoptions {args} {
275
+ puts stderr "ITCL_INITOPT!$args!"
276
+ }
277
+
278
+ # ======================= initoptions ===========================
279
+
280
+ proc initoptions {args} {
281
+ upvar win win
282
+ upvar itcl_hull itcl_hull
283
+ upvar itcl_option_components itcl_option_components
284
+
285
+ #puts stderr "INITOPT!!$win!"
286
+ if {[llength $args]} {
287
+ set argsDict [dict create {*}$args]
288
+ } else {
289
+ set argsDict [dict create]
290
+ }
291
+ set my_class [uplevel 1 namespace current]
292
+ set myOptions [namespace eval $my_class {info classoptions}]
293
+ if {[dict exists $::itcl::internal::dicts::classComponents $my_class]} {
294
+ set class_info_dict [dict get $::itcl::internal::dicts::classComponents $my_class]
295
+ # set myOptions [lsort -unique [namespace eval $my_class {info options}]]
296
+ foreach comp [uplevel 1 info components] {
297
+ if {[dict exists $class_info_dict $comp -keptoptions]} {
298
+ foreach my_opt [dict get $class_info_dict $comp -keptoptions] {
299
+ if {[lsearch $myOptions $my_opt] < 0} {
300
+ #puts stderr "KEOPT!$my_opt!"
301
+ lappend myOptions $my_opt
302
+ }
303
+ }
304
+ }
305
+ }
306
+ } else {
307
+ set class_info_dict [list]
308
+ }
309
+ #puts stderr "OPTS!$win!$my_class![join [lsort $myOptions]] \n]!"
310
+ set opt_lst [list configure]
311
+ set my_win $win
312
+ foreach opt [lsort $myOptions] {
313
+ set found 0
314
+ if {[catch {
315
+ set resource [uplevel 1 info option $opt -resource]
316
+ set class [uplevel 1 info option $opt -class]
317
+ set default_val [uplevel 1 info option $opt -default]
318
+ set found 1
319
+ } msg]} {
320
+ # puts stderr "MSG!$opt!$msg!"
321
+ }
322
+ #puts stderr "OPT!$opt!$found!"
323
+ if {$found} {
324
+ if {[catch {
325
+ set val [uplevel #0 ::option get $my_win $resource $class]
326
+ } msg]} {
327
+ set val ""
328
+ }
329
+ if {[::dict exists $argsDict $opt]} {
330
+ # we have an explicitly set option
331
+ set val [::dict get $argsDict $opt]
332
+ } else {
333
+ if {[string length $val] == 0} {
334
+ set val $default_val
335
+ }
336
+ }
337
+ set ::itcl::internal::variables::${win}::itcl_options($opt) $val
338
+ set ::itcl::internal::variables::${win}::__itcl_option_infos($opt) [list $resource $class $default_val]
339
+ #puts stderr "OPT1!$opt!$val!"
340
+ # uplevel 1 [list set itcl_options($opt) [list $val]]
341
+ if {[catch {uplevel 1 $my_win configure $opt [list $val]} msg]} {
342
+ puts stderr "initoptions ERR!$msg!$my_class!$my_win!configure!$opt!$val!"
343
+ }
344
+ }
345
+ foreach comp [dict keys $class_info_dict] {
346
+ #puts stderr "OPT1!$opt!$comp![dict get $class_info_dict $comp]!"
347
+ if {[dict exists $class_info_dict $comp -keptoptions]} {
348
+ if {[lsearch [dict get $class_info_dict $comp -keptoptions] $opt] >= 0} {
349
+ if {$found == 0} {
350
+ # we use the option value of the first component for setting
351
+ # the option, as the components are traversed in the dict
352
+ # depending on the ordering of the component creation!!
353
+ set my_info [uplevel 1 \[set $comp\] configure $opt]
354
+ set resource [lindex $my_info 1]
355
+ set class [lindex $my_info 2]
356
+ set default_val [lindex $my_info 3]
357
+ set found 2
358
+ set val [uplevel #0 ::option get $my_win $resource $class]
359
+ if {[::dict exists $argsDict $opt]} {
360
+ # we have an explicitly set option
361
+ set val [::dict get $argsDict $opt]
362
+ } else {
363
+ if {[string length $val] == 0} {
364
+ set val $default_val
365
+ }
366
+ }
367
+ #puts stderr "OPT2!$opt!$val!"
368
+ set ::itcl::internal::variables::${win}::itcl_options($opt) $val
369
+ set ::itcl::internal::variables::${win}::__itcl_option_infos($opt) [list $resource $class $default_val]
370
+ # uplevel 1 [list set itcl_options($opt) [list $val]]
371
+ }
372
+ if {[catch {uplevel 1 \[set $comp\] configure $opt [list $val]} msg]} {
373
+ puts stderr "initoptions ERR2!$msg!$my_class!$comp!configure!$opt!$val!"
374
+ }
375
+ if {![uplevel 1 info exists itcl_option_components($opt)]} {
376
+ set itcl_option_components($opt) [list]
377
+ }
378
+ if {[lsearch [set itcl_option_components($opt)] $comp] < 0} {
379
+ if {![catch {
380
+ set optval [uplevel 1 [list set itcl_options($opt)]]
381
+ } msg3]} {
382
+ uplevel 1 \[set $comp\] configure $opt $optval
383
+ }
384
+ lappend itcl_option_components($opt) $comp
385
+ }
386
+ }
387
+ }
388
+ }
389
+ }
390
+ # uplevel 1 $opt_lst
391
+ }
392
+
393
+ # ======================= setoptions ===========================
394
+
395
+ proc setoptions {args} {
396
+
397
+ #puts stderr "setOPT!!$args!"
398
+ if {[llength $args]} {
399
+ set argsDict [dict create {*}$args]
400
+ } else {
401
+ set argsDict [dict create]
402
+ }
403
+ set my_class [uplevel 1 namespace current]
404
+ set myOptions [namespace eval $my_class {info options}]
405
+ #puts stderr "OPTS!$win!$my_class![join [lsort $myOptions]] \n]!"
406
+ set opt_lst [list configure]
407
+ foreach opt [lsort $myOptions] {
408
+ set found 0
409
+ if {[catch {
410
+ set resource [uplevel 1 info option $opt -resource]
411
+ set class [uplevel 1 info option $opt -class]
412
+ set default_val [uplevel 1 info option $opt -default]
413
+ set found 1
414
+ } msg]} {
415
+ # puts stderr "MSG!$opt!$msg!"
416
+ }
417
+ #puts stderr "OPT!$opt!$found!"
418
+ if {$found} {
419
+ set val ""
420
+ if {[::dict exists $argsDict $opt]} {
421
+ # we have an explicitly set option
422
+ set val [::dict get $argsDict $opt]
423
+ } else {
424
+ if {[string length $val] == 0} {
425
+ set val $default_val
426
+ }
427
+ }
428
+ set myObj [uplevel 1 set this]
429
+ #puts stderr "myObj!$myObj!"
430
+ set ::itcl::internal::variables::${myObj}::itcl_options($opt) $val
431
+ set ::itcl::internal::variables::${myObj}::__itcl_option_infos($opt) [list $resource $class $default_val]
432
+ #puts stderr "OPT1!$opt!$val!"
433
+ uplevel 1 [list set itcl_options($opt) [list $val]]
434
+ # if {[catch {uplevel 1 $myObj configure $opt [list $val]} msg]} {
435
+ #puts stderr "initoptions ERR!$msg!$my_class!$my_win!configure!$opt!$val!"
436
+ # }
437
+ }
438
+ }
439
+ # uplevel 1 $opt_lst
440
+ }
441
+
442
+ # ========================= keepcomponentoption ======================
443
+ # Invoked by Tcl during evaluating constructor whenever
444
+ # the "keepcomponentoption" command is invoked to list the options
445
+ # to be kept when an ::itcl::extendedclass component has been setup
446
+ # for an object.
447
+ #
448
+ # It checks, for all arguments, if the opt is an option of that class
449
+ # and of that component. If that is the case it adds the component name
450
+ # to the list of components for that option.
451
+ # The variable is the object variable: itcl_option_components($opt)
452
+ #
453
+ # Handles the following syntax:
454
+ #
455
+ # keepcomponentoption <componentName> <optionName> ?<optionName> ...?
456
+ #
457
+ # ======================================================================
458
+
459
+
460
+ proc keepcomponentoption {args} {
461
+ upvar win win
462
+ upvar itcl_hull itcl_hull
463
+
464
+ set usage "wrong # args, should be: keepcomponentoption componentName optionName ?optionName ...?"
465
+
466
+ #puts stderr "KEEP!$args![uplevel 1 namespace current]!"
467
+ if {[llength $args] < 2} {
468
+ puts stderr $usage
469
+ return -code error
470
+ }
471
+ set my_hull [uplevel 1 set itcl_hull]
472
+ set my_class [uplevel 1 namespace current]
473
+ set comp [lindex $args 0]
474
+ set args [lrange $args 1 end]
475
+ set class_info_dict [dict get $::itcl::internal::dicts::classComponents $my_class]
476
+ if {![dict exists $class_info_dict $comp]} {
477
+ puts stderr "keepcomponentoption cannot find component \"$comp\""
478
+ return -code error
479
+ }
480
+ set class_comp_dict [dict get $class_info_dict $comp]
481
+ if {![dict exists $class_comp_dict -keptoptions]} {
482
+ dict set class_comp_dict -keptoptions [list]
483
+ }
484
+ foreach opt $args {
485
+ #puts stderr "KEEP!$opt!"
486
+ if {[string range $opt 0 0] ne "-"} {
487
+ puts stderr "keepcomponentoption: option must begin with a \"-\"!"
488
+ return -code error
489
+ }
490
+ if {[lsearch [dict get $class_comp_dict -keptoptions] $opt] < 0} {
491
+ dict lappend class_comp_dict -keptoptions $opt
492
+ }
493
+ }
494
+ if {![info exists ::itcl::internal::component_objects([lindex [uplevel 1 info context] 1])]} {
495
+ set comp_object $::itcl::internal::component_objects([lindex [uplevel 1 info context] 1])
496
+ } else {
497
+ set comp_object "unknown_comp_obj_$comp!"
498
+ }
499
+ dict set class_info_dict $comp $class_comp_dict
500
+ dict set ::itcl::internal::dicts::classComponents $my_class $class_info_dict
501
+ puts stderr "CLDI!$class_comp_dict!"
502
+ addToItclOptions $my_class $comp_object $args [list]
503
+ }
504
+
505
+ proc ignorecomponentoption {args} {
506
+ puts stderr "IGNORE_COMPONENT_OPTION!$args!"
507
+ }
508
+
509
+ proc renamecomponentoption {args} {
510
+ puts stderr "rename_COMPONENT_OPTION!$args!"
511
+ }
512
+
513
+ proc addoptioncomponent {args} {
514
+ puts stderr "ADD_OPTION_COMPONENT!$args!"
515
+ }
516
+
517
+ proc ignoreoptioncomponent {args} {
518
+ puts stderr "IGNORE_OPTION_COMPONENT!$args!"
519
+ }
520
+
521
+ proc renameoptioncomponent {args} {
522
+ puts stderr "RENAME_OPTION_COMPONENT!$args!"
523
+ }
524
+
525
+ proc getEclassOptions {args} {
526
+ upvar win win
527
+
528
+ #puts stderr "getEclassOptions!$args!$win![uplevel 1 namespace current]!"
529
+ #parray ::itcl::internal::variables::${win}::itcl_options
530
+ set result [list]
531
+ foreach opt [array names ::itcl::internal::variables::${win}::itcl_options] {
532
+ if {[catch {
533
+ foreach {res cls def} [set ::itcl::internal::variables::${win}::__itcl_option_infos($opt)] break
534
+ lappend result [list $opt $res $cls $def [set ::itcl::internal::variables::${win}::itcl_options($opt)]]
535
+ } msg]} {
536
+ }
537
+ }
538
+ return $result
539
+ }
540
+
541
+ proc eclassConfigure {args} {
542
+ upvar win win
543
+
544
+ #puts stderr "+++ eclassConfigure!$args!"
545
+ if {[llength $args] > 1} {
546
+ foreach {opt val} $args break
547
+ if {[::info exists ::itcl::internal::variables::${win}::itcl_options($opt)]} {
548
+ set ::itcl::internal::variables::${win}::itcl_options($opt) $val
549
+ return
550
+ }
551
+ } else {
552
+ foreach {opt} $args break
553
+ if {[::info exists ::itcl::internal::variables::${win}::itcl_options($opt)]} {
554
+ #puts stderr "OP![set ::itcl::internal::variables::${win}::itcl_options($opt)]!"
555
+ foreach {res cls def} [set ::itcl::internal::variables::${win}::__itcl_option_infos($opt)] break
556
+ return [list $opt $res $cls $def [set ::itcl::internal::variables::${win}::itcl_options($opt)]]
557
+ }
558
+ }
559
+ return -code error
560
+ }
561
+
562
+ }
lib/itcl4.2.4/itclWidget.tcl ADDED
@@ -0,0 +1,447 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # itclWidget.tcl
3
+ # ----------------------------------------------------------------------
4
+ # Invoked automatically upon startup to customize the interpreter
5
+ # for [incr Tcl] when one of ::itcl::widget or ::itcl::widgetadaptor is called.
6
+ # ----------------------------------------------------------------------
7
+ # AUTHOR: Arnulf P. Wiedemann
8
+ #
9
+ # ----------------------------------------------------------------------
10
+ # Copyright (c) 2008 Arnulf P. Wiedemann
11
+ # ======================================================================
12
+ # See the file "license.terms" for information on usage and
13
+ # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14
+
15
+ package require Tk 8.6 9
16
+ # package require itclwidget [set ::itcl::version]
17
+
18
+ namespace eval ::itcl {
19
+
20
+ proc widget {name args} {
21
+ set result [uplevel 1 ::itcl::internal::commands::genericclass widget $name $args]
22
+ # we handle create by owerselfs !! allow classunknown to handle that
23
+ oo::objdefine $result unexport create
24
+ return $result
25
+ }
26
+
27
+ proc widgetadaptor {name args} {
28
+ set result [uplevel 1 ::itcl::internal::commands::genericclass widgetadaptor $name $args]
29
+ # we handle create by owerselfs !! allow classunknown to handle that
30
+ oo::objdefine $result unexport create
31
+ return $result
32
+ }
33
+
34
+ } ; # end ::itcl
35
+
36
+
37
+ namespace eval ::itcl::internal::commands {
38
+
39
+ proc initWidgetOptions {varNsName widgetName className} {
40
+ set myDict [set ::itcl::internal::dicts::classOptions]
41
+ if {$myDict eq ""} {
42
+ return
43
+ }
44
+ if {![dict exists $myDict $className]} {
45
+ return
46
+ }
47
+ set myDict [dict get $myDict $className]
48
+ foreach option [dict keys $myDict] {
49
+ set infos [dict get $myDict $option]
50
+ set resource [dict get $infos -resource]
51
+ set class [dict get $infos -class]
52
+ set value [::option get $widgetName $resource $class]
53
+ if {$value eq ""} {
54
+ if {[dict exists $infos -default]} {
55
+ set defaultValue [dict get $infos -default]
56
+ uplevel 1 set ${varNsName}::itcl_options($option) $defaultValue
57
+ }
58
+ } else {
59
+ uplevel 1 set ${varNsName}::itcl_options($option) $value
60
+ }
61
+ }
62
+ }
63
+
64
+ proc initWidgetDelegatedOptions {varNsName widgetName className args} {
65
+ set myDict [set ::itcl::internal::dicts::classDelegatedOptions]
66
+ if {$myDict eq ""} {
67
+ return
68
+ }
69
+ if {![dict exists $myDict $className]} {
70
+ return
71
+ }
72
+ set myDict [dict get $myDict $className]
73
+ foreach option [dict keys $myDict] {
74
+ set infos [dict get $myDict $option]
75
+ if {![dict exists $infos -resource]} {
76
+ # this is the case when delegating "*"
77
+ continue
78
+ }
79
+ if {![dict exists $infos -component]} {
80
+ # nothing to do
81
+ continue
82
+ }
83
+ # check if not in the command line options
84
+ # these have higher priority
85
+ set myOption $option
86
+ if {[dict exists $infos -as]} {
87
+ set myOption [dict get $infos -as]
88
+ }
89
+ set noOptionSet 0
90
+ foreach {optName optVal} $args {
91
+ if {$optName eq $myOption} {
92
+ set noOptionSet 1
93
+ break
94
+ }
95
+ }
96
+ if {$noOptionSet} {
97
+ continue
98
+ }
99
+ set resource [dict get $infos -resource]
100
+ set class [dict get $infos -class]
101
+ set component [dict get $infos -component]
102
+ set value [::option get $widgetName $resource $class]
103
+ if {$component ne ""} {
104
+ if {$value ne ""} {
105
+ set compVar [namespace eval ${varNsName}${className} "set $component"]
106
+ if {$compVar ne ""} {
107
+ uplevel 1 $compVar configure $myOption $value
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ proc widgetinitobjectoptions {varNsName widgetName className} {
115
+ #puts stderr "initWidgetObjectOptions!$varNsName!$widgetName!$className!"
116
+ }
117
+
118
+ proc deletehull {newName oldName what} {
119
+ if {$what eq "delete"} {
120
+ set name [namespace tail $newName]
121
+ regsub {hull[0-9]+} $name {} name
122
+ rename $name {}
123
+ }
124
+ if {$what eq "rename"} {
125
+ set name [namespace tail $newName]
126
+ regsub {hull[0-9]+} $name {} name
127
+ rename $name {}
128
+ }
129
+ }
130
+
131
+ proc hullandoptionsinstall {objectName className widgetClass hulltype args} {
132
+ if {$hulltype eq ""} {
133
+ set hulltype frame
134
+ }
135
+ set idx 0
136
+ set found 0
137
+ foreach {optName optValue} $args {
138
+ if {$optName eq "-class"} {
139
+ set found 1
140
+ set widgetClass $optValue
141
+ break
142
+ }
143
+ incr idx
144
+ }
145
+ if {$found} {
146
+ set args [lreplace $args $idx [expr {$idx + 1}]]
147
+ }
148
+ if {$widgetClass eq ""} {
149
+ set widgetClass $className
150
+ set widgetClass [string totitle $widgetClass]
151
+ }
152
+ set cmd "set win $objectName; ::itcl::builtin::installhull using $hulltype -class $widgetClass $args"
153
+ uplevel 2 $cmd
154
+ }
155
+
156
+ } ; # end ::itcl::internal::commands
157
+
158
+ namespace eval ::itcl::builtin {
159
+
160
+ proc installhull {args} {
161
+ set cmdPath ::itcl::internal::commands
162
+ set className [uplevel 1 info class]
163
+
164
+ set replace 0
165
+ switch -- [llength $args] {
166
+ 0 {
167
+ return -code error\
168
+ "wrong # args: should be \"[lindex [info level 0] 0]\
169
+ name|using <widgetType> ?arg ...?\""
170
+ }
171
+ 1 {
172
+ set widgetName [lindex $args 0]
173
+ set varNsName $::itcl::internal::varNsName($widgetName)
174
+ }
175
+ default {
176
+ upvar win win
177
+ set widgetName $win
178
+
179
+ set varNsName $::itcl::internal::varNsName($widgetName)
180
+ set widgetType [lindex $args 1]
181
+ incr replace
182
+ if {[llength $args] > 3 && [lindex $args 2] eq "-class"} {
183
+ set classNam [lindex $args 3]
184
+ incr replace 2
185
+ } else {
186
+ set classNam [string totitle $widgetType]
187
+ }
188
+ uplevel 1 [lreplace $args 0 $replace $widgetType $widgetName -class $classNam]
189
+ uplevel 1 [list ${cmdPath}::initWidgetOptions $varNsName $widgetName $className]
190
+ }
191
+ }
192
+
193
+ # initialize the itcl_hull variable
194
+ set i 0
195
+ set nam ::itcl::internal::widgets::hull
196
+ while {1} {
197
+ incr i
198
+ set hullNam ${nam}${i}$widgetName
199
+ if {[::info command $hullNam] eq ""} {
200
+ break
201
+ }
202
+ }
203
+ uplevel 1 [list ${cmdPath}::sethullwindowname $widgetName]
204
+ uplevel 1 [list ::rename $widgetName $hullNam]
205
+ uplevel 1 [list ::trace add command $hullNam {delete rename} ::itcl::internal::commands::deletehull]
206
+ catch {${cmdPath}::checksetitclhull [list] 0}
207
+ namespace eval ${varNsName}${className} "set itcl_hull $hullNam"
208
+ catch {${cmdPath}::checksetitclhull [list] 2}
209
+ uplevel 1 [lreplace $args 0 $replace ${cmdPath}::initWidgetDelegatedOptions $varNsName $widgetName $className]
210
+ }
211
+
212
+ proc installcomponent {args} {
213
+ upvar win win
214
+
215
+ set className [uplevel 1 info class]
216
+ set myType [${className}::info types [namespace tail $className]]
217
+ set isType 0
218
+ if {$myType ne ""} {
219
+ set isType 1
220
+ }
221
+ set numArgs [llength $args]
222
+ set usage "usage: installcomponent <componentName> using <widgetType> <widgetPath> ?-option value ...?"
223
+ if {$numArgs < 4} {
224
+ error $usage
225
+ }
226
+ foreach {componentName using widgetType widgetPath} $args break
227
+ set opts [lrange $args 4 end]
228
+ if {$using ne "using"} {
229
+ error $usage
230
+ }
231
+ if {!$isType} {
232
+ set hullExists [uplevel 1 ::info exists itcl_hull]
233
+ if {!$hullExists} {
234
+ error "cannot install \"$componentName\" before \"itcl_hull\" exists"
235
+ }
236
+ set hullVal [uplevel 1 set itcl_hull]
237
+ if {$hullVal eq ""} {
238
+ error "cannot install \"$componentName\" before \"itcl_hull\" exists"
239
+ }
240
+ }
241
+ # check for delegated option and ask the option database for the values
242
+ # first check for number of delegated options
243
+ set numOpts 0
244
+ set starOption 0
245
+ set myDict [set ::itcl::internal::dicts::classDelegatedOptions]
246
+ if {[dict exists $myDict $className]} {
247
+ set myDict [dict get $myDict $className]
248
+ foreach option [dict keys $myDict] {
249
+ if {$option eq "*"} {
250
+ set starOption 1
251
+ }
252
+ incr numOpts
253
+ }
254
+ }
255
+ set myOptionDict [set ::itcl::internal::dicts::classOptions]
256
+ if {[dict exists $myOptionDict $className]} {
257
+ set myOptionDict [dict get $myOptionDict $className]
258
+ }
259
+ set cmd [list $widgetPath configure]
260
+ set cmd1 "set $componentName \[$widgetType $widgetPath\]"
261
+ uplevel 1 $cmd1
262
+ if {$starOption} {
263
+ upvar $componentName compName
264
+ set cmd1 [list $compName configure]
265
+ set configInfos [uplevel 1 $cmd1]
266
+ foreach entry $configInfos {
267
+ if {[llength $entry] > 2} {
268
+ foreach {optName resource class defaultValue} $entry break
269
+ set val ""
270
+ catch {
271
+ set val [::option get $win $resource $class]
272
+ }
273
+ if {$val ne ""} {
274
+ set addOpt 1
275
+ if {[dict exists $myDict $$optName]} {
276
+ set addOpt 0
277
+ } else {
278
+ set starDict [dict get $myDict "*"]
279
+ if {[dict exists $starDict -except]} {
280
+ set exceptions [dict get $starDict -except]
281
+ if {[lsearch $exceptions $optName] >= 0} {
282
+ set addOpt 0
283
+ }
284
+
285
+ }
286
+ if {[dict exists $myOptionDict $optName]} {
287
+ set addOpt 0
288
+ }
289
+ }
290
+ if {$addOpt} {
291
+ lappend cmd $optName $val
292
+ }
293
+
294
+ }
295
+
296
+ }
297
+ }
298
+ } else {
299
+ foreach optName [dict keys $myDict] {
300
+ set optInfos [dict get $myDict $optName]
301
+ set resource [dict get $optInfos -resource]
302
+ set class [namespace tail $className]
303
+ set class [string totitle $class]
304
+ set val ""
305
+ catch {
306
+ set val [::option get $win $resource $class]
307
+ }
308
+ if {$val ne ""} {
309
+ if {[dict exists $optInfos -as] } {
310
+ set optName [dict get $optInfos -as]
311
+ }
312
+ lappend cmd $optName $val
313
+ }
314
+ }
315
+ }
316
+ lappend cmd {*}$opts
317
+ uplevel 1 $cmd
318
+ }
319
+
320
+ } ; # end ::itcl::builtin
321
+
322
+ set ::itcl::internal::dicts::hullTypes [list \
323
+ frame \
324
+ toplevel \
325
+ labelframe \
326
+ ttk:frame \
327
+ ttk:toplevel \
328
+ ttk:labelframe \
329
+ ]
330
+
331
+ namespace eval ::itcl::builtin::Info {
332
+
333
+ proc hulltypes {args} {
334
+ namespace upvar ::itcl::internal::dicts hullTypes hullTypes
335
+
336
+ set numArgs [llength $args]
337
+ if {$numArgs > 1} {
338
+ error "wrong # args should be: info hulltypes ?<pattern>?"
339
+ }
340
+ set pattern ""
341
+ if {$numArgs > 0} {
342
+ set pattern [lindex $args 0]
343
+ }
344
+ if {$pattern ne ""} {
345
+ return [lsearch -all -inline -glob $hullTypes $pattern]
346
+ }
347
+ return $hullTypes
348
+
349
+ }
350
+
351
+ proc widgetclasses {args} {
352
+ set numArgs [llength $args]
353
+ if {$numArgs > 1} {
354
+ error "wrong # args should be: info widgetclasses ?<pattern>?"
355
+ }
356
+ set pattern ""
357
+ if {$numArgs > 0} {
358
+ set pattern [lindex $args 0]
359
+ }
360
+ set myDict [set ::itcl::internal::dicts::classes]
361
+ if {![dict exists $myDict widget]} {
362
+ return [list]
363
+ }
364
+ set myDict [dict get $myDict widget]
365
+ set result [list]
366
+ if {$pattern ne ""} {
367
+ foreach key [dict keys $myDict] {
368
+ set myInfo [dict get $myDict $key]
369
+ set value [dict get $myInfo -widget]
370
+ if {[string match $pattern $value]} {
371
+ lappend result $value
372
+ }
373
+ }
374
+ } else {
375
+ foreach key [dict keys $myDict] {
376
+ set myInfo [dict get $myDict $key]
377
+ lappend result [dict get $myInfo -widget]
378
+ }
379
+ }
380
+ return $result
381
+ }
382
+
383
+ proc widgets {args} {
384
+ set numArgs [llength $args]
385
+ if {$numArgs > 1} {
386
+ error "wrong # args should be: info widgets ?<pattern>?"
387
+ }
388
+ set pattern ""
389
+ if {$numArgs > 0} {
390
+ set pattern [lindex $args 0]
391
+ }
392
+ set myDict [set ::itcl::internal::dicts::classes]
393
+ if {![dict exists $myDict widget]} {
394
+ return [list]
395
+ }
396
+ set myDict [dict get $myDict widget]
397
+ set result [list]
398
+ if {$pattern ne ""} {
399
+ foreach key [dict keys $myDict] {
400
+ set myInfo [dict get $myDict $key]
401
+ set value [dict get $myInfo -name]
402
+ if {[string match $pattern $value]} {
403
+ lappend result $value
404
+ }
405
+ }
406
+ } else {
407
+ foreach key [dict keys $myDict] {
408
+ set myInfo [dict get $myDict $key]
409
+ lappend result [dict get $myInfo -name]
410
+ }
411
+ }
412
+ return $result
413
+ }
414
+
415
+ proc widgetadaptors {args} {
416
+ set numArgs [llength $args]
417
+ if {$numArgs > 1} {
418
+ error "wrong # args should be: info widgetadaptors ?<pattern>?"
419
+ }
420
+ set pattern ""
421
+ if {$numArgs > 0} {
422
+ set pattern [lindex $args 0]
423
+ }
424
+ set myDict [set ::itcl::internal::dicts::classes]
425
+ if {![dict exists $myDict widgetadaptor]} {
426
+ return [list]
427
+ }
428
+ set myDict [dict get $myDict widgetadaptor]
429
+ set result [list]
430
+ if {$pattern ne ""} {
431
+ foreach key [dict keys $myDict] {
432
+ set myInfo [dict get $myDict $key]
433
+ set value [dict get $myInfo -name]
434
+ if {[string match $pattern $value]} {
435
+ lappend result $value
436
+ }
437
+ }
438
+ } else {
439
+ foreach key [dict keys $myDict] {
440
+ set myInfo [dict get $myDict $key]
441
+ lappend result [dict get $myInfo -name]
442
+ }
443
+ }
444
+ return $result
445
+ }
446
+
447
+ } ; # end ::itcl::builtin::Info
lib/itcl4.2.4/libitclstub4.2.4.a ADDED
Binary file (2.75 kB). View file
 
lib/itcl4.2.4/pkgIndex.tcl ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- tcl -*-
2
+ # Tcl package index file, version 1.1
3
+ #
4
+
5
+ if {![package vsatisfies [package provide Tcl] 8.6-]} {return}
6
+
7
+ if {[package vsatisfies [package provide Tcl] 9.0-]} {
8
+ package ifneeded itcl 4.2.4 \
9
+ [list load [file join $dir libtcl9itcl4.2.4.so] Itcl]
10
+ } else {
11
+ package ifneeded itcl 4.2.4 \
12
+ [list load [file join $dir libitcl4.2.4.so] Itcl]
13
+ }
14
+ package ifneeded Itcl 4.2.4 [list package require -exact itcl 4.2.4]
lib/python3.10/py_compile.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Routine to "compile" a .py file to a .pyc file.
2
+
3
+ This module has intimate knowledge of the format of .pyc files.
4
+ """
5
+
6
+ import enum
7
+ import importlib._bootstrap_external
8
+ import importlib.machinery
9
+ import importlib.util
10
+ import os
11
+ import os.path
12
+ import sys
13
+ import traceback
14
+
15
+ __all__ = ["compile", "main", "PyCompileError", "PycInvalidationMode"]
16
+
17
+
18
+ class PyCompileError(Exception):
19
+ """Exception raised when an error occurs while attempting to
20
+ compile the file.
21
+
22
+ To raise this exception, use
23
+
24
+ raise PyCompileError(exc_type,exc_value,file[,msg])
25
+
26
+ where
27
+
28
+ exc_type: exception type to be used in error message
29
+ type name can be accesses as class variable
30
+ 'exc_type_name'
31
+
32
+ exc_value: exception value to be used in error message
33
+ can be accesses as class variable 'exc_value'
34
+
35
+ file: name of file being compiled to be used in error message
36
+ can be accesses as class variable 'file'
37
+
38
+ msg: string message to be written as error message
39
+ If no value is given, a default exception message will be
40
+ given, consistent with 'standard' py_compile output.
41
+ message (or default) can be accesses as class variable
42
+ 'msg'
43
+
44
+ """
45
+
46
+ def __init__(self, exc_type, exc_value, file, msg=''):
47
+ exc_type_name = exc_type.__name__
48
+ if exc_type is SyntaxError:
49
+ tbtext = ''.join(traceback.format_exception_only(
50
+ exc_type, exc_value))
51
+ errmsg = tbtext.replace('File "<string>"', 'File "%s"' % file)
52
+ else:
53
+ errmsg = "Sorry: %s: %s" % (exc_type_name,exc_value)
54
+
55
+ Exception.__init__(self,msg or errmsg,exc_type_name,exc_value,file)
56
+
57
+ self.exc_type_name = exc_type_name
58
+ self.exc_value = exc_value
59
+ self.file = file
60
+ self.msg = msg or errmsg
61
+
62
+ def __str__(self):
63
+ return self.msg
64
+
65
+
66
+ class PycInvalidationMode(enum.Enum):
67
+ TIMESTAMP = 1
68
+ CHECKED_HASH = 2
69
+ UNCHECKED_HASH = 3
70
+
71
+
72
+ def _get_default_invalidation_mode():
73
+ if os.environ.get('SOURCE_DATE_EPOCH'):
74
+ return PycInvalidationMode.CHECKED_HASH
75
+ else:
76
+ return PycInvalidationMode.TIMESTAMP
77
+
78
+
79
+ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1,
80
+ invalidation_mode=None, quiet=0):
81
+ """Byte-compile one Python source file to Python bytecode.
82
+
83
+ :param file: The source file name.
84
+ :param cfile: The target byte compiled file name. When not given, this
85
+ defaults to the PEP 3147/PEP 488 location.
86
+ :param dfile: Purported file name, i.e. the file name that shows up in
87
+ error messages. Defaults to the source file name.
88
+ :param doraise: Flag indicating whether or not an exception should be
89
+ raised when a compile error is found. If an exception occurs and this
90
+ flag is set to False, a string indicating the nature of the exception
91
+ will be printed, and the function will return to the caller. If an
92
+ exception occurs and this flag is set to True, a PyCompileError
93
+ exception will be raised.
94
+ :param optimize: The optimization level for the compiler. Valid values
95
+ are -1, 0, 1 and 2. A value of -1 means to use the optimization
96
+ level of the current interpreter, as given by -O command line options.
97
+ :param invalidation_mode:
98
+ :param quiet: Return full output with False or 0, errors only with 1,
99
+ and no output with 2.
100
+
101
+ :return: Path to the resulting byte compiled file.
102
+
103
+ Note that it isn't necessary to byte-compile Python modules for
104
+ execution efficiency -- Python itself byte-compiles a module when
105
+ it is loaded, and if it can, writes out the bytecode to the
106
+ corresponding .pyc file.
107
+
108
+ However, if a Python installation is shared between users, it is a
109
+ good idea to byte-compile all modules upon installation, since
110
+ other users may not be able to write in the source directories,
111
+ and thus they won't be able to write the .pyc file, and then
112
+ they would be byte-compiling every module each time it is loaded.
113
+ This can slow down program start-up considerably.
114
+
115
+ See compileall.py for a script/module that uses this module to
116
+ byte-compile all installed files (or all files in selected
117
+ directories).
118
+
119
+ Do note that FileExistsError is raised if cfile ends up pointing at a
120
+ non-regular file or symlink. Because the compilation uses a file renaming,
121
+ the resulting file would be regular and thus not the same type of file as
122
+ it was previously.
123
+ """
124
+ if invalidation_mode is None:
125
+ invalidation_mode = _get_default_invalidation_mode()
126
+ if cfile is None:
127
+ if optimize >= 0:
128
+ optimization = optimize if optimize >= 1 else ''
129
+ cfile = importlib.util.cache_from_source(file,
130
+ optimization=optimization)
131
+ else:
132
+ cfile = importlib.util.cache_from_source(file)
133
+ if os.path.islink(cfile):
134
+ msg = ('{} is a symlink and will be changed into a regular file if '
135
+ 'import writes a byte-compiled file to it')
136
+ raise FileExistsError(msg.format(cfile))
137
+ elif os.path.exists(cfile) and not os.path.isfile(cfile):
138
+ msg = ('{} is a non-regular file and will be changed into a regular '
139
+ 'one if import writes a byte-compiled file to it')
140
+ raise FileExistsError(msg.format(cfile))
141
+ loader = importlib.machinery.SourceFileLoader('<py_compile>', file)
142
+ source_bytes = loader.get_data(file)
143
+ try:
144
+ code = loader.source_to_code(source_bytes, dfile or file,
145
+ _optimize=optimize)
146
+ except Exception as err:
147
+ py_exc = PyCompileError(err.__class__, err, dfile or file)
148
+ if quiet < 2:
149
+ if doraise:
150
+ raise py_exc
151
+ else:
152
+ sys.stderr.write(py_exc.msg + '\n')
153
+ return
154
+ try:
155
+ dirname = os.path.dirname(cfile)
156
+ if dirname:
157
+ os.makedirs(dirname)
158
+ except FileExistsError:
159
+ pass
160
+ if invalidation_mode == PycInvalidationMode.TIMESTAMP:
161
+ source_stats = loader.path_stats(file)
162
+ bytecode = importlib._bootstrap_external._code_to_timestamp_pyc(
163
+ code, source_stats['mtime'], source_stats['size'])
164
+ else:
165
+ source_hash = importlib.util.source_hash(source_bytes)
166
+ bytecode = importlib._bootstrap_external._code_to_hash_pyc(
167
+ code,
168
+ source_hash,
169
+ (invalidation_mode == PycInvalidationMode.CHECKED_HASH),
170
+ )
171
+ mode = importlib._bootstrap_external._calc_mode(file)
172
+ importlib._bootstrap_external._write_atomic(cfile, bytecode, mode)
173
+ return cfile
174
+
175
+
176
+ def main():
177
+ import argparse
178
+
179
+ description = 'A simple command-line interface for py_compile module.'
180
+ parser = argparse.ArgumentParser(description=description)
181
+ parser.add_argument(
182
+ '-q', '--quiet',
183
+ action='store_true',
184
+ help='Suppress error output',
185
+ )
186
+ parser.add_argument(
187
+ 'filenames',
188
+ nargs='+',
189
+ help='Files to compile',
190
+ )
191
+ args = parser.parse_args()
192
+ if args.filenames == ['-']:
193
+ filenames = [filename.rstrip('\n') for filename in sys.stdin.readlines()]
194
+ else:
195
+ filenames = args.filenames
196
+ for filename in filenames:
197
+ try:
198
+ compile(filename, doraise=True)
199
+ except PyCompileError as error:
200
+ if args.quiet:
201
+ parser.exit(1)
202
+ else:
203
+ parser.exit(1, error.msg)
204
+ except OSError as error:
205
+ if args.quiet:
206
+ parser.exit(1)
207
+ else:
208
+ parser.exit(1, str(error))
209
+
210
+
211
+ if __name__ == "__main__":
212
+ main()
lib/python3.10/pyclbr.py ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Parse a Python module and describe its classes and functions.
2
+
3
+ Parse enough of a Python file to recognize imports and class and
4
+ function definitions, and to find out the superclasses of a class.
5
+
6
+ The interface consists of a single function:
7
+ readmodule_ex(module, path=None)
8
+ where module is the name of a Python module, and path is an optional
9
+ list of directories where the module is to be searched. If present,
10
+ path is prepended to the system search path sys.path. The return value
11
+ is a dictionary. The keys of the dictionary are the names of the
12
+ classes and functions defined in the module (including classes that are
13
+ defined via the from XXX import YYY construct). The values are
14
+ instances of classes Class and Function. One special key/value pair is
15
+ present for packages: the key '__path__' has a list as its value which
16
+ contains the package search path.
17
+
18
+ Classes and Functions have a common superclass: _Object. Every instance
19
+ has the following attributes:
20
+ module -- name of the module;
21
+ name -- name of the object;
22
+ file -- file in which the object is defined;
23
+ lineno -- line in the file where the object's definition starts;
24
+ end_lineno -- line in the file where the object's definition ends;
25
+ parent -- parent of this object, if any;
26
+ children -- nested objects contained in this object.
27
+ The 'children' attribute is a dictionary mapping names to objects.
28
+
29
+ Instances of Function describe functions with the attributes from _Object,
30
+ plus the following:
31
+ is_async -- if a function is defined with an 'async' prefix
32
+
33
+ Instances of Class describe classes with the attributes from _Object,
34
+ plus the following:
35
+ super -- list of super classes (Class instances if possible);
36
+ methods -- mapping of method names to beginning line numbers.
37
+ If the name of a super class is not recognized, the corresponding
38
+ entry in the list of super classes is not a class instance but a
39
+ string giving the name of the super class. Since import statements
40
+ are recognized and imported modules are scanned as well, this
41
+ shouldn't happen often.
42
+ """
43
+
44
+ import ast
45
+ import sys
46
+ import importlib.util
47
+
48
+ __all__ = ["readmodule", "readmodule_ex", "Class", "Function"]
49
+
50
+ _modules = {} # Initialize cache of modules we've seen.
51
+
52
+
53
+ class _Object:
54
+ "Information about Python class or function."
55
+ def __init__(self, module, name, file, lineno, end_lineno, parent):
56
+ self.module = module
57
+ self.name = name
58
+ self.file = file
59
+ self.lineno = lineno
60
+ self.end_lineno = end_lineno
61
+ self.parent = parent
62
+ self.children = {}
63
+ if parent is not None:
64
+ parent.children[name] = self
65
+
66
+
67
+ # Odd Function and Class signatures are for back-compatibility.
68
+ class Function(_Object):
69
+ "Information about a Python function, including methods."
70
+ def __init__(self, module, name, file, lineno,
71
+ parent=None, is_async=False, *, end_lineno=None):
72
+ super().__init__(module, name, file, lineno, end_lineno, parent)
73
+ self.is_async = is_async
74
+ if isinstance(parent, Class):
75
+ parent.methods[name] = lineno
76
+
77
+
78
+ class Class(_Object):
79
+ "Information about a Python class."
80
+ def __init__(self, module, name, super_, file, lineno,
81
+ parent=None, *, end_lineno=None):
82
+ super().__init__(module, name, file, lineno, end_lineno, parent)
83
+ self.super = super_ or []
84
+ self.methods = {}
85
+
86
+
87
+ # These 2 functions are used in these tests
88
+ # Lib/test/test_pyclbr, Lib/idlelib/idle_test/test_browser.py
89
+ def _nest_function(ob, func_name, lineno, end_lineno, is_async=False):
90
+ "Return a Function after nesting within ob."
91
+ return Function(ob.module, func_name, ob.file, lineno,
92
+ parent=ob, is_async=is_async, end_lineno=end_lineno)
93
+
94
+ def _nest_class(ob, class_name, lineno, end_lineno, super=None):
95
+ "Return a Class after nesting within ob."
96
+ return Class(ob.module, class_name, super, ob.file, lineno,
97
+ parent=ob, end_lineno=end_lineno)
98
+
99
+
100
+ def readmodule(module, path=None):
101
+ """Return Class objects for the top-level classes in module.
102
+
103
+ This is the original interface, before Functions were added.
104
+ """
105
+
106
+ res = {}
107
+ for key, value in _readmodule(module, path or []).items():
108
+ if isinstance(value, Class):
109
+ res[key] = value
110
+ return res
111
+
112
+ def readmodule_ex(module, path=None):
113
+ """Return a dictionary with all functions and classes in module.
114
+
115
+ Search for module in PATH + sys.path.
116
+ If possible, include imported superclasses.
117
+ Do this by reading source, without importing (and executing) it.
118
+ """
119
+ return _readmodule(module, path or [])
120
+
121
+
122
+ def _readmodule(module, path, inpackage=None):
123
+ """Do the hard work for readmodule[_ex].
124
+
125
+ If inpackage is given, it must be the dotted name of the package in
126
+ which we are searching for a submodule, and then PATH must be the
127
+ package search path; otherwise, we are searching for a top-level
128
+ module, and path is combined with sys.path.
129
+ """
130
+ # Compute the full module name (prepending inpackage if set).
131
+ if inpackage is not None:
132
+ fullmodule = "%s.%s" % (inpackage, module)
133
+ else:
134
+ fullmodule = module
135
+
136
+ # Check in the cache.
137
+ if fullmodule in _modules:
138
+ return _modules[fullmodule]
139
+
140
+ # Initialize the dict for this module's contents.
141
+ tree = {}
142
+
143
+ # Check if it is a built-in module; we don't do much for these.
144
+ if module in sys.builtin_module_names and inpackage is None:
145
+ _modules[module] = tree
146
+ return tree
147
+
148
+ # Check for a dotted module name.
149
+ i = module.rfind('.')
150
+ if i >= 0:
151
+ package = module[:i]
152
+ submodule = module[i+1:]
153
+ parent = _readmodule(package, path, inpackage)
154
+ if inpackage is not None:
155
+ package = "%s.%s" % (inpackage, package)
156
+ if not '__path__' in parent:
157
+ raise ImportError('No package named {}'.format(package))
158
+ return _readmodule(submodule, parent['__path__'], package)
159
+
160
+ # Search the path for the module.
161
+ f = None
162
+ if inpackage is not None:
163
+ search_path = path
164
+ else:
165
+ search_path = path + sys.path
166
+ spec = importlib.util._find_spec_from_path(fullmodule, search_path)
167
+ if spec is None:
168
+ raise ModuleNotFoundError(f"no module named {fullmodule!r}", name=fullmodule)
169
+ _modules[fullmodule] = tree
170
+ # Is module a package?
171
+ if spec.submodule_search_locations is not None:
172
+ tree['__path__'] = spec.submodule_search_locations
173
+ try:
174
+ source = spec.loader.get_source(fullmodule)
175
+ except (AttributeError, ImportError):
176
+ # If module is not Python source, we cannot do anything.
177
+ return tree
178
+ else:
179
+ if source is None:
180
+ return tree
181
+
182
+ fname = spec.loader.get_filename(fullmodule)
183
+ return _create_tree(fullmodule, path, fname, source, tree, inpackage)
184
+
185
+
186
+ class _ModuleBrowser(ast.NodeVisitor):
187
+ def __init__(self, module, path, file, tree, inpackage):
188
+ self.path = path
189
+ self.tree = tree
190
+ self.file = file
191
+ self.module = module
192
+ self.inpackage = inpackage
193
+ self.stack = []
194
+
195
+ def visit_ClassDef(self, node):
196
+ bases = []
197
+ for base in node.bases:
198
+ name = ast.unparse(base)
199
+ if name in self.tree:
200
+ # We know this super class.
201
+ bases.append(self.tree[name])
202
+ elif len(names := name.split(".")) > 1:
203
+ # Super class form is module.class:
204
+ # look in module for class.
205
+ *_, module, class_ = names
206
+ if module in _modules:
207
+ bases.append(_modules[module].get(class_, name))
208
+ else:
209
+ bases.append(name)
210
+
211
+ parent = self.stack[-1] if self.stack else None
212
+ class_ = Class(self.module, node.name, bases, self.file, node.lineno,
213
+ parent=parent, end_lineno=node.end_lineno)
214
+ if parent is None:
215
+ self.tree[node.name] = class_
216
+ self.stack.append(class_)
217
+ self.generic_visit(node)
218
+ self.stack.pop()
219
+
220
+ def visit_FunctionDef(self, node, *, is_async=False):
221
+ parent = self.stack[-1] if self.stack else None
222
+ function = Function(self.module, node.name, self.file, node.lineno,
223
+ parent, is_async, end_lineno=node.end_lineno)
224
+ if parent is None:
225
+ self.tree[node.name] = function
226
+ self.stack.append(function)
227
+ self.generic_visit(node)
228
+ self.stack.pop()
229
+
230
+ def visit_AsyncFunctionDef(self, node):
231
+ self.visit_FunctionDef(node, is_async=True)
232
+
233
+ def visit_Import(self, node):
234
+ if node.col_offset != 0:
235
+ return
236
+
237
+ for module in node.names:
238
+ try:
239
+ try:
240
+ _readmodule(module.name, self.path, self.inpackage)
241
+ except ImportError:
242
+ _readmodule(module.name, [])
243
+ except (ImportError, SyntaxError):
244
+ # If we can't find or parse the imported module,
245
+ # too bad -- don't die here.
246
+ continue
247
+
248
+ def visit_ImportFrom(self, node):
249
+ if node.col_offset != 0:
250
+ return
251
+ try:
252
+ module = "." * node.level
253
+ if node.module:
254
+ module += node.module
255
+ module = _readmodule(module, self.path, self.inpackage)
256
+ except (ImportError, SyntaxError):
257
+ return
258
+
259
+ for name in node.names:
260
+ if name.name in module:
261
+ self.tree[name.asname or name.name] = module[name.name]
262
+ elif name.name == "*":
263
+ for import_name, import_value in module.items():
264
+ if import_name.startswith("_"):
265
+ continue
266
+ self.tree[import_name] = import_value
267
+
268
+
269
+ def _create_tree(fullmodule, path, fname, source, tree, inpackage):
270
+ mbrowser = _ModuleBrowser(fullmodule, path, fname, tree, inpackage)
271
+ mbrowser.visit(ast.parse(source))
272
+ return mbrowser.tree
273
+
274
+
275
+ def _main():
276
+ "Print module output (default this file) for quick visual check."
277
+ import os
278
+ try:
279
+ mod = sys.argv[1]
280
+ except:
281
+ mod = __file__
282
+ if os.path.exists(mod):
283
+ path = [os.path.dirname(mod)]
284
+ mod = os.path.basename(mod)
285
+ if mod.lower().endswith(".py"):
286
+ mod = mod[:-3]
287
+ else:
288
+ path = []
289
+ tree = readmodule_ex(mod, path)
290
+ lineno_key = lambda a: getattr(a, 'lineno', 0)
291
+ objs = sorted(tree.values(), key=lineno_key, reverse=True)
292
+ indent_level = 2
293
+ while objs:
294
+ obj = objs.pop()
295
+ if isinstance(obj, list):
296
+ # Value is a __path__ key.
297
+ continue
298
+ if not hasattr(obj, 'indent'):
299
+ obj.indent = 0
300
+
301
+ if isinstance(obj, _Object):
302
+ new_objs = sorted(obj.children.values(),
303
+ key=lineno_key, reverse=True)
304
+ for ob in new_objs:
305
+ ob.indent = obj.indent + indent_level
306
+ objs.extend(new_objs)
307
+ if isinstance(obj, Class):
308
+ print("{}class {} {} {}"
309
+ .format(' ' * obj.indent, obj.name, obj.super, obj.lineno))
310
+ elif isinstance(obj, Function):
311
+ print("{}def {} {}".format(' ' * obj.indent, obj.name, obj.lineno))
312
+
313
+ if __name__ == "__main__":
314
+ _main()
lib/python3.10/pydoc.py ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.10/queue.py ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''A multi-producer, multi-consumer queue.'''
2
+
3
+ import threading
4
+ import types
5
+ from collections import deque
6
+ from heapq import heappush, heappop
7
+ from time import monotonic as time
8
+ try:
9
+ from _queue import SimpleQueue
10
+ except ImportError:
11
+ SimpleQueue = None
12
+
13
+ __all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue', 'SimpleQueue']
14
+
15
+
16
+ try:
17
+ from _queue import Empty
18
+ except ImportError:
19
+ class Empty(Exception):
20
+ 'Exception raised by Queue.get(block=0)/get_nowait().'
21
+ pass
22
+
23
+ class Full(Exception):
24
+ 'Exception raised by Queue.put(block=0)/put_nowait().'
25
+ pass
26
+
27
+
28
+ class Queue:
29
+ '''Create a queue object with a given maximum size.
30
+
31
+ If maxsize is <= 0, the queue size is infinite.
32
+ '''
33
+
34
+ def __init__(self, maxsize=0):
35
+ self.maxsize = maxsize
36
+ self._init(maxsize)
37
+
38
+ # mutex must be held whenever the queue is mutating. All methods
39
+ # that acquire mutex must release it before returning. mutex
40
+ # is shared between the three conditions, so acquiring and
41
+ # releasing the conditions also acquires and releases mutex.
42
+ self.mutex = threading.Lock()
43
+
44
+ # Notify not_empty whenever an item is added to the queue; a
45
+ # thread waiting to get is notified then.
46
+ self.not_empty = threading.Condition(self.mutex)
47
+
48
+ # Notify not_full whenever an item is removed from the queue;
49
+ # a thread waiting to put is notified then.
50
+ self.not_full = threading.Condition(self.mutex)
51
+
52
+ # Notify all_tasks_done whenever the number of unfinished tasks
53
+ # drops to zero; thread waiting to join() is notified to resume
54
+ self.all_tasks_done = threading.Condition(self.mutex)
55
+ self.unfinished_tasks = 0
56
+
57
+ def task_done(self):
58
+ '''Indicate that a formerly enqueued task is complete.
59
+
60
+ Used by Queue consumer threads. For each get() used to fetch a task,
61
+ a subsequent call to task_done() tells the queue that the processing
62
+ on the task is complete.
63
+
64
+ If a join() is currently blocking, it will resume when all items
65
+ have been processed (meaning that a task_done() call was received
66
+ for every item that had been put() into the queue).
67
+
68
+ Raises a ValueError if called more times than there were items
69
+ placed in the queue.
70
+ '''
71
+ with self.all_tasks_done:
72
+ unfinished = self.unfinished_tasks - 1
73
+ if unfinished <= 0:
74
+ if unfinished < 0:
75
+ raise ValueError('task_done() called too many times')
76
+ self.all_tasks_done.notify_all()
77
+ self.unfinished_tasks = unfinished
78
+
79
+ def join(self):
80
+ '''Blocks until all items in the Queue have been gotten and processed.
81
+
82
+ The count of unfinished tasks goes up whenever an item is added to the
83
+ queue. The count goes down whenever a consumer thread calls task_done()
84
+ to indicate the item was retrieved and all work on it is complete.
85
+
86
+ When the count of unfinished tasks drops to zero, join() unblocks.
87
+ '''
88
+ with self.all_tasks_done:
89
+ while self.unfinished_tasks:
90
+ self.all_tasks_done.wait()
91
+
92
+ def qsize(self):
93
+ '''Return the approximate size of the queue (not reliable!).'''
94
+ with self.mutex:
95
+ return self._qsize()
96
+
97
+ def empty(self):
98
+ '''Return True if the queue is empty, False otherwise (not reliable!).
99
+
100
+ This method is likely to be removed at some point. Use qsize() == 0
101
+ as a direct substitute, but be aware that either approach risks a race
102
+ condition where a queue can grow before the result of empty() or
103
+ qsize() can be used.
104
+
105
+ To create code that needs to wait for all queued tasks to be
106
+ completed, the preferred technique is to use the join() method.
107
+ '''
108
+ with self.mutex:
109
+ return not self._qsize()
110
+
111
+ def full(self):
112
+ '''Return True if the queue is full, False otherwise (not reliable!).
113
+
114
+ This method is likely to be removed at some point. Use qsize() >= n
115
+ as a direct substitute, but be aware that either approach risks a race
116
+ condition where a queue can shrink before the result of full() or
117
+ qsize() can be used.
118
+ '''
119
+ with self.mutex:
120
+ return 0 < self.maxsize <= self._qsize()
121
+
122
+ def put(self, item, block=True, timeout=None):
123
+ '''Put an item into the queue.
124
+
125
+ If optional args 'block' is true and 'timeout' is None (the default),
126
+ block if necessary until a free slot is available. If 'timeout' is
127
+ a non-negative number, it blocks at most 'timeout' seconds and raises
128
+ the Full exception if no free slot was available within that time.
129
+ Otherwise ('block' is false), put an item on the queue if a free slot
130
+ is immediately available, else raise the Full exception ('timeout'
131
+ is ignored in that case).
132
+ '''
133
+ with self.not_full:
134
+ if self.maxsize > 0:
135
+ if not block:
136
+ if self._qsize() >= self.maxsize:
137
+ raise Full
138
+ elif timeout is None:
139
+ while self._qsize() >= self.maxsize:
140
+ self.not_full.wait()
141
+ elif timeout < 0:
142
+ raise ValueError("'timeout' must be a non-negative number")
143
+ else:
144
+ endtime = time() + timeout
145
+ while self._qsize() >= self.maxsize:
146
+ remaining = endtime - time()
147
+ if remaining <= 0.0:
148
+ raise Full
149
+ self.not_full.wait(remaining)
150
+ self._put(item)
151
+ self.unfinished_tasks += 1
152
+ self.not_empty.notify()
153
+
154
+ def get(self, block=True, timeout=None):
155
+ '''Remove and return an item from the queue.
156
+
157
+ If optional args 'block' is true and 'timeout' is None (the default),
158
+ block if necessary until an item is available. If 'timeout' is
159
+ a non-negative number, it blocks at most 'timeout' seconds and raises
160
+ the Empty exception if no item was available within that time.
161
+ Otherwise ('block' is false), return an item if one is immediately
162
+ available, else raise the Empty exception ('timeout' is ignored
163
+ in that case).
164
+ '''
165
+ with self.not_empty:
166
+ if not block:
167
+ if not self._qsize():
168
+ raise Empty
169
+ elif timeout is None:
170
+ while not self._qsize():
171
+ self.not_empty.wait()
172
+ elif timeout < 0:
173
+ raise ValueError("'timeout' must be a non-negative number")
174
+ else:
175
+ endtime = time() + timeout
176
+ while not self._qsize():
177
+ remaining = endtime - time()
178
+ if remaining <= 0.0:
179
+ raise Empty
180
+ self.not_empty.wait(remaining)
181
+ item = self._get()
182
+ self.not_full.notify()
183
+ return item
184
+
185
+ def put_nowait(self, item):
186
+ '''Put an item into the queue without blocking.
187
+
188
+ Only enqueue the item if a free slot is immediately available.
189
+ Otherwise raise the Full exception.
190
+ '''
191
+ return self.put(item, block=False)
192
+
193
+ def get_nowait(self):
194
+ '''Remove and return an item from the queue without blocking.
195
+
196
+ Only get an item if one is immediately available. Otherwise
197
+ raise the Empty exception.
198
+ '''
199
+ return self.get(block=False)
200
+
201
+ # Override these methods to implement other queue organizations
202
+ # (e.g. stack or priority queue).
203
+ # These will only be called with appropriate locks held
204
+
205
+ # Initialize the queue representation
206
+ def _init(self, maxsize):
207
+ self.queue = deque()
208
+
209
+ def _qsize(self):
210
+ return len(self.queue)
211
+
212
+ # Put a new item in the queue
213
+ def _put(self, item):
214
+ self.queue.append(item)
215
+
216
+ # Get an item from the queue
217
+ def _get(self):
218
+ return self.queue.popleft()
219
+
220
+ __class_getitem__ = classmethod(types.GenericAlias)
221
+
222
+
223
+ class PriorityQueue(Queue):
224
+ '''Variant of Queue that retrieves open entries in priority order (lowest first).
225
+
226
+ Entries are typically tuples of the form: (priority number, data).
227
+ '''
228
+
229
+ def _init(self, maxsize):
230
+ self.queue = []
231
+
232
+ def _qsize(self):
233
+ return len(self.queue)
234
+
235
+ def _put(self, item):
236
+ heappush(self.queue, item)
237
+
238
+ def _get(self):
239
+ return heappop(self.queue)
240
+
241
+
242
+ class LifoQueue(Queue):
243
+ '''Variant of Queue that retrieves most recently added entries first.'''
244
+
245
+ def _init(self, maxsize):
246
+ self.queue = []
247
+
248
+ def _qsize(self):
249
+ return len(self.queue)
250
+
251
+ def _put(self, item):
252
+ self.queue.append(item)
253
+
254
+ def _get(self):
255
+ return self.queue.pop()
256
+
257
+
258
+ class _PySimpleQueue:
259
+ '''Simple, unbounded FIFO queue.
260
+
261
+ This pure Python implementation is not reentrant.
262
+ '''
263
+ # Note: while this pure Python version provides fairness
264
+ # (by using a threading.Semaphore which is itself fair, being based
265
+ # on threading.Condition), fairness is not part of the API contract.
266
+ # This allows the C version to use a different implementation.
267
+
268
+ def __init__(self):
269
+ self._queue = deque()
270
+ self._count = threading.Semaphore(0)
271
+
272
+ def put(self, item, block=True, timeout=None):
273
+ '''Put the item on the queue.
274
+
275
+ The optional 'block' and 'timeout' arguments are ignored, as this method
276
+ never blocks. They are provided for compatibility with the Queue class.
277
+ '''
278
+ self._queue.append(item)
279
+ self._count.release()
280
+
281
+ def get(self, block=True, timeout=None):
282
+ '''Remove and return an item from the queue.
283
+
284
+ If optional args 'block' is true and 'timeout' is None (the default),
285
+ block if necessary until an item is available. If 'timeout' is
286
+ a non-negative number, it blocks at most 'timeout' seconds and raises
287
+ the Empty exception if no item was available within that time.
288
+ Otherwise ('block' is false), return an item if one is immediately
289
+ available, else raise the Empty exception ('timeout' is ignored
290
+ in that case).
291
+ '''
292
+ if timeout is not None and timeout < 0:
293
+ raise ValueError("'timeout' must be a non-negative number")
294
+ if not self._count.acquire(block, timeout):
295
+ raise Empty
296
+ return self._queue.popleft()
297
+
298
+ def put_nowait(self, item):
299
+ '''Put an item into the queue without blocking.
300
+
301
+ This is exactly equivalent to `put(item, block=False)` and is only provided
302
+ for compatibility with the Queue class.
303
+ '''
304
+ return self.put(item, block=False)
305
+
306
+ def get_nowait(self):
307
+ '''Remove and return an item from the queue without blocking.
308
+
309
+ Only get an item if one is immediately available. Otherwise
310
+ raise the Empty exception.
311
+ '''
312
+ return self.get(block=False)
313
+
314
+ def empty(self):
315
+ '''Return True if the queue is empty, False otherwise (not reliable!).'''
316
+ return len(self._queue) == 0
317
+
318
+ def qsize(self):
319
+ '''Return the approximate size of the queue (not reliable!).'''
320
+ return len(self._queue)
321
+
322
+ __class_getitem__ = classmethod(types.GenericAlias)
323
+
324
+
325
+ if SimpleQueue is None:
326
+ SimpleQueue = _PySimpleQueue
lib/python3.10/quopri.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #! /usr/bin/env python3
2
+
3
+ """Conversions to/from quoted-printable transport encoding as per RFC 1521."""
4
+
5
+ # (Dec 1991 version).
6
+
7
+ __all__ = ["encode", "decode", "encodestring", "decodestring"]
8
+
9
+ ESCAPE = b'='
10
+ MAXLINESIZE = 76
11
+ HEX = b'0123456789ABCDEF'
12
+ EMPTYSTRING = b''
13
+
14
+ try:
15
+ from binascii import a2b_qp, b2a_qp
16
+ except ImportError:
17
+ a2b_qp = None
18
+ b2a_qp = None
19
+
20
+
21
+ def needsquoting(c, quotetabs, header):
22
+ """Decide whether a particular byte ordinal needs to be quoted.
23
+
24
+ The 'quotetabs' flag indicates whether embedded tabs and spaces should be
25
+ quoted. Note that line-ending tabs and spaces are always encoded, as per
26
+ RFC 1521.
27
+ """
28
+ assert isinstance(c, bytes)
29
+ if c in b' \t':
30
+ return quotetabs
31
+ # if header, we have to escape _ because _ is used to escape space
32
+ if c == b'_':
33
+ return header
34
+ return c == ESCAPE or not (b' ' <= c <= b'~')
35
+
36
+ def quote(c):
37
+ """Quote a single character."""
38
+ assert isinstance(c, bytes) and len(c)==1
39
+ c = ord(c)
40
+ return ESCAPE + bytes((HEX[c//16], HEX[c%16]))
41
+
42
+
43
+
44
+ def encode(input, output, quotetabs, header=False):
45
+ """Read 'input', apply quoted-printable encoding, and write to 'output'.
46
+
47
+ 'input' and 'output' are binary file objects. The 'quotetabs' flag
48
+ indicates whether embedded tabs and spaces should be quoted. Note that
49
+ line-ending tabs and spaces are always encoded, as per RFC 1521.
50
+ The 'header' flag indicates whether we are encoding spaces as _ as per RFC
51
+ 1522."""
52
+
53
+ if b2a_qp is not None:
54
+ data = input.read()
55
+ odata = b2a_qp(data, quotetabs=quotetabs, header=header)
56
+ output.write(odata)
57
+ return
58
+
59
+ def write(s, output=output, lineEnd=b'\n'):
60
+ # RFC 1521 requires that the line ending in a space or tab must have
61
+ # that trailing character encoded.
62
+ if s and s[-1:] in b' \t':
63
+ output.write(s[:-1] + quote(s[-1:]) + lineEnd)
64
+ elif s == b'.':
65
+ output.write(quote(s) + lineEnd)
66
+ else:
67
+ output.write(s + lineEnd)
68
+
69
+ prevline = None
70
+ while 1:
71
+ line = input.readline()
72
+ if not line:
73
+ break
74
+ outline = []
75
+ # Strip off any readline induced trailing newline
76
+ stripped = b''
77
+ if line[-1:] == b'\n':
78
+ line = line[:-1]
79
+ stripped = b'\n'
80
+ # Calculate the un-length-limited encoded line
81
+ for c in line:
82
+ c = bytes((c,))
83
+ if needsquoting(c, quotetabs, header):
84
+ c = quote(c)
85
+ if header and c == b' ':
86
+ outline.append(b'_')
87
+ else:
88
+ outline.append(c)
89
+ # First, write out the previous line
90
+ if prevline is not None:
91
+ write(prevline)
92
+ # Now see if we need any soft line breaks because of RFC-imposed
93
+ # length limitations. Then do the thisline->prevline dance.
94
+ thisline = EMPTYSTRING.join(outline)
95
+ while len(thisline) > MAXLINESIZE:
96
+ # Don't forget to include the soft line break `=' sign in the
97
+ # length calculation!
98
+ write(thisline[:MAXLINESIZE-1], lineEnd=b'=\n')
99
+ thisline = thisline[MAXLINESIZE-1:]
100
+ # Write out the current line
101
+ prevline = thisline
102
+ # Write out the last line, without a trailing newline
103
+ if prevline is not None:
104
+ write(prevline, lineEnd=stripped)
105
+
106
+ def encodestring(s, quotetabs=False, header=False):
107
+ if b2a_qp is not None:
108
+ return b2a_qp(s, quotetabs=quotetabs, header=header)
109
+ from io import BytesIO
110
+ infp = BytesIO(s)
111
+ outfp = BytesIO()
112
+ encode(infp, outfp, quotetabs, header)
113
+ return outfp.getvalue()
114
+
115
+
116
+
117
+ def decode(input, output, header=False):
118
+ """Read 'input', apply quoted-printable decoding, and write to 'output'.
119
+ 'input' and 'output' are binary file objects.
120
+ If 'header' is true, decode underscore as space (per RFC 1522)."""
121
+
122
+ if a2b_qp is not None:
123
+ data = input.read()
124
+ odata = a2b_qp(data, header=header)
125
+ output.write(odata)
126
+ return
127
+
128
+ new = b''
129
+ while 1:
130
+ line = input.readline()
131
+ if not line: break
132
+ i, n = 0, len(line)
133
+ if n > 0 and line[n-1:n] == b'\n':
134
+ partial = 0; n = n-1
135
+ # Strip trailing whitespace
136
+ while n > 0 and line[n-1:n] in b" \t\r":
137
+ n = n-1
138
+ else:
139
+ partial = 1
140
+ while i < n:
141
+ c = line[i:i+1]
142
+ if c == b'_' and header:
143
+ new = new + b' '; i = i+1
144
+ elif c != ESCAPE:
145
+ new = new + c; i = i+1
146
+ elif i+1 == n and not partial:
147
+ partial = 1; break
148
+ elif i+1 < n and line[i+1:i+2] == ESCAPE:
149
+ new = new + ESCAPE; i = i+2
150
+ elif i+2 < n and ishex(line[i+1:i+2]) and ishex(line[i+2:i+3]):
151
+ new = new + bytes((unhex(line[i+1:i+3]),)); i = i+3
152
+ else: # Bad escape sequence -- leave it in
153
+ new = new + c; i = i+1
154
+ if not partial:
155
+ output.write(new + b'\n')
156
+ new = b''
157
+ if new:
158
+ output.write(new)
159
+
160
+ def decodestring(s, header=False):
161
+ if a2b_qp is not None:
162
+ return a2b_qp(s, header=header)
163
+ from io import BytesIO
164
+ infp = BytesIO(s)
165
+ outfp = BytesIO()
166
+ decode(infp, outfp, header=header)
167
+ return outfp.getvalue()
168
+
169
+
170
+
171
+ # Other helper functions
172
+ def ishex(c):
173
+ """Return true if the byte ordinal 'c' is a hexadecimal digit in ASCII."""
174
+ assert isinstance(c, bytes)
175
+ return b'0' <= c <= b'9' or b'a' <= c <= b'f' or b'A' <= c <= b'F'
176
+
177
+ def unhex(s):
178
+ """Get the integer value of a hexadecimal number."""
179
+ bits = 0
180
+ for c in s:
181
+ c = bytes((c,))
182
+ if b'0' <= c <= b'9':
183
+ i = ord('0')
184
+ elif b'a' <= c <= b'f':
185
+ i = ord('a')-10
186
+ elif b'A' <= c <= b'F':
187
+ i = ord(b'A')-10
188
+ else:
189
+ assert False, "non-hex digit "+repr(c)
190
+ bits = bits*16 + (ord(c) - i)
191
+ return bits
192
+
193
+
194
+
195
+ def main():
196
+ import sys
197
+ import getopt
198
+ try:
199
+ opts, args = getopt.getopt(sys.argv[1:], 'td')
200
+ except getopt.error as msg:
201
+ sys.stdout = sys.stderr
202
+ print(msg)
203
+ print("usage: quopri [-t | -d] [file] ...")
204
+ print("-t: quote tabs")
205
+ print("-d: decode; default encode")
206
+ sys.exit(2)
207
+ deco = False
208
+ tabs = False
209
+ for o, a in opts:
210
+ if o == '-t': tabs = True
211
+ if o == '-d': deco = True
212
+ if tabs and deco:
213
+ sys.stdout = sys.stderr
214
+ print("-t and -d are mutually exclusive")
215
+ sys.exit(2)
216
+ if not args: args = ['-']
217
+ sts = 0
218
+ for file in args:
219
+ if file == '-':
220
+ fp = sys.stdin.buffer
221
+ else:
222
+ try:
223
+ fp = open(file, "rb")
224
+ except OSError as msg:
225
+ sys.stderr.write("%s: can't open (%s)\n" % (file, msg))
226
+ sts = 1
227
+ continue
228
+ try:
229
+ if deco:
230
+ decode(fp, sys.stdout.buffer)
231
+ else:
232
+ encode(fp, sys.stdout.buffer, tabs)
233
+ finally:
234
+ if file != '-':
235
+ fp.close()
236
+ if sts:
237
+ sys.exit(sts)
238
+
239
+
240
+
241
+ if __name__ == '__main__':
242
+ main()
lib/python3.10/random.py ADDED
@@ -0,0 +1,930 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Random variable generators.
2
+
3
+ bytes
4
+ -----
5
+ uniform bytes (values between 0 and 255)
6
+
7
+ integers
8
+ --------
9
+ uniform within range
10
+
11
+ sequences
12
+ ---------
13
+ pick random element
14
+ pick random sample
15
+ pick weighted random sample
16
+ generate random permutation
17
+
18
+ distributions on the real line:
19
+ ------------------------------
20
+ uniform
21
+ triangular
22
+ normal (Gaussian)
23
+ lognormal
24
+ negative exponential
25
+ gamma
26
+ beta
27
+ pareto
28
+ Weibull
29
+
30
+ distributions on the circle (angles 0 to 2pi)
31
+ ---------------------------------------------
32
+ circular uniform
33
+ von Mises
34
+
35
+ General notes on the underlying Mersenne Twister core generator:
36
+
37
+ * The period is 2**19937-1.
38
+ * It is one of the most extensively tested generators in existence.
39
+ * The random() method is implemented in C, executes in a single Python step,
40
+ and is, therefore, threadsafe.
41
+
42
+ """
43
+
44
+ # Translated by Guido van Rossum from C source provided by
45
+ # Adrian Baddeley. Adapted by Raymond Hettinger for use with
46
+ # the Mersenne Twister and os.urandom() core generators.
47
+
48
+ from warnings import warn as _warn
49
+ from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
50
+ from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
51
+ from math import tau as TWOPI, floor as _floor, isfinite as _isfinite
52
+ from os import urandom as _urandom
53
+ from _collections_abc import Set as _Set, Sequence as _Sequence
54
+ from operator import index as _index
55
+ from itertools import accumulate as _accumulate, repeat as _repeat
56
+ from bisect import bisect as _bisect
57
+ import os as _os
58
+ import _random
59
+
60
+ try:
61
+ # hashlib is pretty heavy to load, try lean internal module first
62
+ from _sha512 import sha512 as _sha512
63
+ except ImportError:
64
+ # fallback to official implementation
65
+ from hashlib import sha512 as _sha512
66
+
67
+ __all__ = [
68
+ "Random",
69
+ "SystemRandom",
70
+ "betavariate",
71
+ "choice",
72
+ "choices",
73
+ "expovariate",
74
+ "gammavariate",
75
+ "gauss",
76
+ "getrandbits",
77
+ "getstate",
78
+ "lognormvariate",
79
+ "normalvariate",
80
+ "paretovariate",
81
+ "randbytes",
82
+ "randint",
83
+ "random",
84
+ "randrange",
85
+ "sample",
86
+ "seed",
87
+ "setstate",
88
+ "shuffle",
89
+ "triangular",
90
+ "uniform",
91
+ "vonmisesvariate",
92
+ "weibullvariate",
93
+ ]
94
+
95
+ NV_MAGICCONST = 4 * _exp(-0.5) / _sqrt(2.0)
96
+ LOG4 = _log(4.0)
97
+ SG_MAGICCONST = 1.0 + _log(4.5)
98
+ BPF = 53 # Number of bits in a float
99
+ RECIP_BPF = 2 ** -BPF
100
+ _ONE = 1
101
+
102
+
103
+ class Random(_random.Random):
104
+ """Random number generator base class used by bound module functions.
105
+
106
+ Used to instantiate instances of Random to get generators that don't
107
+ share state.
108
+
109
+ Class Random can also be subclassed if you want to use a different basic
110
+ generator of your own devising: in that case, override the following
111
+ methods: random(), seed(), getstate(), and setstate().
112
+ Optionally, implement a getrandbits() method so that randrange()
113
+ can cover arbitrarily large ranges.
114
+
115
+ """
116
+
117
+ VERSION = 3 # used by getstate/setstate
118
+
119
+ def __init__(self, x=None):
120
+ """Initialize an instance.
121
+
122
+ Optional argument x controls seeding, as for Random.seed().
123
+ """
124
+
125
+ self.seed(x)
126
+ self.gauss_next = None
127
+
128
+ def seed(self, a=None, version=2):
129
+ """Initialize internal state from a seed.
130
+
131
+ The only supported seed types are None, int, float,
132
+ str, bytes, and bytearray.
133
+
134
+ None or no argument seeds from current time or from an operating
135
+ system specific randomness source if available.
136
+
137
+ If *a* is an int, all bits are used.
138
+
139
+ For version 2 (the default), all of the bits are used if *a* is a str,
140
+ bytes, or bytearray. For version 1 (provided for reproducing random
141
+ sequences from older versions of Python), the algorithm for str and
142
+ bytes generates a narrower range of seeds.
143
+
144
+ """
145
+
146
+ if version == 1 and isinstance(a, (str, bytes)):
147
+ a = a.decode('latin-1') if isinstance(a, bytes) else a
148
+ x = ord(a[0]) << 7 if a else 0
149
+ for c in map(ord, a):
150
+ x = ((1000003 * x) ^ c) & 0xFFFFFFFFFFFFFFFF
151
+ x ^= len(a)
152
+ a = -2 if x == -1 else x
153
+
154
+ elif version == 2 and isinstance(a, (str, bytes, bytearray)):
155
+ if isinstance(a, str):
156
+ a = a.encode()
157
+ a = int.from_bytes(a + _sha512(a).digest(), 'big')
158
+
159
+ elif not isinstance(a, (type(None), int, float, str, bytes, bytearray)):
160
+ _warn('Seeding based on hashing is deprecated\n'
161
+ 'since Python 3.9 and will be removed in a subsequent '
162
+ 'version. The only \n'
163
+ 'supported seed types are: None, '
164
+ 'int, float, str, bytes, and bytearray.',
165
+ DeprecationWarning, 2)
166
+
167
+ super().seed(a)
168
+ self.gauss_next = None
169
+
170
+ def getstate(self):
171
+ """Return internal state; can be passed to setstate() later."""
172
+ return self.VERSION, super().getstate(), self.gauss_next
173
+
174
+ def setstate(self, state):
175
+ """Restore internal state from object returned by getstate()."""
176
+ version = state[0]
177
+ if version == 3:
178
+ version, internalstate, self.gauss_next = state
179
+ super().setstate(internalstate)
180
+ elif version == 2:
181
+ version, internalstate, self.gauss_next = state
182
+ # In version 2, the state was saved as signed ints, which causes
183
+ # inconsistencies between 32/64-bit systems. The state is
184
+ # really unsigned 32-bit ints, so we convert negative ints from
185
+ # version 2 to positive longs for version 3.
186
+ try:
187
+ internalstate = tuple(x % (2 ** 32) for x in internalstate)
188
+ except ValueError as e:
189
+ raise TypeError from e
190
+ super().setstate(internalstate)
191
+ else:
192
+ raise ValueError("state with version %s passed to "
193
+ "Random.setstate() of version %s" %
194
+ (version, self.VERSION))
195
+
196
+
197
+ ## -------------------------------------------------------
198
+ ## ---- Methods below this point do not need to be overridden or extended
199
+ ## ---- when subclassing for the purpose of using a different core generator.
200
+
201
+
202
+ ## -------------------- pickle support -------------------
203
+
204
+ # Issue 17489: Since __reduce__ was defined to fix #759889 this is no
205
+ # longer called; we leave it here because it has been here since random was
206
+ # rewritten back in 2001 and why risk breaking something.
207
+ def __getstate__(self): # for pickle
208
+ return self.getstate()
209
+
210
+ def __setstate__(self, state): # for pickle
211
+ self.setstate(state)
212
+
213
+ def __reduce__(self):
214
+ return self.__class__, (), self.getstate()
215
+
216
+
217
+ ## ---- internal support method for evenly distributed integers ----
218
+
219
+ def __init_subclass__(cls, /, **kwargs):
220
+ """Control how subclasses generate random integers.
221
+
222
+ The algorithm a subclass can use depends on the random() and/or
223
+ getrandbits() implementation available to it and determines
224
+ whether it can generate random integers from arbitrarily large
225
+ ranges.
226
+ """
227
+
228
+ for c in cls.__mro__:
229
+ if '_randbelow' in c.__dict__:
230
+ # just inherit it
231
+ break
232
+ if 'getrandbits' in c.__dict__:
233
+ cls._randbelow = cls._randbelow_with_getrandbits
234
+ break
235
+ if 'random' in c.__dict__:
236
+ cls._randbelow = cls._randbelow_without_getrandbits
237
+ break
238
+
239
+ def _randbelow_with_getrandbits(self, n):
240
+ "Return a random int in the range [0,n). Returns 0 if n==0."
241
+
242
+ if not n:
243
+ return 0
244
+ getrandbits = self.getrandbits
245
+ k = n.bit_length() # don't use (n-1) here because n can be 1
246
+ r = getrandbits(k) # 0 <= r < 2**k
247
+ while r >= n:
248
+ r = getrandbits(k)
249
+ return r
250
+
251
+ def _randbelow_without_getrandbits(self, n, maxsize=1<<BPF):
252
+ """Return a random int in the range [0,n). Returns 0 if n==0.
253
+
254
+ The implementation does not use getrandbits, but only random.
255
+ """
256
+
257
+ random = self.random
258
+ if n >= maxsize:
259
+ _warn("Underlying random() generator does not supply \n"
260
+ "enough bits to choose from a population range this large.\n"
261
+ "To remove the range limitation, add a getrandbits() method.")
262
+ return _floor(random() * n)
263
+ if n == 0:
264
+ return 0
265
+ rem = maxsize % n
266
+ limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0
267
+ r = random()
268
+ while r >= limit:
269
+ r = random()
270
+ return _floor(r * maxsize) % n
271
+
272
+ _randbelow = _randbelow_with_getrandbits
273
+
274
+
275
+ ## --------------------------------------------------------
276
+ ## ---- Methods below this point generate custom distributions
277
+ ## ---- based on the methods defined above. They do not
278
+ ## ---- directly touch the underlying generator and only
279
+ ## ---- access randomness through the methods: random(),
280
+ ## ---- getrandbits(), or _randbelow().
281
+
282
+
283
+ ## -------------------- bytes methods ---------------------
284
+
285
+ def randbytes(self, n):
286
+ """Generate n random bytes."""
287
+ return self.getrandbits(n * 8).to_bytes(n, 'little')
288
+
289
+
290
+ ## -------------------- integer methods -------------------
291
+
292
+ def randrange(self, start, stop=None, step=_ONE):
293
+ """Choose a random item from range(start, stop[, step]).
294
+
295
+ This fixes the problem with randint() which includes the
296
+ endpoint; in Python this is usually not what you want.
297
+
298
+ """
299
+
300
+ # This code is a bit messy to make it fast for the
301
+ # common case while still doing adequate error checking.
302
+ try:
303
+ istart = _index(start)
304
+ except TypeError:
305
+ istart = int(start)
306
+ if istart != start:
307
+ _warn('randrange() will raise TypeError in the future',
308
+ DeprecationWarning, 2)
309
+ raise ValueError("non-integer arg 1 for randrange()")
310
+ _warn('non-integer arguments to randrange() have been deprecated '
311
+ 'since Python 3.10 and will be removed in a subsequent '
312
+ 'version',
313
+ DeprecationWarning, 2)
314
+ if stop is None:
315
+ # We don't check for "step != 1" because it hasn't been
316
+ # type checked and converted to an integer yet.
317
+ if step is not _ONE:
318
+ raise TypeError('Missing a non-None stop argument')
319
+ if istart > 0:
320
+ return self._randbelow(istart)
321
+ raise ValueError("empty range for randrange()")
322
+
323
+ # stop argument supplied.
324
+ try:
325
+ istop = _index(stop)
326
+ except TypeError:
327
+ istop = int(stop)
328
+ if istop != stop:
329
+ _warn('randrange() will raise TypeError in the future',
330
+ DeprecationWarning, 2)
331
+ raise ValueError("non-integer stop for randrange()")
332
+ _warn('non-integer arguments to randrange() have been deprecated '
333
+ 'since Python 3.10 and will be removed in a subsequent '
334
+ 'version',
335
+ DeprecationWarning, 2)
336
+ width = istop - istart
337
+ try:
338
+ istep = _index(step)
339
+ except TypeError:
340
+ istep = int(step)
341
+ if istep != step:
342
+ _warn('randrange() will raise TypeError in the future',
343
+ DeprecationWarning, 2)
344
+ raise ValueError("non-integer step for randrange()")
345
+ _warn('non-integer arguments to randrange() have been deprecated '
346
+ 'since Python 3.10 and will be removed in a subsequent '
347
+ 'version',
348
+ DeprecationWarning, 2)
349
+ # Fast path.
350
+ if istep == 1:
351
+ if width > 0:
352
+ return istart + self._randbelow(width)
353
+ raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
354
+
355
+ # Non-unit step argument supplied.
356
+ if istep > 0:
357
+ n = (width + istep - 1) // istep
358
+ elif istep < 0:
359
+ n = (width + istep + 1) // istep
360
+ else:
361
+ raise ValueError("zero step for randrange()")
362
+ if n <= 0:
363
+ raise ValueError("empty range for randrange()")
364
+ return istart + istep * self._randbelow(n)
365
+
366
+ def randint(self, a, b):
367
+ """Return random integer in range [a, b], including both end points.
368
+ """
369
+
370
+ return self.randrange(a, b+1)
371
+
372
+
373
+ ## -------------------- sequence methods -------------------
374
+
375
+ def choice(self, seq):
376
+ """Choose a random element from a non-empty sequence."""
377
+ # raises IndexError if seq is empty
378
+ return seq[self._randbelow(len(seq))]
379
+
380
+ def shuffle(self, x, random=None):
381
+ """Shuffle list x in place, and return None.
382
+
383
+ Optional argument random is a 0-argument function returning a
384
+ random float in [0.0, 1.0); if it is the default None, the
385
+ standard random.random will be used.
386
+
387
+ """
388
+
389
+ if random is None:
390
+ randbelow = self._randbelow
391
+ for i in reversed(range(1, len(x))):
392
+ # pick an element in x[:i+1] with which to exchange x[i]
393
+ j = randbelow(i + 1)
394
+ x[i], x[j] = x[j], x[i]
395
+ else:
396
+ _warn('The *random* parameter to shuffle() has been deprecated\n'
397
+ 'since Python 3.9 and will be removed in a subsequent '
398
+ 'version.',
399
+ DeprecationWarning, 2)
400
+ floor = _floor
401
+ for i in reversed(range(1, len(x))):
402
+ # pick an element in x[:i+1] with which to exchange x[i]
403
+ j = floor(random() * (i + 1))
404
+ x[i], x[j] = x[j], x[i]
405
+
406
+ def sample(self, population, k, *, counts=None):
407
+ """Chooses k unique random elements from a population sequence or set.
408
+
409
+ Returns a new list containing elements from the population while
410
+ leaving the original population unchanged. The resulting list is
411
+ in selection order so that all sub-slices will also be valid random
412
+ samples. This allows raffle winners (the sample) to be partitioned
413
+ into grand prize and second place winners (the subslices).
414
+
415
+ Members of the population need not be hashable or unique. If the
416
+ population contains repeats, then each occurrence is a possible
417
+ selection in the sample.
418
+
419
+ Repeated elements can be specified one at a time or with the optional
420
+ counts parameter. For example:
421
+
422
+ sample(['red', 'blue'], counts=[4, 2], k=5)
423
+
424
+ is equivalent to:
425
+
426
+ sample(['red', 'red', 'red', 'red', 'blue', 'blue'], k=5)
427
+
428
+ To choose a sample from a range of integers, use range() for the
429
+ population argument. This is especially fast and space efficient
430
+ for sampling from a large population:
431
+
432
+ sample(range(10000000), 60)
433
+
434
+ """
435
+
436
+ # Sampling without replacement entails tracking either potential
437
+ # selections (the pool) in a list or previous selections in a set.
438
+
439
+ # When the number of selections is small compared to the
440
+ # population, then tracking selections is efficient, requiring
441
+ # only a small set and an occasional reselection. For
442
+ # a larger number of selections, the pool tracking method is
443
+ # preferred since the list takes less space than the
444
+ # set and it doesn't suffer from frequent reselections.
445
+
446
+ # The number of calls to _randbelow() is kept at or near k, the
447
+ # theoretical minimum. This is important because running time
448
+ # is dominated by _randbelow() and because it extracts the
449
+ # least entropy from the underlying random number generators.
450
+
451
+ # Memory requirements are kept to the smaller of a k-length
452
+ # set or an n-length list.
453
+
454
+ # There are other sampling algorithms that do not require
455
+ # auxiliary memory, but they were rejected because they made
456
+ # too many calls to _randbelow(), making them slower and
457
+ # causing them to eat more entropy than necessary.
458
+
459
+ if not isinstance(population, _Sequence):
460
+ if isinstance(population, _Set):
461
+ _warn('Sampling from a set deprecated\n'
462
+ 'since Python 3.9 and will be removed in a subsequent version.',
463
+ DeprecationWarning, 2)
464
+ population = tuple(population)
465
+ else:
466
+ raise TypeError("Population must be a sequence. For dicts or sets, use sorted(d).")
467
+ n = len(population)
468
+ if counts is not None:
469
+ cum_counts = list(_accumulate(counts))
470
+ if len(cum_counts) != n:
471
+ raise ValueError('The number of counts does not match the population')
472
+ total = cum_counts.pop()
473
+ if not isinstance(total, int):
474
+ raise TypeError('Counts must be integers')
475
+ if total <= 0:
476
+ raise ValueError('Total of counts must be greater than zero')
477
+ selections = self.sample(range(total), k=k)
478
+ bisect = _bisect
479
+ return [population[bisect(cum_counts, s)] for s in selections]
480
+ randbelow = self._randbelow
481
+ if not 0 <= k <= n:
482
+ raise ValueError("Sample larger than population or is negative")
483
+ result = [None] * k
484
+ setsize = 21 # size of a small set minus size of an empty list
485
+ if k > 5:
486
+ setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets
487
+ if n <= setsize:
488
+ # An n-length list is smaller than a k-length set.
489
+ # Invariant: non-selected at pool[0 : n-i]
490
+ pool = list(population)
491
+ for i in range(k):
492
+ j = randbelow(n - i)
493
+ result[i] = pool[j]
494
+ pool[j] = pool[n - i - 1] # move non-selected item into vacancy
495
+ else:
496
+ selected = set()
497
+ selected_add = selected.add
498
+ for i in range(k):
499
+ j = randbelow(n)
500
+ while j in selected:
501
+ j = randbelow(n)
502
+ selected_add(j)
503
+ result[i] = population[j]
504
+ return result
505
+
506
+ def choices(self, population, weights=None, *, cum_weights=None, k=1):
507
+ """Return a k sized list of population elements chosen with replacement.
508
+
509
+ If the relative weights or cumulative weights are not specified,
510
+ the selections are made with equal probability.
511
+
512
+ """
513
+ random = self.random
514
+ n = len(population)
515
+ if cum_weights is None:
516
+ if weights is None:
517
+ floor = _floor
518
+ n += 0.0 # convert to float for a small speed improvement
519
+ return [population[floor(random() * n)] for i in _repeat(None, k)]
520
+ try:
521
+ cum_weights = list(_accumulate(weights))
522
+ except TypeError:
523
+ if not isinstance(weights, int):
524
+ raise
525
+ k = weights
526
+ raise TypeError(
527
+ f'The number of choices must be a keyword argument: {k=}'
528
+ ) from None
529
+ elif weights is not None:
530
+ raise TypeError('Cannot specify both weights and cumulative weights')
531
+ if len(cum_weights) != n:
532
+ raise ValueError('The number of weights does not match the population')
533
+ total = cum_weights[-1] + 0.0 # convert to float
534
+ if total <= 0.0:
535
+ raise ValueError('Total of weights must be greater than zero')
536
+ if not _isfinite(total):
537
+ raise ValueError('Total of weights must be finite')
538
+ bisect = _bisect
539
+ hi = n - 1
540
+ return [population[bisect(cum_weights, random() * total, 0, hi)]
541
+ for i in _repeat(None, k)]
542
+
543
+
544
+ ## -------------------- real-valued distributions -------------------
545
+
546
+ def uniform(self, a, b):
547
+ "Get a random number in the range [a, b) or [a, b] depending on rounding."
548
+ return a + (b - a) * self.random()
549
+
550
+ def triangular(self, low=0.0, high=1.0, mode=None):
551
+ """Triangular distribution.
552
+
553
+ Continuous distribution bounded by given lower and upper limits,
554
+ and having a given mode value in-between.
555
+
556
+ http://en.wikipedia.org/wiki/Triangular_distribution
557
+
558
+ """
559
+ u = self.random()
560
+ try:
561
+ c = 0.5 if mode is None else (mode - low) / (high - low)
562
+ except ZeroDivisionError:
563
+ return low
564
+ if u > c:
565
+ u = 1.0 - u
566
+ c = 1.0 - c
567
+ low, high = high, low
568
+ return low + (high - low) * _sqrt(u * c)
569
+
570
+ def normalvariate(self, mu, sigma):
571
+ """Normal distribution.
572
+
573
+ mu is the mean, and sigma is the standard deviation.
574
+
575
+ """
576
+ # Uses Kinderman and Monahan method. Reference: Kinderman,
577
+ # A.J. and Monahan, J.F., "Computer generation of random
578
+ # variables using the ratio of uniform deviates", ACM Trans
579
+ # Math Software, 3, (1977), pp257-260.
580
+
581
+ random = self.random
582
+ while True:
583
+ u1 = random()
584
+ u2 = 1.0 - random()
585
+ z = NV_MAGICCONST * (u1 - 0.5) / u2
586
+ zz = z * z / 4.0
587
+ if zz <= -_log(u2):
588
+ break
589
+ return mu + z * sigma
590
+
591
+ def gauss(self, mu, sigma):
592
+ """Gaussian distribution.
593
+
594
+ mu is the mean, and sigma is the standard deviation. This is
595
+ slightly faster than the normalvariate() function.
596
+
597
+ Not thread-safe without a lock around calls.
598
+
599
+ """
600
+ # When x and y are two variables from [0, 1), uniformly
601
+ # distributed, then
602
+ #
603
+ # cos(2*pi*x)*sqrt(-2*log(1-y))
604
+ # sin(2*pi*x)*sqrt(-2*log(1-y))
605
+ #
606
+ # are two *independent* variables with normal distribution
607
+ # (mu = 0, sigma = 1).
608
+ # (Lambert Meertens)
609
+ # (corrected version; bug discovered by Mike Miller, fixed by LM)
610
+
611
+ # Multithreading note: When two threads call this function
612
+ # simultaneously, it is possible that they will receive the
613
+ # same return value. The window is very small though. To
614
+ # avoid this, you have to use a lock around all calls. (I
615
+ # didn't want to slow this down in the serial case by using a
616
+ # lock here.)
617
+
618
+ random = self.random
619
+ z = self.gauss_next
620
+ self.gauss_next = None
621
+ if z is None:
622
+ x2pi = random() * TWOPI
623
+ g2rad = _sqrt(-2.0 * _log(1.0 - random()))
624
+ z = _cos(x2pi) * g2rad
625
+ self.gauss_next = _sin(x2pi) * g2rad
626
+
627
+ return mu + z * sigma
628
+
629
+ def lognormvariate(self, mu, sigma):
630
+ """Log normal distribution.
631
+
632
+ If you take the natural logarithm of this distribution, you'll get a
633
+ normal distribution with mean mu and standard deviation sigma.
634
+ mu can have any value, and sigma must be greater than zero.
635
+
636
+ """
637
+ return _exp(self.normalvariate(mu, sigma))
638
+
639
+ def expovariate(self, lambd):
640
+ """Exponential distribution.
641
+
642
+ lambd is 1.0 divided by the desired mean. It should be
643
+ nonzero. (The parameter would be called "lambda", but that is
644
+ a reserved word in Python.) Returned values range from 0 to
645
+ positive infinity if lambd is positive, and from negative
646
+ infinity to 0 if lambd is negative.
647
+
648
+ """
649
+ # lambd: rate lambd = 1/mean
650
+ # ('lambda' is a Python reserved word)
651
+
652
+ # we use 1-random() instead of random() to preclude the
653
+ # possibility of taking the log of zero.
654
+ return -_log(1.0 - self.random()) / lambd
655
+
656
+ def vonmisesvariate(self, mu, kappa):
657
+ """Circular data distribution.
658
+
659
+ mu is the mean angle, expressed in radians between 0 and 2*pi, and
660
+ kappa is the concentration parameter, which must be greater than or
661
+ equal to zero. If kappa is equal to zero, this distribution reduces
662
+ to a uniform random angle over the range 0 to 2*pi.
663
+
664
+ """
665
+ # Based upon an algorithm published in: Fisher, N.I.,
666
+ # "Statistical Analysis of Circular Data", Cambridge
667
+ # University Press, 1993.
668
+
669
+ # Thanks to Magnus Kessler for a correction to the
670
+ # implementation of step 4.
671
+
672
+ random = self.random
673
+ if kappa <= 1e-6:
674
+ return TWOPI * random()
675
+
676
+ s = 0.5 / kappa
677
+ r = s + _sqrt(1.0 + s * s)
678
+
679
+ while True:
680
+ u1 = random()
681
+ z = _cos(_pi * u1)
682
+
683
+ d = z / (r + z)
684
+ u2 = random()
685
+ if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d):
686
+ break
687
+
688
+ q = 1.0 / r
689
+ f = (q + z) / (1.0 + q * z)
690
+ u3 = random()
691
+ if u3 > 0.5:
692
+ theta = (mu + _acos(f)) % TWOPI
693
+ else:
694
+ theta = (mu - _acos(f)) % TWOPI
695
+
696
+ return theta
697
+
698
+ def gammavariate(self, alpha, beta):
699
+ """Gamma distribution. Not the gamma function!
700
+
701
+ Conditions on the parameters are alpha > 0 and beta > 0.
702
+
703
+ The probability distribution function is:
704
+
705
+ x ** (alpha - 1) * math.exp(-x / beta)
706
+ pdf(x) = --------------------------------------
707
+ math.gamma(alpha) * beta ** alpha
708
+
709
+ """
710
+ # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
711
+
712
+ # Warning: a few older sources define the gamma distribution in terms
713
+ # of alpha > -1.0
714
+ if alpha <= 0.0 or beta <= 0.0:
715
+ raise ValueError('gammavariate: alpha and beta must be > 0.0')
716
+
717
+ random = self.random
718
+ if alpha > 1.0:
719
+
720
+ # Uses R.C.H. Cheng, "The generation of Gamma
721
+ # variables with non-integral shape parameters",
722
+ # Applied Statistics, (1977), 26, No. 1, p71-74
723
+
724
+ ainv = _sqrt(2.0 * alpha - 1.0)
725
+ bbb = alpha - LOG4
726
+ ccc = alpha + ainv
727
+
728
+ while True:
729
+ u1 = random()
730
+ if not 1e-7 < u1 < 0.9999999:
731
+ continue
732
+ u2 = 1.0 - random()
733
+ v = _log(u1 / (1.0 - u1)) / ainv
734
+ x = alpha * _exp(v)
735
+ z = u1 * u1 * u2
736
+ r = bbb + ccc * v - x
737
+ if r + SG_MAGICCONST - 4.5 * z >= 0.0 or r >= _log(z):
738
+ return x * beta
739
+
740
+ elif alpha == 1.0:
741
+ # expovariate(1/beta)
742
+ return -_log(1.0 - random()) * beta
743
+
744
+ else:
745
+ # alpha is between 0 and 1 (exclusive)
746
+ # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
747
+ while True:
748
+ u = random()
749
+ b = (_e + alpha) / _e
750
+ p = b * u
751
+ if p <= 1.0:
752
+ x = p ** (1.0 / alpha)
753
+ else:
754
+ x = -_log((b - p) / alpha)
755
+ u1 = random()
756
+ if p > 1.0:
757
+ if u1 <= x ** (alpha - 1.0):
758
+ break
759
+ elif u1 <= _exp(-x):
760
+ break
761
+ return x * beta
762
+
763
+ def betavariate(self, alpha, beta):
764
+ """Beta distribution.
765
+
766
+ Conditions on the parameters are alpha > 0 and beta > 0.
767
+ Returned values range between 0 and 1.
768
+
769
+ """
770
+ ## See
771
+ ## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html
772
+ ## for Ivan Frohne's insightful analysis of why the original implementation:
773
+ ##
774
+ ## def betavariate(self, alpha, beta):
775
+ ## # Discrete Event Simulation in C, pp 87-88.
776
+ ##
777
+ ## y = self.expovariate(alpha)
778
+ ## z = self.expovariate(1.0/beta)
779
+ ## return z/(y+z)
780
+ ##
781
+ ## was dead wrong, and how it probably got that way.
782
+
783
+ # This version due to Janne Sinkkonen, and matches all the std
784
+ # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
785
+ y = self.gammavariate(alpha, 1.0)
786
+ if y:
787
+ return y / (y + self.gammavariate(beta, 1.0))
788
+ return 0.0
789
+
790
+ def paretovariate(self, alpha):
791
+ """Pareto distribution. alpha is the shape parameter."""
792
+ # Jain, pg. 495
793
+
794
+ u = 1.0 - self.random()
795
+ return u ** (-1.0 / alpha)
796
+
797
+ def weibullvariate(self, alpha, beta):
798
+ """Weibull distribution.
799
+
800
+ alpha is the scale parameter and beta is the shape parameter.
801
+
802
+ """
803
+ # Jain, pg. 499; bug fix courtesy Bill Arms
804
+
805
+ u = 1.0 - self.random()
806
+ return alpha * (-_log(u)) ** (1.0 / beta)
807
+
808
+
809
+ ## ------------------------------------------------------------------
810
+ ## --------------- Operating System Random Source ------------------
811
+
812
+
813
+ class SystemRandom(Random):
814
+ """Alternate random number generator using sources provided
815
+ by the operating system (such as /dev/urandom on Unix or
816
+ CryptGenRandom on Windows).
817
+
818
+ Not available on all systems (see os.urandom() for details).
819
+
820
+ """
821
+
822
+ def random(self):
823
+ """Get the next random number in the range [0.0, 1.0)."""
824
+ return (int.from_bytes(_urandom(7), 'big') >> 3) * RECIP_BPF
825
+
826
+ def getrandbits(self, k):
827
+ """getrandbits(k) -> x. Generates an int with k random bits."""
828
+ if k < 0:
829
+ raise ValueError('number of bits must be non-negative')
830
+ numbytes = (k + 7) // 8 # bits / 8 and rounded up
831
+ x = int.from_bytes(_urandom(numbytes), 'big')
832
+ return x >> (numbytes * 8 - k) # trim excess bits
833
+
834
+ def randbytes(self, n):
835
+ """Generate n random bytes."""
836
+ # os.urandom(n) fails with ValueError for n < 0
837
+ # and returns an empty bytes string for n == 0.
838
+ return _urandom(n)
839
+
840
+ def seed(self, *args, **kwds):
841
+ "Stub method. Not used for a system random number generator."
842
+ return None
843
+
844
+ def _notimplemented(self, *args, **kwds):
845
+ "Method should not be called for a system random number generator."
846
+ raise NotImplementedError('System entropy source does not have state.')
847
+ getstate = setstate = _notimplemented
848
+
849
+
850
+ # ----------------------------------------------------------------------
851
+ # Create one instance, seeded from current time, and export its methods
852
+ # as module-level functions. The functions share state across all uses
853
+ # (both in the user's code and in the Python libraries), but that's fine
854
+ # for most programs and is easier for the casual user than making them
855
+ # instantiate their own Random() instance.
856
+
857
+ _inst = Random()
858
+ seed = _inst.seed
859
+ random = _inst.random
860
+ uniform = _inst.uniform
861
+ triangular = _inst.triangular
862
+ randint = _inst.randint
863
+ choice = _inst.choice
864
+ randrange = _inst.randrange
865
+ sample = _inst.sample
866
+ shuffle = _inst.shuffle
867
+ choices = _inst.choices
868
+ normalvariate = _inst.normalvariate
869
+ lognormvariate = _inst.lognormvariate
870
+ expovariate = _inst.expovariate
871
+ vonmisesvariate = _inst.vonmisesvariate
872
+ gammavariate = _inst.gammavariate
873
+ gauss = _inst.gauss
874
+ betavariate = _inst.betavariate
875
+ paretovariate = _inst.paretovariate
876
+ weibullvariate = _inst.weibullvariate
877
+ getstate = _inst.getstate
878
+ setstate = _inst.setstate
879
+ getrandbits = _inst.getrandbits
880
+ randbytes = _inst.randbytes
881
+
882
+
883
+ ## ------------------------------------------------------
884
+ ## ----------------- test program -----------------------
885
+
886
+ def _test_generator(n, func, args):
887
+ from statistics import stdev, fmean as mean
888
+ from time import perf_counter
889
+
890
+ t0 = perf_counter()
891
+ data = [func(*args) for i in _repeat(None, n)]
892
+ t1 = perf_counter()
893
+
894
+ xbar = mean(data)
895
+ sigma = stdev(data, xbar)
896
+ low = min(data)
897
+ high = max(data)
898
+
899
+ print(f'{t1 - t0:.3f} sec, {n} times {func.__name__}')
900
+ print('avg %g, stddev %g, min %g, max %g\n' % (xbar, sigma, low, high))
901
+
902
+
903
+ def _test(N=2000):
904
+ _test_generator(N, random, ())
905
+ _test_generator(N, normalvariate, (0.0, 1.0))
906
+ _test_generator(N, lognormvariate, (0.0, 1.0))
907
+ _test_generator(N, vonmisesvariate, (0.0, 1.0))
908
+ _test_generator(N, gammavariate, (0.01, 1.0))
909
+ _test_generator(N, gammavariate, (0.1, 1.0))
910
+ _test_generator(N, gammavariate, (0.1, 2.0))
911
+ _test_generator(N, gammavariate, (0.5, 1.0))
912
+ _test_generator(N, gammavariate, (0.9, 1.0))
913
+ _test_generator(N, gammavariate, (1.0, 1.0))
914
+ _test_generator(N, gammavariate, (2.0, 1.0))
915
+ _test_generator(N, gammavariate, (20.0, 1.0))
916
+ _test_generator(N, gammavariate, (200.0, 1.0))
917
+ _test_generator(N, gauss, (0.0, 1.0))
918
+ _test_generator(N, betavariate, (3.0, 3.0))
919
+ _test_generator(N, triangular, (0.0, 1.0, 1.0 / 3.0))
920
+
921
+
922
+ ## ------------------------------------------------------
923
+ ## ------------------ fork support ---------------------
924
+
925
+ if hasattr(_os, "fork"):
926
+ _os.register_at_fork(after_in_child=_inst.seed)
927
+
928
+
929
+ if __name__ == '__main__':
930
+ _test()
lib/python3.10/re.py ADDED
@@ -0,0 +1,383 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Secret Labs' Regular Expression Engine
3
+ #
4
+ # re-compatible interface for the sre matching engine
5
+ #
6
+ # Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved.
7
+ #
8
+ # This version of the SRE library can be redistributed under CNRI's
9
+ # Python 1.6 license. For any other use, please contact Secret Labs
10
+ # AB (info@pythonware.com).
11
+ #
12
+ # Portions of this engine have been developed in cooperation with
13
+ # CNRI. Hewlett-Packard provided funding for 1.6 integration and
14
+ # other compatibility work.
15
+ #
16
+
17
+ r"""Support for regular expressions (RE).
18
+
19
+ This module provides regular expression matching operations similar to
20
+ those found in Perl. It supports both 8-bit and Unicode strings; both
21
+ the pattern and the strings being processed can contain null bytes and
22
+ characters outside the US ASCII range.
23
+
24
+ Regular expressions can contain both special and ordinary characters.
25
+ Most ordinary characters, like "A", "a", or "0", are the simplest
26
+ regular expressions; they simply match themselves. You can
27
+ concatenate ordinary characters, so last matches the string 'last'.
28
+
29
+ The special characters are:
30
+ "." Matches any character except a newline.
31
+ "^" Matches the start of the string.
32
+ "$" Matches the end of the string or just before the newline at
33
+ the end of the string.
34
+ "*" Matches 0 or more (greedy) repetitions of the preceding RE.
35
+ Greedy means that it will match as many repetitions as possible.
36
+ "+" Matches 1 or more (greedy) repetitions of the preceding RE.
37
+ "?" Matches 0 or 1 (greedy) of the preceding RE.
38
+ *?,+?,?? Non-greedy versions of the previous three special characters.
39
+ {m,n} Matches from m to n repetitions of the preceding RE.
40
+ {m,n}? Non-greedy version of the above.
41
+ "\\" Either escapes special characters or signals a special sequence.
42
+ [] Indicates a set of characters.
43
+ A "^" as the first character indicates a complementing set.
44
+ "|" A|B, creates an RE that will match either A or B.
45
+ (...) Matches the RE inside the parentheses.
46
+ The contents can be retrieved or matched later in the string.
47
+ (?aiLmsux) The letters set the corresponding flags defined below.
48
+ (?:...) Non-grouping version of regular parentheses.
49
+ (?P<name>...) The substring matched by the group is accessible by name.
50
+ (?P=name) Matches the text matched earlier by the group named name.
51
+ (?#...) A comment; ignored.
52
+ (?=...) Matches if ... matches next, but doesn't consume the string.
53
+ (?!...) Matches if ... doesn't match next.
54
+ (?<=...) Matches if preceded by ... (must be fixed length).
55
+ (?<!...) Matches if not preceded by ... (must be fixed length).
56
+ (?(id/name)yes|no) Matches yes pattern if the group with id/name matched,
57
+ the (optional) no pattern otherwise.
58
+
59
+ The special sequences consist of "\\" and a character from the list
60
+ below. If the ordinary character is not on the list, then the
61
+ resulting RE will match the second character.
62
+ \number Matches the contents of the group of the same number.
63
+ \A Matches only at the start of the string.
64
+ \Z Matches only at the end of the string.
65
+ \b Matches the empty string, but only at the start or end of a word.
66
+ \B Matches the empty string, but not at the start or end of a word.
67
+ \d Matches any decimal digit; equivalent to the set [0-9] in
68
+ bytes patterns or string patterns with the ASCII flag.
69
+ In string patterns without the ASCII flag, it will match the whole
70
+ range of Unicode digits.
71
+ \D Matches any non-digit character; equivalent to [^\d].
72
+ \s Matches any whitespace character; equivalent to [ \t\n\r\f\v] in
73
+ bytes patterns or string patterns with the ASCII flag.
74
+ In string patterns without the ASCII flag, it will match the whole
75
+ range of Unicode whitespace characters.
76
+ \S Matches any non-whitespace character; equivalent to [^\s].
77
+ \w Matches any alphanumeric character; equivalent to [a-zA-Z0-9_]
78
+ in bytes patterns or string patterns with the ASCII flag.
79
+ In string patterns without the ASCII flag, it will match the
80
+ range of Unicode alphanumeric characters (letters plus digits
81
+ plus underscore).
82
+ With LOCALE, it will match the set [0-9_] plus characters defined
83
+ as letters for the current locale.
84
+ \W Matches the complement of \w.
85
+ \\ Matches a literal backslash.
86
+
87
+ This module exports the following functions:
88
+ match Match a regular expression pattern to the beginning of a string.
89
+ fullmatch Match a regular expression pattern to all of a string.
90
+ search Search a string for the presence of a pattern.
91
+ sub Substitute occurrences of a pattern found in a string.
92
+ subn Same as sub, but also return the number of substitutions made.
93
+ split Split a string by the occurrences of a pattern.
94
+ findall Find all occurrences of a pattern in a string.
95
+ finditer Return an iterator yielding a Match object for each match.
96
+ compile Compile a pattern into a Pattern object.
97
+ purge Clear the regular expression cache.
98
+ escape Backslash all non-alphanumerics in a string.
99
+
100
+ Each function other than purge and escape can take an optional 'flags' argument
101
+ consisting of one or more of the following module constants, joined by "|".
102
+ A, L, and U are mutually exclusive.
103
+ A ASCII For string patterns, make \w, \W, \b, \B, \d, \D
104
+ match the corresponding ASCII character categories
105
+ (rather than the whole Unicode categories, which is the
106
+ default).
107
+ For bytes patterns, this flag is the only available
108
+ behaviour and needn't be specified.
109
+ I IGNORECASE Perform case-insensitive matching.
110
+ L LOCALE Make \w, \W, \b, \B, dependent on the current locale.
111
+ M MULTILINE "^" matches the beginning of lines (after a newline)
112
+ as well as the string.
113
+ "$" matches the end of lines (before a newline) as well
114
+ as the end of the string.
115
+ S DOTALL "." matches any character at all, including the newline.
116
+ X VERBOSE Ignore whitespace and comments for nicer looking RE's.
117
+ U UNICODE For compatibility only. Ignored for string patterns (it
118
+ is the default), and forbidden for bytes patterns.
119
+
120
+ This module also defines an exception 'error'.
121
+
122
+ """
123
+
124
+ import enum
125
+ import sre_compile
126
+ import sre_parse
127
+ import functools
128
+ try:
129
+ import _locale
130
+ except ImportError:
131
+ _locale = None
132
+
133
+
134
+ # public symbols
135
+ __all__ = [
136
+ "match", "fullmatch", "search", "sub", "subn", "split",
137
+ "findall", "finditer", "compile", "purge", "template", "escape",
138
+ "error", "Pattern", "Match", "A", "I", "L", "M", "S", "X", "U",
139
+ "ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",
140
+ "UNICODE",
141
+ ]
142
+
143
+ __version__ = "2.2.1"
144
+
145
+ class RegexFlag(enum.IntFlag):
146
+ ASCII = A = sre_compile.SRE_FLAG_ASCII # assume ascii "locale"
147
+ IGNORECASE = I = sre_compile.SRE_FLAG_IGNORECASE # ignore case
148
+ LOCALE = L = sre_compile.SRE_FLAG_LOCALE # assume current 8-bit locale
149
+ UNICODE = U = sre_compile.SRE_FLAG_UNICODE # assume unicode "locale"
150
+ MULTILINE = M = sre_compile.SRE_FLAG_MULTILINE # make anchors look for newline
151
+ DOTALL = S = sre_compile.SRE_FLAG_DOTALL # make dot match newline
152
+ VERBOSE = X = sre_compile.SRE_FLAG_VERBOSE # ignore whitespace and comments
153
+ # sre extensions (experimental, don't rely on these)
154
+ TEMPLATE = T = sre_compile.SRE_FLAG_TEMPLATE # disable backtracking
155
+ DEBUG = sre_compile.SRE_FLAG_DEBUG # dump pattern after compilation
156
+
157
+ def __repr__(self):
158
+ if self._name_ is not None:
159
+ return f're.{self._name_}'
160
+ value = self._value_
161
+ members = []
162
+ negative = value < 0
163
+ if negative:
164
+ value = ~value
165
+ for m in self.__class__:
166
+ if value & m._value_:
167
+ value &= ~m._value_
168
+ members.append(f're.{m._name_}')
169
+ if value:
170
+ members.append(hex(value))
171
+ res = '|'.join(members)
172
+ if negative:
173
+ if len(members) > 1:
174
+ res = f'~({res})'
175
+ else:
176
+ res = f'~{res}'
177
+ return res
178
+ __str__ = object.__str__
179
+ globals().update(RegexFlag.__members__)
180
+
181
+ # sre exception
182
+ error = sre_compile.error
183
+
184
+ # --------------------------------------------------------------------
185
+ # public interface
186
+
187
+ def match(pattern, string, flags=0):
188
+ """Try to apply the pattern at the start of the string, returning
189
+ a Match object, or None if no match was found."""
190
+ return _compile(pattern, flags).match(string)
191
+
192
+ def fullmatch(pattern, string, flags=0):
193
+ """Try to apply the pattern to all of the string, returning
194
+ a Match object, or None if no match was found."""
195
+ return _compile(pattern, flags).fullmatch(string)
196
+
197
+ def search(pattern, string, flags=0):
198
+ """Scan through string looking for a match to the pattern, returning
199
+ a Match object, or None if no match was found."""
200
+ return _compile(pattern, flags).search(string)
201
+
202
+ def sub(pattern, repl, string, count=0, flags=0):
203
+ """Return the string obtained by replacing the leftmost
204
+ non-overlapping occurrences of the pattern in string by the
205
+ replacement repl. repl can be either a string or a callable;
206
+ if a string, backslash escapes in it are processed. If it is
207
+ a callable, it's passed the Match object and must return
208
+ a replacement string to be used."""
209
+ return _compile(pattern, flags).sub(repl, string, count)
210
+
211
+ def subn(pattern, repl, string, count=0, flags=0):
212
+ """Return a 2-tuple containing (new_string, number).
213
+ new_string is the string obtained by replacing the leftmost
214
+ non-overlapping occurrences of the pattern in the source
215
+ string by the replacement repl. number is the number of
216
+ substitutions that were made. repl can be either a string or a
217
+ callable; if a string, backslash escapes in it are processed.
218
+ If it is a callable, it's passed the Match object and must
219
+ return a replacement string to be used."""
220
+ return _compile(pattern, flags).subn(repl, string, count)
221
+
222
+ def split(pattern, string, maxsplit=0, flags=0):
223
+ """Split the source string by the occurrences of the pattern,
224
+ returning a list containing the resulting substrings. If
225
+ capturing parentheses are used in pattern, then the text of all
226
+ groups in the pattern are also returned as part of the resulting
227
+ list. If maxsplit is nonzero, at most maxsplit splits occur,
228
+ and the remainder of the string is returned as the final element
229
+ of the list."""
230
+ return _compile(pattern, flags).split(string, maxsplit)
231
+
232
+ def findall(pattern, string, flags=0):
233
+ """Return a list of all non-overlapping matches in the string.
234
+
235
+ If one or more capturing groups are present in the pattern, return
236
+ a list of groups; this will be a list of tuples if the pattern
237
+ has more than one group.
238
+
239
+ Empty matches are included in the result."""
240
+ return _compile(pattern, flags).findall(string)
241
+
242
+ def finditer(pattern, string, flags=0):
243
+ """Return an iterator over all non-overlapping matches in the
244
+ string. For each match, the iterator returns a Match object.
245
+
246
+ Empty matches are included in the result."""
247
+ return _compile(pattern, flags).finditer(string)
248
+
249
+ def compile(pattern, flags=0):
250
+ "Compile a regular expression pattern, returning a Pattern object."
251
+ return _compile(pattern, flags)
252
+
253
+ def purge():
254
+ "Clear the regular expression caches"
255
+ _cache.clear()
256
+ _compile_repl.cache_clear()
257
+
258
+ def template(pattern, flags=0):
259
+ "Compile a template pattern, returning a Pattern object"
260
+ return _compile(pattern, flags|T)
261
+
262
+ # SPECIAL_CHARS
263
+ # closing ')', '}' and ']'
264
+ # '-' (a range in character set)
265
+ # '&', '~', (extended character set operations)
266
+ # '#' (comment) and WHITESPACE (ignored) in verbose mode
267
+ _special_chars_map = {i: '\\' + chr(i) for i in b'()[]{}?*+-|^$\\.&~# \t\n\r\v\f'}
268
+
269
+ def escape(pattern):
270
+ """
271
+ Escape special characters in a string.
272
+ """
273
+ if isinstance(pattern, str):
274
+ return pattern.translate(_special_chars_map)
275
+ else:
276
+ pattern = str(pattern, 'latin1')
277
+ return pattern.translate(_special_chars_map).encode('latin1')
278
+
279
+ Pattern = type(sre_compile.compile('', 0))
280
+ Match = type(sre_compile.compile('', 0).match(''))
281
+
282
+ # --------------------------------------------------------------------
283
+ # internals
284
+
285
+ _cache = {} # ordered!
286
+
287
+ _MAXCACHE = 512
288
+ def _compile(pattern, flags):
289
+ # internal: compile pattern
290
+ if isinstance(flags, RegexFlag):
291
+ flags = flags.value
292
+ try:
293
+ return _cache[type(pattern), pattern, flags]
294
+ except KeyError:
295
+ pass
296
+ if isinstance(pattern, Pattern):
297
+ if flags:
298
+ raise ValueError(
299
+ "cannot process flags argument with a compiled pattern")
300
+ return pattern
301
+ if not sre_compile.isstring(pattern):
302
+ raise TypeError("first argument must be string or compiled pattern")
303
+ p = sre_compile.compile(pattern, flags)
304
+ if not (flags & DEBUG):
305
+ if len(_cache) >= _MAXCACHE:
306
+ # Drop the oldest item
307
+ try:
308
+ del _cache[next(iter(_cache))]
309
+ except (StopIteration, RuntimeError, KeyError):
310
+ pass
311
+ _cache[type(pattern), pattern, flags] = p
312
+ return p
313
+
314
+ @functools.lru_cache(_MAXCACHE)
315
+ def _compile_repl(repl, pattern):
316
+ # internal: compile replacement pattern
317
+ return sre_parse.parse_template(repl, pattern)
318
+
319
+ def _expand(pattern, match, template):
320
+ # internal: Match.expand implementation hook
321
+ template = sre_parse.parse_template(template, pattern)
322
+ return sre_parse.expand_template(template, match)
323
+
324
+ def _subx(pattern, template):
325
+ # internal: Pattern.sub/subn implementation helper
326
+ template = _compile_repl(template, pattern)
327
+ if not template[0] and len(template[1]) == 1:
328
+ # literal replacement
329
+ return template[1][0]
330
+ def filter(match, template=template):
331
+ return sre_parse.expand_template(template, match)
332
+ return filter
333
+
334
+ # register myself for pickling
335
+
336
+ import copyreg
337
+
338
+ def _pickle(p):
339
+ return _compile, (p.pattern, p.flags)
340
+
341
+ copyreg.pickle(Pattern, _pickle, _compile)
342
+
343
+ # --------------------------------------------------------------------
344
+ # experimental stuff (see python-dev discussions for details)
345
+
346
+ class Scanner:
347
+ def __init__(self, lexicon, flags=0):
348
+ from sre_constants import BRANCH, SUBPATTERN
349
+ if isinstance(flags, RegexFlag):
350
+ flags = flags.value
351
+ self.lexicon = lexicon
352
+ # combine phrases into a compound pattern
353
+ p = []
354
+ s = sre_parse.State()
355
+ s.flags = flags
356
+ for phrase, action in lexicon:
357
+ gid = s.opengroup()
358
+ p.append(sre_parse.SubPattern(s, [
359
+ (SUBPATTERN, (gid, 0, 0, sre_parse.parse(phrase, flags))),
360
+ ]))
361
+ s.closegroup(gid, p[-1])
362
+ p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
363
+ self.scanner = sre_compile.compile(p)
364
+ def scan(self, string):
365
+ result = []
366
+ append = result.append
367
+ match = self.scanner.scanner(string).match
368
+ i = 0
369
+ while True:
370
+ m = match()
371
+ if not m:
372
+ break
373
+ j = m.end()
374
+ if i == j:
375
+ break
376
+ action = self.lexicon[m.lastindex-1][1]
377
+ if callable(action):
378
+ self.match = m
379
+ action = action(self, m.group())
380
+ if action is not None:
381
+ append(action)
382
+ i = j
383
+ return result, string[i:]
lib/python3.10/reprlib.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Redo the builtin repr() (representation) but with limits on most sizes."""
2
+
3
+ __all__ = ["Repr", "repr", "recursive_repr"]
4
+
5
+ import builtins
6
+ from itertools import islice
7
+ from _thread import get_ident
8
+
9
+ def recursive_repr(fillvalue='...'):
10
+ 'Decorator to make a repr function return fillvalue for a recursive call'
11
+
12
+ def decorating_function(user_function):
13
+ repr_running = set()
14
+
15
+ def wrapper(self):
16
+ key = id(self), get_ident()
17
+ if key in repr_running:
18
+ return fillvalue
19
+ repr_running.add(key)
20
+ try:
21
+ result = user_function(self)
22
+ finally:
23
+ repr_running.discard(key)
24
+ return result
25
+
26
+ # Can't use functools.wraps() here because of bootstrap issues
27
+ wrapper.__module__ = getattr(user_function, '__module__')
28
+ wrapper.__doc__ = getattr(user_function, '__doc__')
29
+ wrapper.__name__ = getattr(user_function, '__name__')
30
+ wrapper.__qualname__ = getattr(user_function, '__qualname__')
31
+ wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
32
+ return wrapper
33
+
34
+ return decorating_function
35
+
36
+ class Repr:
37
+
38
+ def __init__(self):
39
+ self.maxlevel = 6
40
+ self.maxtuple = 6
41
+ self.maxlist = 6
42
+ self.maxarray = 5
43
+ self.maxdict = 4
44
+ self.maxset = 6
45
+ self.maxfrozenset = 6
46
+ self.maxdeque = 6
47
+ self.maxstring = 30
48
+ self.maxlong = 40
49
+ self.maxother = 30
50
+
51
+ def repr(self, x):
52
+ return self.repr1(x, self.maxlevel)
53
+
54
+ def repr1(self, x, level):
55
+ typename = type(x).__name__
56
+ if ' ' in typename:
57
+ parts = typename.split()
58
+ typename = '_'.join(parts)
59
+ if hasattr(self, 'repr_' + typename):
60
+ return getattr(self, 'repr_' + typename)(x, level)
61
+ else:
62
+ return self.repr_instance(x, level)
63
+
64
+ def _repr_iterable(self, x, level, left, right, maxiter, trail=''):
65
+ n = len(x)
66
+ if level <= 0 and n:
67
+ s = '...'
68
+ else:
69
+ newlevel = level - 1
70
+ repr1 = self.repr1
71
+ pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)]
72
+ if n > maxiter: pieces.append('...')
73
+ s = ', '.join(pieces)
74
+ if n == 1 and trail: right = trail + right
75
+ return '%s%s%s' % (left, s, right)
76
+
77
+ def repr_tuple(self, x, level):
78
+ return self._repr_iterable(x, level, '(', ')', self.maxtuple, ',')
79
+
80
+ def repr_list(self, x, level):
81
+ return self._repr_iterable(x, level, '[', ']', self.maxlist)
82
+
83
+ def repr_array(self, x, level):
84
+ if not x:
85
+ return "array('%s')" % x.typecode
86
+ header = "array('%s', [" % x.typecode
87
+ return self._repr_iterable(x, level, header, '])', self.maxarray)
88
+
89
+ def repr_set(self, x, level):
90
+ if not x:
91
+ return 'set()'
92
+ x = _possibly_sorted(x)
93
+ return self._repr_iterable(x, level, '{', '}', self.maxset)
94
+
95
+ def repr_frozenset(self, x, level):
96
+ if not x:
97
+ return 'frozenset()'
98
+ x = _possibly_sorted(x)
99
+ return self._repr_iterable(x, level, 'frozenset({', '})',
100
+ self.maxfrozenset)
101
+
102
+ def repr_deque(self, x, level):
103
+ return self._repr_iterable(x, level, 'deque([', '])', self.maxdeque)
104
+
105
+ def repr_dict(self, x, level):
106
+ n = len(x)
107
+ if n == 0: return '{}'
108
+ if level <= 0: return '{...}'
109
+ newlevel = level - 1
110
+ repr1 = self.repr1
111
+ pieces = []
112
+ for key in islice(_possibly_sorted(x), self.maxdict):
113
+ keyrepr = repr1(key, newlevel)
114
+ valrepr = repr1(x[key], newlevel)
115
+ pieces.append('%s: %s' % (keyrepr, valrepr))
116
+ if n > self.maxdict: pieces.append('...')
117
+ s = ', '.join(pieces)
118
+ return '{%s}' % (s,)
119
+
120
+ def repr_str(self, x, level):
121
+ s = builtins.repr(x[:self.maxstring])
122
+ if len(s) > self.maxstring:
123
+ i = max(0, (self.maxstring-3)//2)
124
+ j = max(0, self.maxstring-3-i)
125
+ s = builtins.repr(x[:i] + x[len(x)-j:])
126
+ s = s[:i] + '...' + s[len(s)-j:]
127
+ return s
128
+
129
+ def repr_int(self, x, level):
130
+ s = builtins.repr(x) # XXX Hope this isn't too slow...
131
+ if len(s) > self.maxlong:
132
+ i = max(0, (self.maxlong-3)//2)
133
+ j = max(0, self.maxlong-3-i)
134
+ s = s[:i] + '...' + s[len(s)-j:]
135
+ return s
136
+
137
+ def repr_instance(self, x, level):
138
+ try:
139
+ s = builtins.repr(x)
140
+ # Bugs in x.__repr__() can cause arbitrary
141
+ # exceptions -- then make up something
142
+ except Exception:
143
+ return '<%s instance at %#x>' % (x.__class__.__name__, id(x))
144
+ if len(s) > self.maxother:
145
+ i = max(0, (self.maxother-3)//2)
146
+ j = max(0, self.maxother-3-i)
147
+ s = s[:i] + '...' + s[len(s)-j:]
148
+ return s
149
+
150
+
151
+ def _possibly_sorted(x):
152
+ # Since not all sequences of items can be sorted and comparison
153
+ # functions may raise arbitrary exceptions, return an unsorted
154
+ # sequence in that case.
155
+ try:
156
+ return sorted(x)
157
+ except Exception:
158
+ return list(x)
159
+
160
+ aRepr = Repr()
161
+ repr = aRepr.repr
lib/python3.10/rlcompleter.py ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Word completion for GNU readline.
2
+
3
+ The completer completes keywords, built-ins and globals in a selectable
4
+ namespace (which defaults to __main__); when completing NAME.NAME..., it
5
+ evaluates (!) the expression up to the last dot and completes its attributes.
6
+
7
+ It's very cool to do "import sys" type "sys.", hit the completion key (twice),
8
+ and see the list of names defined by the sys module!
9
+
10
+ Tip: to use the tab key as the completion key, call
11
+
12
+ readline.parse_and_bind("tab: complete")
13
+
14
+ Notes:
15
+
16
+ - Exceptions raised by the completer function are *ignored* (and generally cause
17
+ the completion to fail). This is a feature -- since readline sets the tty
18
+ device in raw (or cbreak) mode, printing a traceback wouldn't work well
19
+ without some complicated hoopla to save, reset and restore the tty state.
20
+
21
+ - The evaluation of the NAME.NAME... form may cause arbitrary application
22
+ defined code to be executed if an object with a __getattr__ hook is found.
23
+ Since it is the responsibility of the application (or the user) to enable this
24
+ feature, I consider this an acceptable risk. More complicated expressions
25
+ (e.g. function calls or indexing operations) are *not* evaluated.
26
+
27
+ - When the original stdin is not a tty device, GNU readline is never
28
+ used, and this module (and the readline module) are silently inactive.
29
+
30
+ """
31
+
32
+ import atexit
33
+ import builtins
34
+ import inspect
35
+ import __main__
36
+
37
+ __all__ = ["Completer"]
38
+
39
+ class Completer:
40
+ def __init__(self, namespace = None):
41
+ """Create a new completer for the command line.
42
+
43
+ Completer([namespace]) -> completer instance.
44
+
45
+ If unspecified, the default namespace where completions are performed
46
+ is __main__ (technically, __main__.__dict__). Namespaces should be
47
+ given as dictionaries.
48
+
49
+ Completer instances should be used as the completion mechanism of
50
+ readline via the set_completer() call:
51
+
52
+ readline.set_completer(Completer(my_namespace).complete)
53
+ """
54
+
55
+ if namespace and not isinstance(namespace, dict):
56
+ raise TypeError('namespace must be a dictionary')
57
+
58
+ # Don't bind to namespace quite yet, but flag whether the user wants a
59
+ # specific namespace or to use __main__.__dict__. This will allow us
60
+ # to bind to __main__.__dict__ at completion time, not now.
61
+ if namespace is None:
62
+ self.use_main_ns = 1
63
+ else:
64
+ self.use_main_ns = 0
65
+ self.namespace = namespace
66
+
67
+ def complete(self, text, state):
68
+ """Return the next possible completion for 'text'.
69
+
70
+ This is called successively with state == 0, 1, 2, ... until it
71
+ returns None. The completion should begin with 'text'.
72
+
73
+ """
74
+ if self.use_main_ns:
75
+ self.namespace = __main__.__dict__
76
+
77
+ if not text.strip():
78
+ if state == 0:
79
+ if _readline_available:
80
+ readline.insert_text('\t')
81
+ readline.redisplay()
82
+ return ''
83
+ else:
84
+ return '\t'
85
+ else:
86
+ return None
87
+
88
+ if state == 0:
89
+ if "." in text:
90
+ self.matches = self.attr_matches(text)
91
+ else:
92
+ self.matches = self.global_matches(text)
93
+ try:
94
+ return self.matches[state]
95
+ except IndexError:
96
+ return None
97
+
98
+ def _callable_postfix(self, val, word):
99
+ if callable(val):
100
+ word += "("
101
+ try:
102
+ if not inspect.signature(val).parameters:
103
+ word += ")"
104
+ except ValueError:
105
+ pass
106
+
107
+ return word
108
+
109
+ def global_matches(self, text):
110
+ """Compute matches when text is a simple name.
111
+
112
+ Return a list of all keywords, built-in functions and names currently
113
+ defined in self.namespace that match.
114
+
115
+ """
116
+ import keyword
117
+ matches = []
118
+ seen = {"__builtins__"}
119
+ n = len(text)
120
+ for word in keyword.kwlist:
121
+ if word[:n] == text:
122
+ seen.add(word)
123
+ if word in {'finally', 'try'}:
124
+ word = word + ':'
125
+ elif word not in {'False', 'None', 'True',
126
+ 'break', 'continue', 'pass',
127
+ 'else'}:
128
+ word = word + ' '
129
+ matches.append(word)
130
+ for nspace in [self.namespace, builtins.__dict__]:
131
+ for word, val in nspace.items():
132
+ if word[:n] == text and word not in seen:
133
+ seen.add(word)
134
+ matches.append(self._callable_postfix(val, word))
135
+ return matches
136
+
137
+ def attr_matches(self, text):
138
+ """Compute matches when text contains a dot.
139
+
140
+ Assuming the text is of the form NAME.NAME....[NAME], and is
141
+ evaluable in self.namespace, it will be evaluated and its attributes
142
+ (as revealed by dir()) are used as possible completions. (For class
143
+ instances, class members are also considered.)
144
+
145
+ WARNING: this can still invoke arbitrary C code, if an object
146
+ with a __getattr__ hook is evaluated.
147
+
148
+ """
149
+ import re
150
+ m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
151
+ if not m:
152
+ return []
153
+ expr, attr = m.group(1, 3)
154
+ try:
155
+ thisobject = eval(expr, self.namespace)
156
+ except Exception:
157
+ return []
158
+
159
+ # get the content of the object, except __builtins__
160
+ words = set(dir(thisobject))
161
+ words.discard("__builtins__")
162
+
163
+ if hasattr(thisobject, '__class__'):
164
+ words.add('__class__')
165
+ words.update(get_class_members(thisobject.__class__))
166
+ matches = []
167
+ n = len(attr)
168
+ if attr == '':
169
+ noprefix = '_'
170
+ elif attr == '_':
171
+ noprefix = '__'
172
+ else:
173
+ noprefix = None
174
+ while True:
175
+ for word in words:
176
+ if (word[:n] == attr and
177
+ not (noprefix and word[:n+1] == noprefix)):
178
+ match = "%s.%s" % (expr, word)
179
+ if isinstance(getattr(type(thisobject), word, None),
180
+ property):
181
+ # bpo-44752: thisobject.word is a method decorated by
182
+ # `@property`. What follows applies a postfix if
183
+ # thisobject.word is callable, but know we know that
184
+ # this is not callable (because it is a property).
185
+ # Also, getattr(thisobject, word) will evaluate the
186
+ # property method, which is not desirable.
187
+ matches.append(match)
188
+ continue
189
+ if (value := getattr(thisobject, word, None)) is not None:
190
+ matches.append(self._callable_postfix(value, match))
191
+ else:
192
+ matches.append(match)
193
+ if matches or not noprefix:
194
+ break
195
+ if noprefix == '_':
196
+ noprefix = '__'
197
+ else:
198
+ noprefix = None
199
+ matches.sort()
200
+ return matches
201
+
202
+ def get_class_members(klass):
203
+ ret = dir(klass)
204
+ if hasattr(klass,'__bases__'):
205
+ for base in klass.__bases__:
206
+ ret = ret + get_class_members(base)
207
+ return ret
208
+
209
+ try:
210
+ import readline
211
+ except ImportError:
212
+ _readline_available = False
213
+ else:
214
+ readline.set_completer(Completer().complete)
215
+ # Release references early at shutdown (the readline module's
216
+ # contents are quasi-immortal, and the completer function holds a
217
+ # reference to globals).
218
+ atexit.register(lambda: readline.set_completer(None))
219
+ _readline_available = True
lib/python3.10/runpy.py ADDED
@@ -0,0 +1,321 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """runpy.py - locating and running Python code using the module namespace
2
+
3
+ Provides support for locating and running Python scripts using the Python
4
+ module namespace instead of the native filesystem.
5
+
6
+ This allows Python code to play nicely with non-filesystem based PEP 302
7
+ importers when locating support scripts as well as when importing modules.
8
+ """
9
+ # Written by Nick Coghlan <ncoghlan at gmail.com>
10
+ # to implement PEP 338 (Executing Modules as Scripts)
11
+
12
+
13
+ import sys
14
+ import importlib.machinery # importlib first so we can test #15386 via -m
15
+ import importlib.util
16
+ import io
17
+ import types
18
+ import os
19
+
20
+ __all__ = [
21
+ "run_module", "run_path",
22
+ ]
23
+
24
+ class _TempModule(object):
25
+ """Temporarily replace a module in sys.modules with an empty namespace"""
26
+ def __init__(self, mod_name):
27
+ self.mod_name = mod_name
28
+ self.module = types.ModuleType(mod_name)
29
+ self._saved_module = []
30
+
31
+ def __enter__(self):
32
+ mod_name = self.mod_name
33
+ try:
34
+ self._saved_module.append(sys.modules[mod_name])
35
+ except KeyError:
36
+ pass
37
+ sys.modules[mod_name] = self.module
38
+ return self
39
+
40
+ def __exit__(self, *args):
41
+ if self._saved_module:
42
+ sys.modules[self.mod_name] = self._saved_module[0]
43
+ else:
44
+ del sys.modules[self.mod_name]
45
+ self._saved_module = []
46
+
47
+ class _ModifiedArgv0(object):
48
+ def __init__(self, value):
49
+ self.value = value
50
+ self._saved_value = self._sentinel = object()
51
+
52
+ def __enter__(self):
53
+ if self._saved_value is not self._sentinel:
54
+ raise RuntimeError("Already preserving saved value")
55
+ self._saved_value = sys.argv[0]
56
+ sys.argv[0] = self.value
57
+
58
+ def __exit__(self, *args):
59
+ self.value = self._sentinel
60
+ sys.argv[0] = self._saved_value
61
+
62
+ # TODO: Replace these helpers with importlib._bootstrap_external functions.
63
+ def _run_code(code, run_globals, init_globals=None,
64
+ mod_name=None, mod_spec=None,
65
+ pkg_name=None, script_name=None):
66
+ """Helper to run code in nominated namespace"""
67
+ if init_globals is not None:
68
+ run_globals.update(init_globals)
69
+ if mod_spec is None:
70
+ loader = None
71
+ fname = script_name
72
+ cached = None
73
+ else:
74
+ loader = mod_spec.loader
75
+ fname = mod_spec.origin
76
+ cached = mod_spec.cached
77
+ if pkg_name is None:
78
+ pkg_name = mod_spec.parent
79
+ run_globals.update(__name__ = mod_name,
80
+ __file__ = fname,
81
+ __cached__ = cached,
82
+ __doc__ = None,
83
+ __loader__ = loader,
84
+ __package__ = pkg_name,
85
+ __spec__ = mod_spec)
86
+ exec(code, run_globals)
87
+ return run_globals
88
+
89
+ def _run_module_code(code, init_globals=None,
90
+ mod_name=None, mod_spec=None,
91
+ pkg_name=None, script_name=None):
92
+ """Helper to run code in new namespace with sys modified"""
93
+ fname = script_name if mod_spec is None else mod_spec.origin
94
+ with _TempModule(mod_name) as temp_module, _ModifiedArgv0(fname):
95
+ mod_globals = temp_module.module.__dict__
96
+ _run_code(code, mod_globals, init_globals,
97
+ mod_name, mod_spec, pkg_name, script_name)
98
+ # Copy the globals of the temporary module, as they
99
+ # may be cleared when the temporary module goes away
100
+ return mod_globals.copy()
101
+
102
+ # Helper to get the full name, spec and code for a module
103
+ def _get_module_details(mod_name, error=ImportError):
104
+ if mod_name.startswith("."):
105
+ raise error("Relative module names not supported")
106
+ pkg_name, _, _ = mod_name.rpartition(".")
107
+ if pkg_name:
108
+ # Try importing the parent to avoid catching initialization errors
109
+ try:
110
+ __import__(pkg_name)
111
+ except ImportError as e:
112
+ # If the parent or higher ancestor package is missing, let the
113
+ # error be raised by find_spec() below and then be caught. But do
114
+ # not allow other errors to be caught.
115
+ if e.name is None or (e.name != pkg_name and
116
+ not pkg_name.startswith(e.name + ".")):
117
+ raise
118
+ # Warn if the module has already been imported under its normal name
119
+ existing = sys.modules.get(mod_name)
120
+ if existing is not None and not hasattr(existing, "__path__"):
121
+ from warnings import warn
122
+ msg = "{mod_name!r} found in sys.modules after import of " \
123
+ "package {pkg_name!r}, but prior to execution of " \
124
+ "{mod_name!r}; this may result in unpredictable " \
125
+ "behaviour".format(mod_name=mod_name, pkg_name=pkg_name)
126
+ warn(RuntimeWarning(msg))
127
+
128
+ try:
129
+ spec = importlib.util.find_spec(mod_name)
130
+ except (ImportError, AttributeError, TypeError, ValueError) as ex:
131
+ # This hack fixes an impedance mismatch between pkgutil and
132
+ # importlib, where the latter raises other errors for cases where
133
+ # pkgutil previously raised ImportError
134
+ msg = "Error while finding module specification for {!r} ({}: {})"
135
+ if mod_name.endswith(".py"):
136
+ msg += (f". Try using '{mod_name[:-3]}' instead of "
137
+ f"'{mod_name}' as the module name.")
138
+ raise error(msg.format(mod_name, type(ex).__name__, ex)) from ex
139
+ if spec is None:
140
+ raise error("No module named %s" % mod_name)
141
+ if spec.submodule_search_locations is not None:
142
+ if mod_name == "__main__" or mod_name.endswith(".__main__"):
143
+ raise error("Cannot use package as __main__ module")
144
+ try:
145
+ pkg_main_name = mod_name + ".__main__"
146
+ return _get_module_details(pkg_main_name, error)
147
+ except error as e:
148
+ if mod_name not in sys.modules:
149
+ raise # No module loaded; being a package is irrelevant
150
+ raise error(("%s; %r is a package and cannot " +
151
+ "be directly executed") %(e, mod_name))
152
+ loader = spec.loader
153
+ if loader is None:
154
+ raise error("%r is a namespace package and cannot be executed"
155
+ % mod_name)
156
+ try:
157
+ code = loader.get_code(mod_name)
158
+ except ImportError as e:
159
+ raise error(format(e)) from e
160
+ if code is None:
161
+ raise error("No code object available for %s" % mod_name)
162
+ return mod_name, spec, code
163
+
164
+ class _Error(Exception):
165
+ """Error that _run_module_as_main() should report without a traceback"""
166
+
167
+ # XXX ncoghlan: Should this be documented and made public?
168
+ # (Current thoughts: don't repeat the mistake that lead to its
169
+ # creation when run_module() no longer met the needs of
170
+ # mainmodule.c, but couldn't be changed because it was public)
171
+ def _run_module_as_main(mod_name, alter_argv=True):
172
+ """Runs the designated module in the __main__ namespace
173
+
174
+ Note that the executed module will have full access to the
175
+ __main__ namespace. If this is not desirable, the run_module()
176
+ function should be used to run the module code in a fresh namespace.
177
+
178
+ At the very least, these variables in __main__ will be overwritten:
179
+ __name__
180
+ __file__
181
+ __cached__
182
+ __loader__
183
+ __package__
184
+ """
185
+ try:
186
+ if alter_argv or mod_name != "__main__": # i.e. -m switch
187
+ mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
188
+ else: # i.e. directory or zipfile execution
189
+ mod_name, mod_spec, code = _get_main_module_details(_Error)
190
+ except _Error as exc:
191
+ msg = "%s: %s" % (sys.executable, exc)
192
+ sys.exit(msg)
193
+ main_globals = sys.modules["__main__"].__dict__
194
+ if alter_argv:
195
+ sys.argv[0] = mod_spec.origin
196
+ return _run_code(code, main_globals, None,
197
+ "__main__", mod_spec)
198
+
199
+ def run_module(mod_name, init_globals=None,
200
+ run_name=None, alter_sys=False):
201
+ """Execute a module's code without importing it.
202
+
203
+ mod_name -- an absolute module name or package name.
204
+
205
+ Optional arguments:
206
+ init_globals -- dictionary used to pre-populate the module’s
207
+ globals dictionary before the code is executed.
208
+
209
+ run_name -- if not None, this will be used for setting __name__;
210
+ otherwise, __name__ will be set to mod_name + '__main__' if the
211
+ named module is a package and to just mod_name otherwise.
212
+
213
+ alter_sys -- if True, sys.argv[0] is updated with the value of
214
+ __file__ and sys.modules[__name__] is updated with a temporary
215
+ module object for the module being executed. Both are
216
+ restored to their original values before the function returns.
217
+
218
+ Returns the resulting module globals dictionary.
219
+ """
220
+ mod_name, mod_spec, code = _get_module_details(mod_name)
221
+ if run_name is None:
222
+ run_name = mod_name
223
+ if alter_sys:
224
+ return _run_module_code(code, init_globals, run_name, mod_spec)
225
+ else:
226
+ # Leave the sys module alone
227
+ return _run_code(code, {}, init_globals, run_name, mod_spec)
228
+
229
+ def _get_main_module_details(error=ImportError):
230
+ # Helper that gives a nicer error message when attempting to
231
+ # execute a zipfile or directory by invoking __main__.py
232
+ # Also moves the standard __main__ out of the way so that the
233
+ # preexisting __loader__ entry doesn't cause issues
234
+ main_name = "__main__"
235
+ saved_main = sys.modules[main_name]
236
+ del sys.modules[main_name]
237
+ try:
238
+ return _get_module_details(main_name)
239
+ except ImportError as exc:
240
+ if main_name in str(exc):
241
+ raise error("can't find %r module in %r" %
242
+ (main_name, sys.path[0])) from exc
243
+ raise
244
+ finally:
245
+ sys.modules[main_name] = saved_main
246
+
247
+
248
+ def _get_code_from_file(run_name, fname):
249
+ # Check for a compiled file first
250
+ from pkgutil import read_code
251
+ decoded_path = os.path.abspath(os.fsdecode(fname))
252
+ with io.open_code(decoded_path) as f:
253
+ code = read_code(f)
254
+ if code is None:
255
+ # That didn't work, so try it as normal source code
256
+ with io.open_code(decoded_path) as f:
257
+ code = compile(f.read(), fname, 'exec')
258
+ return code, fname
259
+
260
+ def run_path(path_name, init_globals=None, run_name=None):
261
+ """Execute code located at the specified filesystem location.
262
+
263
+ path_name -- filesystem location of a Python script, zipfile,
264
+ or directory containing a top level __main__.py script.
265
+
266
+ Optional arguments:
267
+ init_globals -- dictionary used to pre-populate the module’s
268
+ globals dictionary before the code is executed.
269
+
270
+ run_name -- if not None, this will be used to set __name__;
271
+ otherwise, '<run_path>' will be used for __name__.
272
+
273
+ Returns the resulting module globals dictionary.
274
+ """
275
+ if run_name is None:
276
+ run_name = "<run_path>"
277
+ pkg_name = run_name.rpartition(".")[0]
278
+ from pkgutil import get_importer
279
+ importer = get_importer(path_name)
280
+ # Trying to avoid importing imp so as to not consume the deprecation warning.
281
+ is_NullImporter = False
282
+ if type(importer).__module__ == 'imp':
283
+ if type(importer).__name__ == 'NullImporter':
284
+ is_NullImporter = True
285
+ if isinstance(importer, type(None)) or is_NullImporter:
286
+ # Not a valid sys.path entry, so run the code directly
287
+ # execfile() doesn't help as we want to allow compiled files
288
+ code, fname = _get_code_from_file(run_name, path_name)
289
+ return _run_module_code(code, init_globals, run_name,
290
+ pkg_name=pkg_name, script_name=fname)
291
+ else:
292
+ # Finder is defined for path, so add it to
293
+ # the start of sys.path
294
+ sys.path.insert(0, path_name)
295
+ try:
296
+ # Here's where things are a little different from the run_module
297
+ # case. There, we only had to replace the module in sys while the
298
+ # code was running and doing so was somewhat optional. Here, we
299
+ # have no choice and we have to remove it even while we read the
300
+ # code. If we don't do this, a __loader__ attribute in the
301
+ # existing __main__ module may prevent location of the new module.
302
+ mod_name, mod_spec, code = _get_main_module_details()
303
+ with _TempModule(run_name) as temp_module, \
304
+ _ModifiedArgv0(path_name):
305
+ mod_globals = temp_module.module.__dict__
306
+ return _run_code(code, mod_globals, init_globals,
307
+ run_name, mod_spec, pkg_name).copy()
308
+ finally:
309
+ try:
310
+ sys.path.remove(path_name)
311
+ except ValueError:
312
+ pass
313
+
314
+
315
+ if __name__ == "__main__":
316
+ # Run the module specified as the next command line argument
317
+ if len(sys.argv) < 2:
318
+ print("No module specified for execution", file=sys.stderr)
319
+ else:
320
+ del sys.argv[0] # Make the requested module sys.argv[0]
321
+ _run_module_as_main(sys.argv[0])
lib/python3.10/sched.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A generally useful event scheduler class.
2
+
3
+ Each instance of this class manages its own queue.
4
+ No multi-threading is implied; you are supposed to hack that
5
+ yourself, or use a single instance per application.
6
+
7
+ Each instance is parametrized with two functions, one that is
8
+ supposed to return the current time, one that is supposed to
9
+ implement a delay. You can implement real-time scheduling by
10
+ substituting time and sleep from built-in module time, or you can
11
+ implement simulated time by writing your own functions. This can
12
+ also be used to integrate scheduling with STDWIN events; the delay
13
+ function is allowed to modify the queue. Time can be expressed as
14
+ integers or floating point numbers, as long as it is consistent.
15
+
16
+ Events are specified by tuples (time, priority, action, argument, kwargs).
17
+ As in UNIX, lower priority numbers mean higher priority; in this
18
+ way the queue can be maintained as a priority queue. Execution of the
19
+ event means calling the action function, passing it the argument
20
+ sequence in "argument" (remember that in Python, multiple function
21
+ arguments are be packed in a sequence) and keyword parameters in "kwargs".
22
+ The action function may be an instance method so it
23
+ has another way to reference private data (besides global variables).
24
+ """
25
+
26
+ import time
27
+ import heapq
28
+ from collections import namedtuple
29
+ from itertools import count
30
+ import threading
31
+ from time import monotonic as _time
32
+
33
+ __all__ = ["scheduler"]
34
+
35
+ Event = namedtuple('Event', 'time, priority, sequence, action, argument, kwargs')
36
+ Event.time.__doc__ = ('''Numeric type compatible with the return value of the
37
+ timefunc function passed to the constructor.''')
38
+ Event.priority.__doc__ = ('''Events scheduled for the same time will be executed
39
+ in the order of their priority.''')
40
+ Event.sequence.__doc__ = ('''A continually increasing sequence number that
41
+ separates events if time and priority are equal.''')
42
+ Event.action.__doc__ = ('''Executing the event means executing
43
+ action(*argument, **kwargs)''')
44
+ Event.argument.__doc__ = ('''argument is a sequence holding the positional
45
+ arguments for the action.''')
46
+ Event.kwargs.__doc__ = ('''kwargs is a dictionary holding the keyword
47
+ arguments for the action.''')
48
+
49
+ _sentinel = object()
50
+
51
+ class scheduler:
52
+
53
+ def __init__(self, timefunc=_time, delayfunc=time.sleep):
54
+ """Initialize a new instance, passing the time and delay
55
+ functions"""
56
+ self._queue = []
57
+ self._lock = threading.RLock()
58
+ self.timefunc = timefunc
59
+ self.delayfunc = delayfunc
60
+ self._sequence_generator = count()
61
+
62
+ def enterabs(self, time, priority, action, argument=(), kwargs=_sentinel):
63
+ """Enter a new event in the queue at an absolute time.
64
+
65
+ Returns an ID for the event which can be used to remove it,
66
+ if necessary.
67
+
68
+ """
69
+ if kwargs is _sentinel:
70
+ kwargs = {}
71
+
72
+ with self._lock:
73
+ event = Event(time, priority, next(self._sequence_generator),
74
+ action, argument, kwargs)
75
+ heapq.heappush(self._queue, event)
76
+ return event # The ID
77
+
78
+ def enter(self, delay, priority, action, argument=(), kwargs=_sentinel):
79
+ """A variant that specifies the time as a relative time.
80
+
81
+ This is actually the more commonly used interface.
82
+
83
+ """
84
+ time = self.timefunc() + delay
85
+ return self.enterabs(time, priority, action, argument, kwargs)
86
+
87
+ def cancel(self, event):
88
+ """Remove an event from the queue.
89
+
90
+ This must be presented the ID as returned by enter().
91
+ If the event is not in the queue, this raises ValueError.
92
+
93
+ """
94
+ with self._lock:
95
+ self._queue.remove(event)
96
+ heapq.heapify(self._queue)
97
+
98
+ def empty(self):
99
+ """Check whether the queue is empty."""
100
+ with self._lock:
101
+ return not self._queue
102
+
103
+ def run(self, blocking=True):
104
+ """Execute events until the queue is empty.
105
+ If blocking is False executes the scheduled events due to
106
+ expire soonest (if any) and then return the deadline of the
107
+ next scheduled call in the scheduler.
108
+
109
+ When there is a positive delay until the first event, the
110
+ delay function is called and the event is left in the queue;
111
+ otherwise, the event is removed from the queue and executed
112
+ (its action function is called, passing it the argument). If
113
+ the delay function returns prematurely, it is simply
114
+ restarted.
115
+
116
+ It is legal for both the delay function and the action
117
+ function to modify the queue or to raise an exception;
118
+ exceptions are not caught but the scheduler's state remains
119
+ well-defined so run() may be called again.
120
+
121
+ A questionable hack is added to allow other threads to run:
122
+ just after an event is executed, a delay of 0 is executed, to
123
+ avoid monopolizing the CPU when other threads are also
124
+ runnable.
125
+
126
+ """
127
+ # localize variable access to minimize overhead
128
+ # and to improve thread safety
129
+ lock = self._lock
130
+ q = self._queue
131
+ delayfunc = self.delayfunc
132
+ timefunc = self.timefunc
133
+ pop = heapq.heappop
134
+ while True:
135
+ with lock:
136
+ if not q:
137
+ break
138
+ (time, priority, sequence, action,
139
+ argument, kwargs) = q[0]
140
+ now = timefunc()
141
+ if time > now:
142
+ delay = True
143
+ else:
144
+ delay = False
145
+ pop(q)
146
+ if delay:
147
+ if not blocking:
148
+ return time - now
149
+ delayfunc(time - now)
150
+ else:
151
+ action(*argument, **kwargs)
152
+ delayfunc(0) # Let other threads run
153
+
154
+ @property
155
+ def queue(self):
156
+ """An ordered list of upcoming events.
157
+
158
+ Events are named tuples with fields for:
159
+ time, priority, action, arguments, kwargs
160
+
161
+ """
162
+ # Use heapq to sort the queue rather than using 'sorted(self._queue)'.
163
+ # With heapq, two events scheduled at the same time will show in
164
+ # the actual order they would be retrieved.
165
+ with self._lock:
166
+ events = self._queue[:]
167
+ return list(map(heapq.heappop, [events]*len(events)))
lib/python3.10/secrets.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generate cryptographically strong pseudo-random numbers suitable for
2
+ managing secrets such as account authentication, tokens, and similar.
3
+
4
+ See PEP 506 for more information.
5
+ https://www.python.org/dev/peps/pep-0506/
6
+
7
+ """
8
+
9
+ __all__ = ['choice', 'randbelow', 'randbits', 'SystemRandom',
10
+ 'token_bytes', 'token_hex', 'token_urlsafe',
11
+ 'compare_digest',
12
+ ]
13
+
14
+
15
+ import base64
16
+ import binascii
17
+
18
+ from hmac import compare_digest
19
+ from random import SystemRandom
20
+
21
+ _sysrand = SystemRandom()
22
+
23
+ randbits = _sysrand.getrandbits
24
+ choice = _sysrand.choice
25
+
26
+ def randbelow(exclusive_upper_bound):
27
+ """Return a random int in the range [0, n)."""
28
+ if exclusive_upper_bound <= 0:
29
+ raise ValueError("Upper bound must be positive.")
30
+ return _sysrand._randbelow(exclusive_upper_bound)
31
+
32
+ DEFAULT_ENTROPY = 32 # number of bytes to return by default
33
+
34
+ def token_bytes(nbytes=None):
35
+ """Return a random byte string containing *nbytes* bytes.
36
+
37
+ If *nbytes* is ``None`` or not supplied, a reasonable
38
+ default is used.
39
+
40
+ >>> token_bytes(16) #doctest:+SKIP
41
+ b'\\xebr\\x17D*t\\xae\\xd4\\xe3S\\xb6\\xe2\\xebP1\\x8b'
42
+
43
+ """
44
+ if nbytes is None:
45
+ nbytes = DEFAULT_ENTROPY
46
+ return _sysrand.randbytes(nbytes)
47
+
48
+ def token_hex(nbytes=None):
49
+ """Return a random text string, in hexadecimal.
50
+
51
+ The string has *nbytes* random bytes, each byte converted to two
52
+ hex digits. If *nbytes* is ``None`` or not supplied, a reasonable
53
+ default is used.
54
+
55
+ >>> token_hex(16) #doctest:+SKIP
56
+ 'f9bf78b9a18ce6d46a0cd2b0b86df9da'
57
+
58
+ """
59
+ return binascii.hexlify(token_bytes(nbytes)).decode('ascii')
60
+
61
+ def token_urlsafe(nbytes=None):
62
+ """Return a random URL-safe text string, in Base64 encoding.
63
+
64
+ The string has *nbytes* random bytes. If *nbytes* is ``None``
65
+ or not supplied, a reasonable default is used.
66
+
67
+ >>> token_urlsafe(16) #doctest:+SKIP
68
+ 'Drmhze6EPcv0fN_81Bj-nA'
69
+
70
+ """
71
+ tok = token_bytes(nbytes)
72
+ return base64.urlsafe_b64encode(tok).rstrip(b'=').decode('ascii')
lib/python3.10/selectors.py ADDED
@@ -0,0 +1,619 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Selectors module.
2
+
3
+ This module allows high-level and efficient I/O multiplexing, built upon the
4
+ `select` module primitives.
5
+ """
6
+
7
+
8
+ from abc import ABCMeta, abstractmethod
9
+ from collections import namedtuple
10
+ from collections.abc import Mapping
11
+ import math
12
+ import select
13
+ import sys
14
+
15
+
16
+ # generic events, that must be mapped to implementation-specific ones
17
+ EVENT_READ = (1 << 0)
18
+ EVENT_WRITE = (1 << 1)
19
+
20
+
21
+ def _fileobj_to_fd(fileobj):
22
+ """Return a file descriptor from a file object.
23
+
24
+ Parameters:
25
+ fileobj -- file object or file descriptor
26
+
27
+ Returns:
28
+ corresponding file descriptor
29
+
30
+ Raises:
31
+ ValueError if the object is invalid
32
+ """
33
+ if isinstance(fileobj, int):
34
+ fd = fileobj
35
+ else:
36
+ try:
37
+ fd = int(fileobj.fileno())
38
+ except (AttributeError, TypeError, ValueError):
39
+ raise ValueError("Invalid file object: "
40
+ "{!r}".format(fileobj)) from None
41
+ if fd < 0:
42
+ raise ValueError("Invalid file descriptor: {}".format(fd))
43
+ return fd
44
+
45
+
46
+ SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])
47
+
48
+ SelectorKey.__doc__ = """SelectorKey(fileobj, fd, events, data)
49
+
50
+ Object used to associate a file object to its backing
51
+ file descriptor, selected event mask, and attached data.
52
+ """
53
+ if sys.version_info >= (3, 5):
54
+ SelectorKey.fileobj.__doc__ = 'File object registered.'
55
+ SelectorKey.fd.__doc__ = 'Underlying file descriptor.'
56
+ SelectorKey.events.__doc__ = 'Events that must be waited for on this file object.'
57
+ SelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object.
58
+ For example, this could be used to store a per-client session ID.''')
59
+
60
+
61
+ class _SelectorMapping(Mapping):
62
+ """Mapping of file objects to selector keys."""
63
+
64
+ def __init__(self, selector):
65
+ self._selector = selector
66
+
67
+ def __len__(self):
68
+ return len(self._selector._fd_to_key)
69
+
70
+ def __getitem__(self, fileobj):
71
+ try:
72
+ fd = self._selector._fileobj_lookup(fileobj)
73
+ return self._selector._fd_to_key[fd]
74
+ except KeyError:
75
+ raise KeyError("{!r} is not registered".format(fileobj)) from None
76
+
77
+ def __iter__(self):
78
+ return iter(self._selector._fd_to_key)
79
+
80
+
81
+ class BaseSelector(metaclass=ABCMeta):
82
+ """Selector abstract base class.
83
+
84
+ A selector supports registering file objects to be monitored for specific
85
+ I/O events.
86
+
87
+ A file object is a file descriptor or any object with a `fileno()` method.
88
+ An arbitrary object can be attached to the file object, which can be used
89
+ for example to store context information, a callback, etc.
90
+
91
+ A selector can use various implementations (select(), poll(), epoll()...)
92
+ depending on the platform. The default `Selector` class uses the most
93
+ efficient implementation on the current platform.
94
+ """
95
+
96
+ @abstractmethod
97
+ def register(self, fileobj, events, data=None):
98
+ """Register a file object.
99
+
100
+ Parameters:
101
+ fileobj -- file object or file descriptor
102
+ events -- events to monitor (bitwise mask of EVENT_READ|EVENT_WRITE)
103
+ data -- attached data
104
+
105
+ Returns:
106
+ SelectorKey instance
107
+
108
+ Raises:
109
+ ValueError if events is invalid
110
+ KeyError if fileobj is already registered
111
+ OSError if fileobj is closed or otherwise is unacceptable to
112
+ the underlying system call (if a system call is made)
113
+
114
+ Note:
115
+ OSError may or may not be raised
116
+ """
117
+ raise NotImplementedError
118
+
119
+ @abstractmethod
120
+ def unregister(self, fileobj):
121
+ """Unregister a file object.
122
+
123
+ Parameters:
124
+ fileobj -- file object or file descriptor
125
+
126
+ Returns:
127
+ SelectorKey instance
128
+
129
+ Raises:
130
+ KeyError if fileobj is not registered
131
+
132
+ Note:
133
+ If fileobj is registered but has since been closed this does
134
+ *not* raise OSError (even if the wrapped syscall does)
135
+ """
136
+ raise NotImplementedError
137
+
138
+ def modify(self, fileobj, events, data=None):
139
+ """Change a registered file object monitored events or attached data.
140
+
141
+ Parameters:
142
+ fileobj -- file object or file descriptor
143
+ events -- events to monitor (bitwise mask of EVENT_READ|EVENT_WRITE)
144
+ data -- attached data
145
+
146
+ Returns:
147
+ SelectorKey instance
148
+
149
+ Raises:
150
+ Anything that unregister() or register() raises
151
+ """
152
+ self.unregister(fileobj)
153
+ return self.register(fileobj, events, data)
154
+
155
+ @abstractmethod
156
+ def select(self, timeout=None):
157
+ """Perform the actual selection, until some monitored file objects are
158
+ ready or a timeout expires.
159
+
160
+ Parameters:
161
+ timeout -- if timeout > 0, this specifies the maximum wait time, in
162
+ seconds
163
+ if timeout <= 0, the select() call won't block, and will
164
+ report the currently ready file objects
165
+ if timeout is None, select() will block until a monitored
166
+ file object becomes ready
167
+
168
+ Returns:
169
+ list of (key, events) for ready file objects
170
+ `events` is a bitwise mask of EVENT_READ|EVENT_WRITE
171
+ """
172
+ raise NotImplementedError
173
+
174
+ def close(self):
175
+ """Close the selector.
176
+
177
+ This must be called to make sure that any underlying resource is freed.
178
+ """
179
+ pass
180
+
181
+ def get_key(self, fileobj):
182
+ """Return the key associated to a registered file object.
183
+
184
+ Returns:
185
+ SelectorKey for this file object
186
+ """
187
+ mapping = self.get_map()
188
+ if mapping is None:
189
+ raise RuntimeError('Selector is closed')
190
+ try:
191
+ return mapping[fileobj]
192
+ except KeyError:
193
+ raise KeyError("{!r} is not registered".format(fileobj)) from None
194
+
195
+ @abstractmethod
196
+ def get_map(self):
197
+ """Return a mapping of file objects to selector keys."""
198
+ raise NotImplementedError
199
+
200
+ def __enter__(self):
201
+ return self
202
+
203
+ def __exit__(self, *args):
204
+ self.close()
205
+
206
+
207
+ class _BaseSelectorImpl(BaseSelector):
208
+ """Base selector implementation."""
209
+
210
+ def __init__(self):
211
+ # this maps file descriptors to keys
212
+ self._fd_to_key = {}
213
+ # read-only mapping returned by get_map()
214
+ self._map = _SelectorMapping(self)
215
+
216
+ def _fileobj_lookup(self, fileobj):
217
+ """Return a file descriptor from a file object.
218
+
219
+ This wraps _fileobj_to_fd() to do an exhaustive search in case
220
+ the object is invalid but we still have it in our map. This
221
+ is used by unregister() so we can unregister an object that
222
+ was previously registered even if it is closed. It is also
223
+ used by _SelectorMapping.
224
+ """
225
+ try:
226
+ return _fileobj_to_fd(fileobj)
227
+ except ValueError:
228
+ # Do an exhaustive search.
229
+ for key in self._fd_to_key.values():
230
+ if key.fileobj is fileobj:
231
+ return key.fd
232
+ # Raise ValueError after all.
233
+ raise
234
+
235
+ def register(self, fileobj, events, data=None):
236
+ if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)):
237
+ raise ValueError("Invalid events: {!r}".format(events))
238
+
239
+ key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
240
+
241
+ if key.fd in self._fd_to_key:
242
+ raise KeyError("{!r} (FD {}) is already registered"
243
+ .format(fileobj, key.fd))
244
+
245
+ self._fd_to_key[key.fd] = key
246
+ return key
247
+
248
+ def unregister(self, fileobj):
249
+ try:
250
+ key = self._fd_to_key.pop(self._fileobj_lookup(fileobj))
251
+ except KeyError:
252
+ raise KeyError("{!r} is not registered".format(fileobj)) from None
253
+ return key
254
+
255
+ def modify(self, fileobj, events, data=None):
256
+ try:
257
+ key = self._fd_to_key[self._fileobj_lookup(fileobj)]
258
+ except KeyError:
259
+ raise KeyError("{!r} is not registered".format(fileobj)) from None
260
+ if events != key.events:
261
+ self.unregister(fileobj)
262
+ key = self.register(fileobj, events, data)
263
+ elif data != key.data:
264
+ # Use a shortcut to update the data.
265
+ key = key._replace(data=data)
266
+ self._fd_to_key[key.fd] = key
267
+ return key
268
+
269
+ def close(self):
270
+ self._fd_to_key.clear()
271
+ self._map = None
272
+
273
+ def get_map(self):
274
+ return self._map
275
+
276
+ def _key_from_fd(self, fd):
277
+ """Return the key associated to a given file descriptor.
278
+
279
+ Parameters:
280
+ fd -- file descriptor
281
+
282
+ Returns:
283
+ corresponding key, or None if not found
284
+ """
285
+ try:
286
+ return self._fd_to_key[fd]
287
+ except KeyError:
288
+ return None
289
+
290
+
291
+ class SelectSelector(_BaseSelectorImpl):
292
+ """Select-based selector."""
293
+
294
+ def __init__(self):
295
+ super().__init__()
296
+ self._readers = set()
297
+ self._writers = set()
298
+
299
+ def register(self, fileobj, events, data=None):
300
+ key = super().register(fileobj, events, data)
301
+ if events & EVENT_READ:
302
+ self._readers.add(key.fd)
303
+ if events & EVENT_WRITE:
304
+ self._writers.add(key.fd)
305
+ return key
306
+
307
+ def unregister(self, fileobj):
308
+ key = super().unregister(fileobj)
309
+ self._readers.discard(key.fd)
310
+ self._writers.discard(key.fd)
311
+ return key
312
+
313
+ if sys.platform == 'win32':
314
+ def _select(self, r, w, _, timeout=None):
315
+ r, w, x = select.select(r, w, w, timeout)
316
+ return r, w + x, []
317
+ else:
318
+ _select = select.select
319
+
320
+ def select(self, timeout=None):
321
+ timeout = None if timeout is None else max(timeout, 0)
322
+ ready = []
323
+ try:
324
+ r, w, _ = self._select(self._readers, self._writers, [], timeout)
325
+ except InterruptedError:
326
+ return ready
327
+ r = set(r)
328
+ w = set(w)
329
+ for fd in r | w:
330
+ events = 0
331
+ if fd in r:
332
+ events |= EVENT_READ
333
+ if fd in w:
334
+ events |= EVENT_WRITE
335
+
336
+ key = self._key_from_fd(fd)
337
+ if key:
338
+ ready.append((key, events & key.events))
339
+ return ready
340
+
341
+
342
+ class _PollLikeSelector(_BaseSelectorImpl):
343
+ """Base class shared between poll, epoll and devpoll selectors."""
344
+ _selector_cls = None
345
+ _EVENT_READ = None
346
+ _EVENT_WRITE = None
347
+
348
+ def __init__(self):
349
+ super().__init__()
350
+ self._selector = self._selector_cls()
351
+
352
+ def register(self, fileobj, events, data=None):
353
+ key = super().register(fileobj, events, data)
354
+ poller_events = 0
355
+ if events & EVENT_READ:
356
+ poller_events |= self._EVENT_READ
357
+ if events & EVENT_WRITE:
358
+ poller_events |= self._EVENT_WRITE
359
+ try:
360
+ self._selector.register(key.fd, poller_events)
361
+ except:
362
+ super().unregister(fileobj)
363
+ raise
364
+ return key
365
+
366
+ def unregister(self, fileobj):
367
+ key = super().unregister(fileobj)
368
+ try:
369
+ self._selector.unregister(key.fd)
370
+ except OSError:
371
+ # This can happen if the FD was closed since it
372
+ # was registered.
373
+ pass
374
+ return key
375
+
376
+ def modify(self, fileobj, events, data=None):
377
+ try:
378
+ key = self._fd_to_key[self._fileobj_lookup(fileobj)]
379
+ except KeyError:
380
+ raise KeyError(f"{fileobj!r} is not registered") from None
381
+
382
+ changed = False
383
+ if events != key.events:
384
+ selector_events = 0
385
+ if events & EVENT_READ:
386
+ selector_events |= self._EVENT_READ
387
+ if events & EVENT_WRITE:
388
+ selector_events |= self._EVENT_WRITE
389
+ try:
390
+ self._selector.modify(key.fd, selector_events)
391
+ except:
392
+ super().unregister(fileobj)
393
+ raise
394
+ changed = True
395
+ if data != key.data:
396
+ changed = True
397
+
398
+ if changed:
399
+ key = key._replace(events=events, data=data)
400
+ self._fd_to_key[key.fd] = key
401
+ return key
402
+
403
+ def select(self, timeout=None):
404
+ # This is shared between poll() and epoll().
405
+ # epoll() has a different signature and handling of timeout parameter.
406
+ if timeout is None:
407
+ timeout = None
408
+ elif timeout <= 0:
409
+ timeout = 0
410
+ else:
411
+ # poll() has a resolution of 1 millisecond, round away from
412
+ # zero to wait *at least* timeout seconds.
413
+ timeout = math.ceil(timeout * 1e3)
414
+ ready = []
415
+ try:
416
+ fd_event_list = self._selector.poll(timeout)
417
+ except InterruptedError:
418
+ return ready
419
+ for fd, event in fd_event_list:
420
+ events = 0
421
+ if event & ~self._EVENT_READ:
422
+ events |= EVENT_WRITE
423
+ if event & ~self._EVENT_WRITE:
424
+ events |= EVENT_READ
425
+
426
+ key = self._key_from_fd(fd)
427
+ if key:
428
+ ready.append((key, events & key.events))
429
+ return ready
430
+
431
+
432
+ if hasattr(select, 'poll'):
433
+
434
+ class PollSelector(_PollLikeSelector):
435
+ """Poll-based selector."""
436
+ _selector_cls = select.poll
437
+ _EVENT_READ = select.POLLIN
438
+ _EVENT_WRITE = select.POLLOUT
439
+
440
+
441
+ if hasattr(select, 'epoll'):
442
+
443
+ class EpollSelector(_PollLikeSelector):
444
+ """Epoll-based selector."""
445
+ _selector_cls = select.epoll
446
+ _EVENT_READ = select.EPOLLIN
447
+ _EVENT_WRITE = select.EPOLLOUT
448
+
449
+ def fileno(self):
450
+ return self._selector.fileno()
451
+
452
+ def select(self, timeout=None):
453
+ if timeout is None:
454
+ timeout = -1
455
+ elif timeout <= 0:
456
+ timeout = 0
457
+ else:
458
+ # epoll_wait() has a resolution of 1 millisecond, round away
459
+ # from zero to wait *at least* timeout seconds.
460
+ timeout = math.ceil(timeout * 1e3) * 1e-3
461
+
462
+ # epoll_wait() expects `maxevents` to be greater than zero;
463
+ # we want to make sure that `select()` can be called when no
464
+ # FD is registered.
465
+ max_ev = max(len(self._fd_to_key), 1)
466
+
467
+ ready = []
468
+ try:
469
+ fd_event_list = self._selector.poll(timeout, max_ev)
470
+ except InterruptedError:
471
+ return ready
472
+ for fd, event in fd_event_list:
473
+ events = 0
474
+ if event & ~select.EPOLLIN:
475
+ events |= EVENT_WRITE
476
+ if event & ~select.EPOLLOUT:
477
+ events |= EVENT_READ
478
+
479
+ key = self._key_from_fd(fd)
480
+ if key:
481
+ ready.append((key, events & key.events))
482
+ return ready
483
+
484
+ def close(self):
485
+ self._selector.close()
486
+ super().close()
487
+
488
+
489
+ if hasattr(select, 'devpoll'):
490
+
491
+ class DevpollSelector(_PollLikeSelector):
492
+ """Solaris /dev/poll selector."""
493
+ _selector_cls = select.devpoll
494
+ _EVENT_READ = select.POLLIN
495
+ _EVENT_WRITE = select.POLLOUT
496
+
497
+ def fileno(self):
498
+ return self._selector.fileno()
499
+
500
+ def close(self):
501
+ self._selector.close()
502
+ super().close()
503
+
504
+
505
+ if hasattr(select, 'kqueue'):
506
+
507
+ class KqueueSelector(_BaseSelectorImpl):
508
+ """Kqueue-based selector."""
509
+
510
+ def __init__(self):
511
+ super().__init__()
512
+ self._selector = select.kqueue()
513
+
514
+ def fileno(self):
515
+ return self._selector.fileno()
516
+
517
+ def register(self, fileobj, events, data=None):
518
+ key = super().register(fileobj, events, data)
519
+ try:
520
+ if events & EVENT_READ:
521
+ kev = select.kevent(key.fd, select.KQ_FILTER_READ,
522
+ select.KQ_EV_ADD)
523
+ self._selector.control([kev], 0, 0)
524
+ if events & EVENT_WRITE:
525
+ kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
526
+ select.KQ_EV_ADD)
527
+ self._selector.control([kev], 0, 0)
528
+ except:
529
+ super().unregister(fileobj)
530
+ raise
531
+ return key
532
+
533
+ def unregister(self, fileobj):
534
+ key = super().unregister(fileobj)
535
+ if key.events & EVENT_READ:
536
+ kev = select.kevent(key.fd, select.KQ_FILTER_READ,
537
+ select.KQ_EV_DELETE)
538
+ try:
539
+ self._selector.control([kev], 0, 0)
540
+ except OSError:
541
+ # This can happen if the FD was closed since it
542
+ # was registered.
543
+ pass
544
+ if key.events & EVENT_WRITE:
545
+ kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
546
+ select.KQ_EV_DELETE)
547
+ try:
548
+ self._selector.control([kev], 0, 0)
549
+ except OSError:
550
+ # See comment above.
551
+ pass
552
+ return key
553
+
554
+ def select(self, timeout=None):
555
+ timeout = None if timeout is None else max(timeout, 0)
556
+ # If max_ev is 0, kqueue will ignore the timeout. For consistent
557
+ # behavior with the other selector classes, we prevent that here
558
+ # (using max). See https://bugs.python.org/issue29255
559
+ max_ev = max(len(self._fd_to_key), 1)
560
+ ready = []
561
+ try:
562
+ kev_list = self._selector.control(None, max_ev, timeout)
563
+ except InterruptedError:
564
+ return ready
565
+ for kev in kev_list:
566
+ fd = kev.ident
567
+ flag = kev.filter
568
+ events = 0
569
+ if flag == select.KQ_FILTER_READ:
570
+ events |= EVENT_READ
571
+ if flag == select.KQ_FILTER_WRITE:
572
+ events |= EVENT_WRITE
573
+
574
+ key = self._key_from_fd(fd)
575
+ if key:
576
+ ready.append((key, events & key.events))
577
+ return ready
578
+
579
+ def close(self):
580
+ self._selector.close()
581
+ super().close()
582
+
583
+
584
+ def _can_use(method):
585
+ """Check if we can use the selector depending upon the
586
+ operating system. """
587
+ # Implementation based upon https://github.com/sethmlarson/selectors2/blob/master/selectors2.py
588
+ selector = getattr(select, method, None)
589
+ if selector is None:
590
+ # select module does not implement method
591
+ return False
592
+ # check if the OS and Kernel actually support the method. Call may fail with
593
+ # OSError: [Errno 38] Function not implemented
594
+ try:
595
+ selector_obj = selector()
596
+ if method == 'poll':
597
+ # check that poll actually works
598
+ selector_obj.poll(0)
599
+ else:
600
+ # close epoll, kqueue, and devpoll fd
601
+ selector_obj.close()
602
+ return True
603
+ except OSError:
604
+ return False
605
+
606
+
607
+ # Choose the best implementation, roughly:
608
+ # epoll|kqueue|devpoll > poll > select.
609
+ # select() also can't accept a FD > FD_SETSIZE (usually around 1024)
610
+ if _can_use('kqueue'):
611
+ DefaultSelector = KqueueSelector
612
+ elif _can_use('epoll'):
613
+ DefaultSelector = EpollSelector
614
+ elif _can_use('devpoll'):
615
+ DefaultSelector = DevpollSelector
616
+ elif _can_use('poll'):
617
+ DefaultSelector = PollSelector
618
+ else:
619
+ DefaultSelector = SelectSelector
lib/python3.10/shelve.py ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Manage shelves of pickled objects.
2
+
3
+ A "shelf" is a persistent, dictionary-like object. The difference
4
+ with dbm databases is that the values (not the keys!) in a shelf can
5
+ be essentially arbitrary Python objects -- anything that the "pickle"
6
+ module can handle. This includes most class instances, recursive data
7
+ types, and objects containing lots of shared sub-objects. The keys
8
+ are ordinary strings.
9
+
10
+ To summarize the interface (key is a string, data is an arbitrary
11
+ object):
12
+
13
+ import shelve
14
+ d = shelve.open(filename) # open, with (g)dbm filename -- no suffix
15
+
16
+ d[key] = data # store data at key (overwrites old data if
17
+ # using an existing key)
18
+ data = d[key] # retrieve a COPY of the data at key (raise
19
+ # KeyError if no such key) -- NOTE that this
20
+ # access returns a *copy* of the entry!
21
+ del d[key] # delete data stored at key (raises KeyError
22
+ # if no such key)
23
+ flag = key in d # true if the key exists
24
+ list = d.keys() # a list of all existing keys (slow!)
25
+
26
+ d.close() # close it
27
+
28
+ Dependent on the implementation, closing a persistent dictionary may
29
+ or may not be necessary to flush changes to disk.
30
+
31
+ Normally, d[key] returns a COPY of the entry. This needs care when
32
+ mutable entries are mutated: for example, if d[key] is a list,
33
+ d[key].append(anitem)
34
+ does NOT modify the entry d[key] itself, as stored in the persistent
35
+ mapping -- it only modifies the copy, which is then immediately
36
+ discarded, so that the append has NO effect whatsoever. To append an
37
+ item to d[key] in a way that will affect the persistent mapping, use:
38
+ data = d[key]
39
+ data.append(anitem)
40
+ d[key] = data
41
+
42
+ To avoid the problem with mutable entries, you may pass the keyword
43
+ argument writeback=True in the call to shelve.open. When you use:
44
+ d = shelve.open(filename, writeback=True)
45
+ then d keeps a cache of all entries you access, and writes them all back
46
+ to the persistent mapping when you call d.close(). This ensures that
47
+ such usage as d[key].append(anitem) works as intended.
48
+
49
+ However, using keyword argument writeback=True may consume vast amount
50
+ of memory for the cache, and it may make d.close() very slow, if you
51
+ access many of d's entries after opening it in this way: d has no way to
52
+ check which of the entries you access are mutable and/or which ones you
53
+ actually mutate, so it must cache, and write back at close, all of the
54
+ entries that you access. You can call d.sync() to write back all the
55
+ entries in the cache, and empty the cache (d.sync() also synchronizes
56
+ the persistent dictionary on disk, if feasible).
57
+ """
58
+
59
+ from pickle import DEFAULT_PROTOCOL, Pickler, Unpickler
60
+ from io import BytesIO
61
+
62
+ import collections.abc
63
+
64
+ __all__ = ["Shelf", "BsdDbShelf", "DbfilenameShelf", "open"]
65
+
66
+ class _ClosedDict(collections.abc.MutableMapping):
67
+ 'Marker for a closed dict. Access attempts raise a ValueError.'
68
+
69
+ def closed(self, *args):
70
+ raise ValueError('invalid operation on closed shelf')
71
+ __iter__ = __len__ = __getitem__ = __setitem__ = __delitem__ = keys = closed
72
+
73
+ def __repr__(self):
74
+ return '<Closed Dictionary>'
75
+
76
+
77
+ class Shelf(collections.abc.MutableMapping):
78
+ """Base class for shelf implementations.
79
+
80
+ This is initialized with a dictionary-like object.
81
+ See the module's __doc__ string for an overview of the interface.
82
+ """
83
+
84
+ def __init__(self, dict, protocol=None, writeback=False,
85
+ keyencoding="utf-8"):
86
+ self.dict = dict
87
+ if protocol is None:
88
+ protocol = DEFAULT_PROTOCOL
89
+ self._protocol = protocol
90
+ self.writeback = writeback
91
+ self.cache = {}
92
+ self.keyencoding = keyencoding
93
+
94
+ def __iter__(self):
95
+ for k in self.dict.keys():
96
+ yield k.decode(self.keyencoding)
97
+
98
+ def __len__(self):
99
+ return len(self.dict)
100
+
101
+ def __contains__(self, key):
102
+ return key.encode(self.keyencoding) in self.dict
103
+
104
+ def get(self, key, default=None):
105
+ if key.encode(self.keyencoding) in self.dict:
106
+ return self[key]
107
+ return default
108
+
109
+ def __getitem__(self, key):
110
+ try:
111
+ value = self.cache[key]
112
+ except KeyError:
113
+ f = BytesIO(self.dict[key.encode(self.keyencoding)])
114
+ value = Unpickler(f).load()
115
+ if self.writeback:
116
+ self.cache[key] = value
117
+ return value
118
+
119
+ def __setitem__(self, key, value):
120
+ if self.writeback:
121
+ self.cache[key] = value
122
+ f = BytesIO()
123
+ p = Pickler(f, self._protocol)
124
+ p.dump(value)
125
+ self.dict[key.encode(self.keyencoding)] = f.getvalue()
126
+
127
+ def __delitem__(self, key):
128
+ del self.dict[key.encode(self.keyencoding)]
129
+ try:
130
+ del self.cache[key]
131
+ except KeyError:
132
+ pass
133
+
134
+ def __enter__(self):
135
+ return self
136
+
137
+ def __exit__(self, type, value, traceback):
138
+ self.close()
139
+
140
+ def close(self):
141
+ if self.dict is None:
142
+ return
143
+ try:
144
+ self.sync()
145
+ try:
146
+ self.dict.close()
147
+ except AttributeError:
148
+ pass
149
+ finally:
150
+ # Catch errors that may happen when close is called from __del__
151
+ # because CPython is in interpreter shutdown.
152
+ try:
153
+ self.dict = _ClosedDict()
154
+ except:
155
+ self.dict = None
156
+
157
+ def __del__(self):
158
+ if not hasattr(self, 'writeback'):
159
+ # __init__ didn't succeed, so don't bother closing
160
+ # see http://bugs.python.org/issue1339007 for details
161
+ return
162
+ self.close()
163
+
164
+ def sync(self):
165
+ if self.writeback and self.cache:
166
+ self.writeback = False
167
+ for key, entry in self.cache.items():
168
+ self[key] = entry
169
+ self.writeback = True
170
+ self.cache = {}
171
+ if hasattr(self.dict, 'sync'):
172
+ self.dict.sync()
173
+
174
+
175
+ class BsdDbShelf(Shelf):
176
+ """Shelf implementation using the "BSD" db interface.
177
+
178
+ This adds methods first(), next(), previous(), last() and
179
+ set_location() that have no counterpart in [g]dbm databases.
180
+
181
+ The actual database must be opened using one of the "bsddb"
182
+ modules "open" routines (i.e. bsddb.hashopen, bsddb.btopen or
183
+ bsddb.rnopen) and passed to the constructor.
184
+
185
+ See the module's __doc__ string for an overview of the interface.
186
+ """
187
+
188
+ def __init__(self, dict, protocol=None, writeback=False,
189
+ keyencoding="utf-8"):
190
+ Shelf.__init__(self, dict, protocol, writeback, keyencoding)
191
+
192
+ def set_location(self, key):
193
+ (key, value) = self.dict.set_location(key)
194
+ f = BytesIO(value)
195
+ return (key.decode(self.keyencoding), Unpickler(f).load())
196
+
197
+ def next(self):
198
+ (key, value) = next(self.dict)
199
+ f = BytesIO(value)
200
+ return (key.decode(self.keyencoding), Unpickler(f).load())
201
+
202
+ def previous(self):
203
+ (key, value) = self.dict.previous()
204
+ f = BytesIO(value)
205
+ return (key.decode(self.keyencoding), Unpickler(f).load())
206
+
207
+ def first(self):
208
+ (key, value) = self.dict.first()
209
+ f = BytesIO(value)
210
+ return (key.decode(self.keyencoding), Unpickler(f).load())
211
+
212
+ def last(self):
213
+ (key, value) = self.dict.last()
214
+ f = BytesIO(value)
215
+ return (key.decode(self.keyencoding), Unpickler(f).load())
216
+
217
+
218
+ class DbfilenameShelf(Shelf):
219
+ """Shelf implementation using the "dbm" generic dbm interface.
220
+
221
+ This is initialized with the filename for the dbm database.
222
+ See the module's __doc__ string for an overview of the interface.
223
+ """
224
+
225
+ def __init__(self, filename, flag='c', protocol=None, writeback=False):
226
+ import dbm
227
+ Shelf.__init__(self, dbm.open(filename, flag), protocol, writeback)
228
+
229
+
230
+ def open(filename, flag='c', protocol=None, writeback=False):
231
+ """Open a persistent dictionary for reading and writing.
232
+
233
+ The filename parameter is the base filename for the underlying
234
+ database. As a side-effect, an extension may be added to the
235
+ filename and more than one file may be created. The optional flag
236
+ parameter has the same interpretation as the flag parameter of
237
+ dbm.open(). The optional protocol parameter specifies the
238
+ version of the pickle protocol.
239
+
240
+ See the module's __doc__ string for an overview of the interface.
241
+ """
242
+
243
+ return DbfilenameShelf(filename, flag, protocol, writeback)
lib/python3.10/shlex.py ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A lexical analyzer class for simple shell-like syntaxes."""
2
+
3
+ # Module and documentation by Eric S. Raymond, 21 Dec 1998
4
+ # Input stacking and error message cleanup added by ESR, March 2000
5
+ # push_source() and pop_source() made explicit by ESR, January 2001.
6
+ # Posix compliance, split(), string arguments, and
7
+ # iterator interface by Gustavo Niemeyer, April 2003.
8
+ # changes to tokenize more like Posix shells by Vinay Sajip, July 2016.
9
+
10
+ import os
11
+ import re
12
+ import sys
13
+ from collections import deque
14
+
15
+ from io import StringIO
16
+
17
+ __all__ = ["shlex", "split", "quote", "join"]
18
+
19
+ class shlex:
20
+ "A lexical analyzer class for simple shell-like syntaxes."
21
+ def __init__(self, instream=None, infile=None, posix=False,
22
+ punctuation_chars=False):
23
+ if isinstance(instream, str):
24
+ instream = StringIO(instream)
25
+ if instream is not None:
26
+ self.instream = instream
27
+ self.infile = infile
28
+ else:
29
+ self.instream = sys.stdin
30
+ self.infile = None
31
+ self.posix = posix
32
+ if posix:
33
+ self.eof = None
34
+ else:
35
+ self.eof = ''
36
+ self.commenters = '#'
37
+ self.wordchars = ('abcdfeghijklmnopqrstuvwxyz'
38
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_')
39
+ if self.posix:
40
+ self.wordchars += ('ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ'
41
+ 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ')
42
+ self.whitespace = ' \t\r\n'
43
+ self.whitespace_split = False
44
+ self.quotes = '\'"'
45
+ self.escape = '\\'
46
+ self.escapedquotes = '"'
47
+ self.state = ' '
48
+ self.pushback = deque()
49
+ self.lineno = 1
50
+ self.debug = 0
51
+ self.token = ''
52
+ self.filestack = deque()
53
+ self.source = None
54
+ if not punctuation_chars:
55
+ punctuation_chars = ''
56
+ elif punctuation_chars is True:
57
+ punctuation_chars = '();<>|&'
58
+ self._punctuation_chars = punctuation_chars
59
+ if punctuation_chars:
60
+ # _pushback_chars is a push back queue used by lookahead logic
61
+ self._pushback_chars = deque()
62
+ # these chars added because allowed in file names, args, wildcards
63
+ self.wordchars += '~-./*?='
64
+ #remove any punctuation chars from wordchars
65
+ t = self.wordchars.maketrans(dict.fromkeys(punctuation_chars))
66
+ self.wordchars = self.wordchars.translate(t)
67
+
68
+ @property
69
+ def punctuation_chars(self):
70
+ return self._punctuation_chars
71
+
72
+ def push_token(self, tok):
73
+ "Push a token onto the stack popped by the get_token method"
74
+ if self.debug >= 1:
75
+ print("shlex: pushing token " + repr(tok))
76
+ self.pushback.appendleft(tok)
77
+
78
+ def push_source(self, newstream, newfile=None):
79
+ "Push an input source onto the lexer's input source stack."
80
+ if isinstance(newstream, str):
81
+ newstream = StringIO(newstream)
82
+ self.filestack.appendleft((self.infile, self.instream, self.lineno))
83
+ self.infile = newfile
84
+ self.instream = newstream
85
+ self.lineno = 1
86
+ if self.debug:
87
+ if newfile is not None:
88
+ print('shlex: pushing to file %s' % (self.infile,))
89
+ else:
90
+ print('shlex: pushing to stream %s' % (self.instream,))
91
+
92
+ def pop_source(self):
93
+ "Pop the input source stack."
94
+ self.instream.close()
95
+ (self.infile, self.instream, self.lineno) = self.filestack.popleft()
96
+ if self.debug:
97
+ print('shlex: popping to %s, line %d' \
98
+ % (self.instream, self.lineno))
99
+ self.state = ' '
100
+
101
+ def get_token(self):
102
+ "Get a token from the input stream (or from stack if it's nonempty)"
103
+ if self.pushback:
104
+ tok = self.pushback.popleft()
105
+ if self.debug >= 1:
106
+ print("shlex: popping token " + repr(tok))
107
+ return tok
108
+ # No pushback. Get a token.
109
+ raw = self.read_token()
110
+ # Handle inclusions
111
+ if self.source is not None:
112
+ while raw == self.source:
113
+ spec = self.sourcehook(self.read_token())
114
+ if spec:
115
+ (newfile, newstream) = spec
116
+ self.push_source(newstream, newfile)
117
+ raw = self.get_token()
118
+ # Maybe we got EOF instead?
119
+ while raw == self.eof:
120
+ if not self.filestack:
121
+ return self.eof
122
+ else:
123
+ self.pop_source()
124
+ raw = self.get_token()
125
+ # Neither inclusion nor EOF
126
+ if self.debug >= 1:
127
+ if raw != self.eof:
128
+ print("shlex: token=" + repr(raw))
129
+ else:
130
+ print("shlex: token=EOF")
131
+ return raw
132
+
133
+ def read_token(self):
134
+ quoted = False
135
+ escapedstate = ' '
136
+ while True:
137
+ if self.punctuation_chars and self._pushback_chars:
138
+ nextchar = self._pushback_chars.pop()
139
+ else:
140
+ nextchar = self.instream.read(1)
141
+ if nextchar == '\n':
142
+ self.lineno += 1
143
+ if self.debug >= 3:
144
+ print("shlex: in state %r I see character: %r" % (self.state,
145
+ nextchar))
146
+ if self.state is None:
147
+ self.token = '' # past end of file
148
+ break
149
+ elif self.state == ' ':
150
+ if not nextchar:
151
+ self.state = None # end of file
152
+ break
153
+ elif nextchar in self.whitespace:
154
+ if self.debug >= 2:
155
+ print("shlex: I see whitespace in whitespace state")
156
+ if self.token or (self.posix and quoted):
157
+ break # emit current token
158
+ else:
159
+ continue
160
+ elif nextchar in self.commenters:
161
+ self.instream.readline()
162
+ self.lineno += 1
163
+ elif self.posix and nextchar in self.escape:
164
+ escapedstate = 'a'
165
+ self.state = nextchar
166
+ elif nextchar in self.wordchars:
167
+ self.token = nextchar
168
+ self.state = 'a'
169
+ elif nextchar in self.punctuation_chars:
170
+ self.token = nextchar
171
+ self.state = 'c'
172
+ elif nextchar in self.quotes:
173
+ if not self.posix:
174
+ self.token = nextchar
175
+ self.state = nextchar
176
+ elif self.whitespace_split:
177
+ self.token = nextchar
178
+ self.state = 'a'
179
+ else:
180
+ self.token = nextchar
181
+ if self.token or (self.posix and quoted):
182
+ break # emit current token
183
+ else:
184
+ continue
185
+ elif self.state in self.quotes:
186
+ quoted = True
187
+ if not nextchar: # end of file
188
+ if self.debug >= 2:
189
+ print("shlex: I see EOF in quotes state")
190
+ # XXX what error should be raised here?
191
+ raise ValueError("No closing quotation")
192
+ if nextchar == self.state:
193
+ if not self.posix:
194
+ self.token += nextchar
195
+ self.state = ' '
196
+ break
197
+ else:
198
+ self.state = 'a'
199
+ elif (self.posix and nextchar in self.escape and self.state
200
+ in self.escapedquotes):
201
+ escapedstate = self.state
202
+ self.state = nextchar
203
+ else:
204
+ self.token += nextchar
205
+ elif self.state in self.escape:
206
+ if not nextchar: # end of file
207
+ if self.debug >= 2:
208
+ print("shlex: I see EOF in escape state")
209
+ # XXX what error should be raised here?
210
+ raise ValueError("No escaped character")
211
+ # In posix shells, only the quote itself or the escape
212
+ # character may be escaped within quotes.
213
+ if (escapedstate in self.quotes and
214
+ nextchar != self.state and nextchar != escapedstate):
215
+ self.token += self.state
216
+ self.token += nextchar
217
+ self.state = escapedstate
218
+ elif self.state in ('a', 'c'):
219
+ if not nextchar:
220
+ self.state = None # end of file
221
+ break
222
+ elif nextchar in self.whitespace:
223
+ if self.debug >= 2:
224
+ print("shlex: I see whitespace in word state")
225
+ self.state = ' '
226
+ if self.token or (self.posix and quoted):
227
+ break # emit current token
228
+ else:
229
+ continue
230
+ elif nextchar in self.commenters:
231
+ self.instream.readline()
232
+ self.lineno += 1
233
+ if self.posix:
234
+ self.state = ' '
235
+ if self.token or (self.posix and quoted):
236
+ break # emit current token
237
+ else:
238
+ continue
239
+ elif self.state == 'c':
240
+ if nextchar in self.punctuation_chars:
241
+ self.token += nextchar
242
+ else:
243
+ if nextchar not in self.whitespace:
244
+ self._pushback_chars.append(nextchar)
245
+ self.state = ' '
246
+ break
247
+ elif self.posix and nextchar in self.quotes:
248
+ self.state = nextchar
249
+ elif self.posix and nextchar in self.escape:
250
+ escapedstate = 'a'
251
+ self.state = nextchar
252
+ elif (nextchar in self.wordchars or nextchar in self.quotes
253
+ or (self.whitespace_split and
254
+ nextchar not in self.punctuation_chars)):
255
+ self.token += nextchar
256
+ else:
257
+ if self.punctuation_chars:
258
+ self._pushback_chars.append(nextchar)
259
+ else:
260
+ self.pushback.appendleft(nextchar)
261
+ if self.debug >= 2:
262
+ print("shlex: I see punctuation in word state")
263
+ self.state = ' '
264
+ if self.token or (self.posix and quoted):
265
+ break # emit current token
266
+ else:
267
+ continue
268
+ result = self.token
269
+ self.token = ''
270
+ if self.posix and not quoted and result == '':
271
+ result = None
272
+ if self.debug > 1:
273
+ if result:
274
+ print("shlex: raw token=" + repr(result))
275
+ else:
276
+ print("shlex: raw token=EOF")
277
+ return result
278
+
279
+ def sourcehook(self, newfile):
280
+ "Hook called on a filename to be sourced."
281
+ if newfile[0] == '"':
282
+ newfile = newfile[1:-1]
283
+ # This implements cpp-like semantics for relative-path inclusion.
284
+ if isinstance(self.infile, str) and not os.path.isabs(newfile):
285
+ newfile = os.path.join(os.path.dirname(self.infile), newfile)
286
+ return (newfile, open(newfile, "r"))
287
+
288
+ def error_leader(self, infile=None, lineno=None):
289
+ "Emit a C-compiler-like, Emacs-friendly error-message leader."
290
+ if infile is None:
291
+ infile = self.infile
292
+ if lineno is None:
293
+ lineno = self.lineno
294
+ return "\"%s\", line %d: " % (infile, lineno)
295
+
296
+ def __iter__(self):
297
+ return self
298
+
299
+ def __next__(self):
300
+ token = self.get_token()
301
+ if token == self.eof:
302
+ raise StopIteration
303
+ return token
304
+
305
+ def split(s, comments=False, posix=True):
306
+ """Split the string *s* using shell-like syntax."""
307
+ if s is None:
308
+ import warnings
309
+ warnings.warn("Passing None for 's' to shlex.split() is deprecated.",
310
+ DeprecationWarning, stacklevel=2)
311
+ lex = shlex(s, posix=posix)
312
+ lex.whitespace_split = True
313
+ if not comments:
314
+ lex.commenters = ''
315
+ return list(lex)
316
+
317
+
318
+ def join(split_command):
319
+ """Return a shell-escaped string from *split_command*."""
320
+ return ' '.join(quote(arg) for arg in split_command)
321
+
322
+
323
+ _find_unsafe = re.compile(r'[^\w@%+=:,./-]', re.ASCII).search
324
+
325
+ def quote(s):
326
+ """Return a shell-escaped version of the string *s*."""
327
+ if not s:
328
+ return "''"
329
+ if _find_unsafe(s) is None:
330
+ return s
331
+
332
+ # use single quotes, and put single quotes into double quotes
333
+ # the string $'b is then quoted as '$'"'"'b'
334
+ return "'" + s.replace("'", "'\"'\"'") + "'"
335
+
336
+
337
+ def _print_tokens(lexer):
338
+ while 1:
339
+ tt = lexer.get_token()
340
+ if not tt:
341
+ break
342
+ print("Token: " + repr(tt))
343
+
344
+ if __name__ == '__main__':
345
+ if len(sys.argv) == 1:
346
+ _print_tokens(shlex())
347
+ else:
348
+ fn = sys.argv[1]
349
+ with open(fn) as f:
350
+ _print_tokens(shlex(f, fn))
lib/python3.10/shutil.py ADDED
@@ -0,0 +1,1517 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Utility functions for copying and archiving files and directory trees.
2
+
3
+ XXX The functions here don't copy the resource fork or other metadata on Mac.
4
+
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import stat
10
+ import fnmatch
11
+ import collections
12
+ import errno
13
+
14
+ try:
15
+ import zlib
16
+ del zlib
17
+ _ZLIB_SUPPORTED = True
18
+ except ImportError:
19
+ _ZLIB_SUPPORTED = False
20
+
21
+ try:
22
+ import bz2
23
+ del bz2
24
+ _BZ2_SUPPORTED = True
25
+ except ImportError:
26
+ _BZ2_SUPPORTED = False
27
+
28
+ try:
29
+ import lzma
30
+ del lzma
31
+ _LZMA_SUPPORTED = True
32
+ except ImportError:
33
+ _LZMA_SUPPORTED = False
34
+
35
+ _WINDOWS = os.name == 'nt'
36
+ posix = nt = None
37
+ if os.name == 'posix':
38
+ import posix
39
+ elif _WINDOWS:
40
+ import nt
41
+
42
+ COPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 64 * 1024
43
+ _USE_CP_SENDFILE = hasattr(os, "sendfile") and sys.platform.startswith("linux")
44
+ _HAS_FCOPYFILE = posix and hasattr(posix, "_fcopyfile") # macOS
45
+
46
+ # CMD defaults in Windows 10
47
+ _WIN_DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC"
48
+
49
+ __all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
50
+ "copytree", "move", "rmtree", "Error", "SpecialFileError",
51
+ "ExecError", "make_archive", "get_archive_formats",
52
+ "register_archive_format", "unregister_archive_format",
53
+ "get_unpack_formats", "register_unpack_format",
54
+ "unregister_unpack_format", "unpack_archive",
55
+ "ignore_patterns", "chown", "which", "get_terminal_size",
56
+ "SameFileError"]
57
+ # disk_usage is added later, if available on the platform
58
+
59
+ class Error(OSError):
60
+ pass
61
+
62
+ class SameFileError(Error):
63
+ """Raised when source and destination are the same file."""
64
+
65
+ class SpecialFileError(OSError):
66
+ """Raised when trying to do a kind of operation (e.g. copying) which is
67
+ not supported on a special file (e.g. a named pipe)"""
68
+
69
+ class ExecError(OSError):
70
+ """Raised when a command could not be executed"""
71
+
72
+ class ReadError(OSError):
73
+ """Raised when an archive cannot be read"""
74
+
75
+ class RegistryError(Exception):
76
+ """Raised when a registry operation with the archiving
77
+ and unpacking registries fails"""
78
+
79
+ class _GiveupOnFastCopy(Exception):
80
+ """Raised as a signal to fallback on using raw read()/write()
81
+ file copy when fast-copy functions fail to do so.
82
+ """
83
+
84
+ def _fastcopy_fcopyfile(fsrc, fdst, flags):
85
+ """Copy a regular file content or metadata by using high-performance
86
+ fcopyfile(3) syscall (macOS).
87
+ """
88
+ try:
89
+ infd = fsrc.fileno()
90
+ outfd = fdst.fileno()
91
+ except Exception as err:
92
+ raise _GiveupOnFastCopy(err) # not a regular file
93
+
94
+ try:
95
+ posix._fcopyfile(infd, outfd, flags)
96
+ except OSError as err:
97
+ err.filename = fsrc.name
98
+ err.filename2 = fdst.name
99
+ if err.errno in {errno.EINVAL, errno.ENOTSUP}:
100
+ raise _GiveupOnFastCopy(err)
101
+ else:
102
+ raise err from None
103
+
104
+ def _fastcopy_sendfile(fsrc, fdst):
105
+ """Copy data from one regular mmap-like fd to another by using
106
+ high-performance sendfile(2) syscall.
107
+ This should work on Linux >= 2.6.33 only.
108
+ """
109
+ # Note: copyfileobj() is left alone in order to not introduce any
110
+ # unexpected breakage. Possible risks by using zero-copy calls
111
+ # in copyfileobj() are:
112
+ # - fdst cannot be open in "a"(ppend) mode
113
+ # - fsrc and fdst may be open in "t"(ext) mode
114
+ # - fsrc may be a BufferedReader (which hides unread data in a buffer),
115
+ # GzipFile (which decompresses data), HTTPResponse (which decodes
116
+ # chunks).
117
+ # - possibly others (e.g. encrypted fs/partition?)
118
+ global _USE_CP_SENDFILE
119
+ try:
120
+ infd = fsrc.fileno()
121
+ outfd = fdst.fileno()
122
+ except Exception as err:
123
+ raise _GiveupOnFastCopy(err) # not a regular file
124
+
125
+ # Hopefully the whole file will be copied in a single call.
126
+ # sendfile() is called in a loop 'till EOF is reached (0 return)
127
+ # so a bufsize smaller or bigger than the actual file size
128
+ # should not make any difference, also in case the file content
129
+ # changes while being copied.
130
+ try:
131
+ blocksize = max(os.fstat(infd).st_size, 2 ** 23) # min 8MiB
132
+ except OSError:
133
+ blocksize = 2 ** 27 # 128MiB
134
+ # On 32-bit architectures truncate to 1GiB to avoid OverflowError,
135
+ # see bpo-38319.
136
+ if sys.maxsize < 2 ** 32:
137
+ blocksize = min(blocksize, 2 ** 30)
138
+
139
+ offset = 0
140
+ while True:
141
+ try:
142
+ sent = os.sendfile(outfd, infd, offset, blocksize)
143
+ except OSError as err:
144
+ # ...in oder to have a more informative exception.
145
+ err.filename = fsrc.name
146
+ err.filename2 = fdst.name
147
+
148
+ if err.errno == errno.ENOTSOCK:
149
+ # sendfile() on this platform (probably Linux < 2.6.33)
150
+ # does not support copies between regular files (only
151
+ # sockets).
152
+ _USE_CP_SENDFILE = False
153
+ raise _GiveupOnFastCopy(err)
154
+
155
+ if err.errno == errno.ENOSPC: # filesystem is full
156
+ raise err from None
157
+
158
+ # Give up on first call and if no data was copied.
159
+ if offset == 0 and os.lseek(outfd, 0, os.SEEK_CUR) == 0:
160
+ raise _GiveupOnFastCopy(err)
161
+
162
+ raise err
163
+ else:
164
+ if sent == 0:
165
+ break # EOF
166
+ offset += sent
167
+
168
+ def _copyfileobj_readinto(fsrc, fdst, length=COPY_BUFSIZE):
169
+ """readinto()/memoryview() based variant of copyfileobj().
170
+ *fsrc* must support readinto() method and both files must be
171
+ open in binary mode.
172
+ """
173
+ # Localize variable access to minimize overhead.
174
+ fsrc_readinto = fsrc.readinto
175
+ fdst_write = fdst.write
176
+ with memoryview(bytearray(length)) as mv:
177
+ while True:
178
+ n = fsrc_readinto(mv)
179
+ if not n:
180
+ break
181
+ elif n < length:
182
+ with mv[:n] as smv:
183
+ fdst.write(smv)
184
+ else:
185
+ fdst_write(mv)
186
+
187
+ def copyfileobj(fsrc, fdst, length=0):
188
+ """copy data from file-like object fsrc to file-like object fdst"""
189
+ # Localize variable access to minimize overhead.
190
+ if not length:
191
+ length = COPY_BUFSIZE
192
+ fsrc_read = fsrc.read
193
+ fdst_write = fdst.write
194
+ while True:
195
+ buf = fsrc_read(length)
196
+ if not buf:
197
+ break
198
+ fdst_write(buf)
199
+
200
+ def _samefile(src, dst):
201
+ # Macintosh, Unix.
202
+ if isinstance(src, os.DirEntry) and hasattr(os.path, 'samestat'):
203
+ try:
204
+ return os.path.samestat(src.stat(), os.stat(dst))
205
+ except OSError:
206
+ return False
207
+
208
+ if hasattr(os.path, 'samefile'):
209
+ try:
210
+ return os.path.samefile(src, dst)
211
+ except OSError:
212
+ return False
213
+
214
+ # All other platforms: check for same pathname.
215
+ return (os.path.normcase(os.path.abspath(src)) ==
216
+ os.path.normcase(os.path.abspath(dst)))
217
+
218
+ def _stat(fn):
219
+ return fn.stat() if isinstance(fn, os.DirEntry) else os.stat(fn)
220
+
221
+ def _islink(fn):
222
+ return fn.is_symlink() if isinstance(fn, os.DirEntry) else os.path.islink(fn)
223
+
224
+ def copyfile(src, dst, *, follow_symlinks=True):
225
+ """Copy data from src to dst in the most efficient way possible.
226
+
227
+ If follow_symlinks is not set and src is a symbolic link, a new
228
+ symlink will be created instead of copying the file it points to.
229
+
230
+ """
231
+ sys.audit("shutil.copyfile", src, dst)
232
+
233
+ if _samefile(src, dst):
234
+ raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
235
+
236
+ file_size = 0
237
+ for i, fn in enumerate([src, dst]):
238
+ try:
239
+ st = _stat(fn)
240
+ except OSError:
241
+ # File most likely does not exist
242
+ pass
243
+ else:
244
+ # XXX What about other special files? (sockets, devices...)
245
+ if stat.S_ISFIFO(st.st_mode):
246
+ fn = fn.path if isinstance(fn, os.DirEntry) else fn
247
+ raise SpecialFileError("`%s` is a named pipe" % fn)
248
+ if _WINDOWS and i == 0:
249
+ file_size = st.st_size
250
+
251
+ if not follow_symlinks and _islink(src):
252
+ os.symlink(os.readlink(src), dst)
253
+ else:
254
+ with open(src, 'rb') as fsrc:
255
+ try:
256
+ with open(dst, 'wb') as fdst:
257
+ # macOS
258
+ if _HAS_FCOPYFILE:
259
+ try:
260
+ _fastcopy_fcopyfile(fsrc, fdst, posix._COPYFILE_DATA)
261
+ return dst
262
+ except _GiveupOnFastCopy:
263
+ pass
264
+ # Linux
265
+ elif _USE_CP_SENDFILE:
266
+ try:
267
+ _fastcopy_sendfile(fsrc, fdst)
268
+ return dst
269
+ except _GiveupOnFastCopy:
270
+ pass
271
+ # Windows, see:
272
+ # https://github.com/python/cpython/pull/7160#discussion_r195405230
273
+ elif _WINDOWS and file_size > 0:
274
+ _copyfileobj_readinto(fsrc, fdst, min(file_size, COPY_BUFSIZE))
275
+ return dst
276
+
277
+ copyfileobj(fsrc, fdst)
278
+
279
+ # Issue 43219, raise a less confusing exception
280
+ except IsADirectoryError as e:
281
+ if not os.path.exists(dst):
282
+ raise FileNotFoundError(f'Directory does not exist: {dst}') from e
283
+ else:
284
+ raise
285
+
286
+ return dst
287
+
288
+ def copymode(src, dst, *, follow_symlinks=True):
289
+ """Copy mode bits from src to dst.
290
+
291
+ If follow_symlinks is not set, symlinks aren't followed if and only
292
+ if both `src` and `dst` are symlinks. If `lchmod` isn't available
293
+ (e.g. Linux) this method does nothing.
294
+
295
+ """
296
+ sys.audit("shutil.copymode", src, dst)
297
+
298
+ if not follow_symlinks and _islink(src) and os.path.islink(dst):
299
+ if hasattr(os, 'lchmod'):
300
+ stat_func, chmod_func = os.lstat, os.lchmod
301
+ else:
302
+ return
303
+ else:
304
+ stat_func, chmod_func = _stat, os.chmod
305
+
306
+ st = stat_func(src)
307
+ chmod_func(dst, stat.S_IMODE(st.st_mode))
308
+
309
+ if hasattr(os, 'listxattr'):
310
+ def _copyxattr(src, dst, *, follow_symlinks=True):
311
+ """Copy extended filesystem attributes from `src` to `dst`.
312
+
313
+ Overwrite existing attributes.
314
+
315
+ If `follow_symlinks` is false, symlinks won't be followed.
316
+
317
+ """
318
+
319
+ try:
320
+ names = os.listxattr(src, follow_symlinks=follow_symlinks)
321
+ except OSError as e:
322
+ if e.errno not in (errno.ENOTSUP, errno.ENODATA, errno.EINVAL):
323
+ raise
324
+ return
325
+ for name in names:
326
+ try:
327
+ value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
328
+ os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
329
+ except OSError as e:
330
+ if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA,
331
+ errno.EINVAL):
332
+ raise
333
+ else:
334
+ def _copyxattr(*args, **kwargs):
335
+ pass
336
+
337
+ def copystat(src, dst, *, follow_symlinks=True):
338
+ """Copy file metadata
339
+
340
+ Copy the permission bits, last access time, last modification time, and
341
+ flags from `src` to `dst`. On Linux, copystat() also copies the "extended
342
+ attributes" where possible. The file contents, owner, and group are
343
+ unaffected. `src` and `dst` are path-like objects or path names given as
344
+ strings.
345
+
346
+ If the optional flag `follow_symlinks` is not set, symlinks aren't
347
+ followed if and only if both `src` and `dst` are symlinks.
348
+ """
349
+ sys.audit("shutil.copystat", src, dst)
350
+
351
+ def _nop(*args, ns=None, follow_symlinks=None):
352
+ pass
353
+
354
+ # follow symlinks (aka don't not follow symlinks)
355
+ follow = follow_symlinks or not (_islink(src) and os.path.islink(dst))
356
+ if follow:
357
+ # use the real function if it exists
358
+ def lookup(name):
359
+ return getattr(os, name, _nop)
360
+ else:
361
+ # use the real function only if it exists
362
+ # *and* it supports follow_symlinks
363
+ def lookup(name):
364
+ fn = getattr(os, name, _nop)
365
+ if fn in os.supports_follow_symlinks:
366
+ return fn
367
+ return _nop
368
+
369
+ if isinstance(src, os.DirEntry):
370
+ st = src.stat(follow_symlinks=follow)
371
+ else:
372
+ st = lookup("stat")(src, follow_symlinks=follow)
373
+ mode = stat.S_IMODE(st.st_mode)
374
+ lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
375
+ follow_symlinks=follow)
376
+ # We must copy extended attributes before the file is (potentially)
377
+ # chmod()'ed read-only, otherwise setxattr() will error with -EACCES.
378
+ _copyxattr(src, dst, follow_symlinks=follow)
379
+ try:
380
+ lookup("chmod")(dst, mode, follow_symlinks=follow)
381
+ except NotImplementedError:
382
+ # if we got a NotImplementedError, it's because
383
+ # * follow_symlinks=False,
384
+ # * lchown() is unavailable, and
385
+ # * either
386
+ # * fchownat() is unavailable or
387
+ # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
388
+ # (it returned ENOSUP.)
389
+ # therefore we're out of options--we simply cannot chown the
390
+ # symlink. give up, suppress the error.
391
+ # (which is what shutil always did in this circumstance.)
392
+ pass
393
+ if hasattr(st, 'st_flags'):
394
+ try:
395
+ lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
396
+ except OSError as why:
397
+ for err in 'EOPNOTSUPP', 'ENOTSUP':
398
+ if hasattr(errno, err) and why.errno == getattr(errno, err):
399
+ break
400
+ else:
401
+ raise
402
+
403
+ def copy(src, dst, *, follow_symlinks=True):
404
+ """Copy data and mode bits ("cp src dst"). Return the file's destination.
405
+
406
+ The destination may be a directory.
407
+
408
+ If follow_symlinks is false, symlinks won't be followed. This
409
+ resembles GNU's "cp -P src dst".
410
+
411
+ If source and destination are the same file, a SameFileError will be
412
+ raised.
413
+
414
+ """
415
+ if os.path.isdir(dst):
416
+ dst = os.path.join(dst, os.path.basename(src))
417
+ copyfile(src, dst, follow_symlinks=follow_symlinks)
418
+ copymode(src, dst, follow_symlinks=follow_symlinks)
419
+ return dst
420
+
421
+ def copy2(src, dst, *, follow_symlinks=True):
422
+ """Copy data and metadata. Return the file's destination.
423
+
424
+ Metadata is copied with copystat(). Please see the copystat function
425
+ for more information.
426
+
427
+ The destination may be a directory.
428
+
429
+ If follow_symlinks is false, symlinks won't be followed. This
430
+ resembles GNU's "cp -P src dst".
431
+ """
432
+ if os.path.isdir(dst):
433
+ dst = os.path.join(dst, os.path.basename(src))
434
+ copyfile(src, dst, follow_symlinks=follow_symlinks)
435
+ copystat(src, dst, follow_symlinks=follow_symlinks)
436
+ return dst
437
+
438
+ def ignore_patterns(*patterns):
439
+ """Function that can be used as copytree() ignore parameter.
440
+
441
+ Patterns is a sequence of glob-style patterns
442
+ that are used to exclude files"""
443
+ def _ignore_patterns(path, names):
444
+ ignored_names = []
445
+ for pattern in patterns:
446
+ ignored_names.extend(fnmatch.filter(names, pattern))
447
+ return set(ignored_names)
448
+ return _ignore_patterns
449
+
450
+ def _copytree(entries, src, dst, symlinks, ignore, copy_function,
451
+ ignore_dangling_symlinks, dirs_exist_ok=False):
452
+ if ignore is not None:
453
+ ignored_names = ignore(os.fspath(src), [x.name for x in entries])
454
+ else:
455
+ ignored_names = set()
456
+
457
+ os.makedirs(dst, exist_ok=dirs_exist_ok)
458
+ errors = []
459
+ use_srcentry = copy_function is copy2 or copy_function is copy
460
+
461
+ for srcentry in entries:
462
+ if srcentry.name in ignored_names:
463
+ continue
464
+ srcname = os.path.join(src, srcentry.name)
465
+ dstname = os.path.join(dst, srcentry.name)
466
+ srcobj = srcentry if use_srcentry else srcname
467
+ try:
468
+ is_symlink = srcentry.is_symlink()
469
+ if is_symlink and os.name == 'nt':
470
+ # Special check for directory junctions, which appear as
471
+ # symlinks but we want to recurse.
472
+ lstat = srcentry.stat(follow_symlinks=False)
473
+ if lstat.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT:
474
+ is_symlink = False
475
+ if is_symlink:
476
+ linkto = os.readlink(srcname)
477
+ if symlinks:
478
+ # We can't just leave it to `copy_function` because legacy
479
+ # code with a custom `copy_function` may rely on copytree
480
+ # doing the right thing.
481
+ os.symlink(linkto, dstname)
482
+ copystat(srcobj, dstname, follow_symlinks=not symlinks)
483
+ else:
484
+ # ignore dangling symlink if the flag is on
485
+ if not os.path.exists(linkto) and ignore_dangling_symlinks:
486
+ continue
487
+ # otherwise let the copy occur. copy2 will raise an error
488
+ if srcentry.is_dir():
489
+ copytree(srcobj, dstname, symlinks, ignore,
490
+ copy_function, ignore_dangling_symlinks,
491
+ dirs_exist_ok)
492
+ else:
493
+ copy_function(srcobj, dstname)
494
+ elif srcentry.is_dir():
495
+ copytree(srcobj, dstname, symlinks, ignore, copy_function,
496
+ ignore_dangling_symlinks, dirs_exist_ok)
497
+ else:
498
+ # Will raise a SpecialFileError for unsupported file types
499
+ copy_function(srcobj, dstname)
500
+ # catch the Error from the recursive copytree so that we can
501
+ # continue with other files
502
+ except Error as err:
503
+ errors.extend(err.args[0])
504
+ except OSError as why:
505
+ errors.append((srcname, dstname, str(why)))
506
+ try:
507
+ copystat(src, dst)
508
+ except OSError as why:
509
+ # Copying file access times may fail on Windows
510
+ if getattr(why, 'winerror', None) is None:
511
+ errors.append((src, dst, str(why)))
512
+ if errors:
513
+ raise Error(errors)
514
+ return dst
515
+
516
+ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
517
+ ignore_dangling_symlinks=False, dirs_exist_ok=False):
518
+ """Recursively copy a directory tree and return the destination directory.
519
+
520
+ If exception(s) occur, an Error is raised with a list of reasons.
521
+
522
+ If the optional symlinks flag is true, symbolic links in the
523
+ source tree result in symbolic links in the destination tree; if
524
+ it is false, the contents of the files pointed to by symbolic
525
+ links are copied. If the file pointed by the symlink doesn't
526
+ exist, an exception will be added in the list of errors raised in
527
+ an Error exception at the end of the copy process.
528
+
529
+ You can set the optional ignore_dangling_symlinks flag to true if you
530
+ want to silence this exception. Notice that this has no effect on
531
+ platforms that don't support os.symlink.
532
+
533
+ The optional ignore argument is a callable. If given, it
534
+ is called with the `src` parameter, which is the directory
535
+ being visited by copytree(), and `names` which is the list of
536
+ `src` contents, as returned by os.listdir():
537
+
538
+ callable(src, names) -> ignored_names
539
+
540
+ Since copytree() is called recursively, the callable will be
541
+ called once for each directory that is copied. It returns a
542
+ list of names relative to the `src` directory that should
543
+ not be copied.
544
+
545
+ The optional copy_function argument is a callable that will be used
546
+ to copy each file. It will be called with the source path and the
547
+ destination path as arguments. By default, copy2() is used, but any
548
+ function that supports the same signature (like copy()) can be used.
549
+
550
+ If dirs_exist_ok is false (the default) and `dst` already exists, a
551
+ `FileExistsError` is raised. If `dirs_exist_ok` is true, the copying
552
+ operation will continue if it encounters existing directories, and files
553
+ within the `dst` tree will be overwritten by corresponding files from the
554
+ `src` tree.
555
+ """
556
+ sys.audit("shutil.copytree", src, dst)
557
+ with os.scandir(src) as itr:
558
+ entries = list(itr)
559
+ return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
560
+ ignore=ignore, copy_function=copy_function,
561
+ ignore_dangling_symlinks=ignore_dangling_symlinks,
562
+ dirs_exist_ok=dirs_exist_ok)
563
+
564
+ if hasattr(os.stat_result, 'st_file_attributes'):
565
+ # Special handling for directory junctions to make them behave like
566
+ # symlinks for shutil.rmtree, since in general they do not appear as
567
+ # regular links.
568
+ def _rmtree_isdir(entry):
569
+ try:
570
+ st = entry.stat(follow_symlinks=False)
571
+ return (stat.S_ISDIR(st.st_mode) and not
572
+ (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
573
+ and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
574
+ except OSError:
575
+ return False
576
+
577
+ def _rmtree_islink(path):
578
+ try:
579
+ st = os.lstat(path)
580
+ return (stat.S_ISLNK(st.st_mode) or
581
+ (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
582
+ and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
583
+ except OSError:
584
+ return False
585
+ else:
586
+ def _rmtree_isdir(entry):
587
+ try:
588
+ return entry.is_dir(follow_symlinks=False)
589
+ except OSError:
590
+ return False
591
+
592
+ def _rmtree_islink(path):
593
+ return os.path.islink(path)
594
+
595
+ # version vulnerable to race conditions
596
+ def _rmtree_unsafe(path, onerror):
597
+ try:
598
+ with os.scandir(path) as scandir_it:
599
+ entries = list(scandir_it)
600
+ except OSError:
601
+ onerror(os.scandir, path, sys.exc_info())
602
+ entries = []
603
+ for entry in entries:
604
+ fullname = entry.path
605
+ if _rmtree_isdir(entry):
606
+ try:
607
+ if entry.is_symlink():
608
+ # This can only happen if someone replaces
609
+ # a directory with a symlink after the call to
610
+ # os.scandir or entry.is_dir above.
611
+ raise OSError("Cannot call rmtree on a symbolic link")
612
+ except OSError:
613
+ onerror(os.path.islink, fullname, sys.exc_info())
614
+ continue
615
+ _rmtree_unsafe(fullname, onerror)
616
+ else:
617
+ try:
618
+ os.unlink(fullname)
619
+ except OSError:
620
+ onerror(os.unlink, fullname, sys.exc_info())
621
+ try:
622
+ os.rmdir(path)
623
+ except OSError:
624
+ onerror(os.rmdir, path, sys.exc_info())
625
+
626
+ # Version using fd-based APIs to protect against races
627
+ def _rmtree_safe_fd(topfd, path, onerror):
628
+ try:
629
+ with os.scandir(topfd) as scandir_it:
630
+ entries = list(scandir_it)
631
+ except OSError as err:
632
+ err.filename = path
633
+ onerror(os.scandir, path, sys.exc_info())
634
+ return
635
+ for entry in entries:
636
+ fullname = os.path.join(path, entry.name)
637
+ try:
638
+ is_dir = entry.is_dir(follow_symlinks=False)
639
+ except OSError:
640
+ is_dir = False
641
+ else:
642
+ if is_dir:
643
+ try:
644
+ orig_st = entry.stat(follow_symlinks=False)
645
+ is_dir = stat.S_ISDIR(orig_st.st_mode)
646
+ except OSError:
647
+ onerror(os.lstat, fullname, sys.exc_info())
648
+ continue
649
+ if is_dir:
650
+ try:
651
+ dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
652
+ dirfd_closed = False
653
+ except OSError:
654
+ onerror(os.open, fullname, sys.exc_info())
655
+ else:
656
+ try:
657
+ if os.path.samestat(orig_st, os.fstat(dirfd)):
658
+ _rmtree_safe_fd(dirfd, fullname, onerror)
659
+ try:
660
+ os.close(dirfd)
661
+ dirfd_closed = True
662
+ os.rmdir(entry.name, dir_fd=topfd)
663
+ except OSError:
664
+ onerror(os.rmdir, fullname, sys.exc_info())
665
+ else:
666
+ try:
667
+ # This can only happen if someone replaces
668
+ # a directory with a symlink after the call to
669
+ # os.scandir or stat.S_ISDIR above.
670
+ raise OSError("Cannot call rmtree on a symbolic "
671
+ "link")
672
+ except OSError:
673
+ onerror(os.path.islink, fullname, sys.exc_info())
674
+ finally:
675
+ if not dirfd_closed:
676
+ os.close(dirfd)
677
+ else:
678
+ try:
679
+ os.unlink(entry.name, dir_fd=topfd)
680
+ except OSError:
681
+ onerror(os.unlink, fullname, sys.exc_info())
682
+
683
+ _use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
684
+ os.supports_dir_fd and
685
+ os.scandir in os.supports_fd and
686
+ os.stat in os.supports_follow_symlinks)
687
+
688
+ def rmtree(path, ignore_errors=False, onerror=None):
689
+ """Recursively delete a directory tree.
690
+
691
+ If ignore_errors is set, errors are ignored; otherwise, if onerror
692
+ is set, it is called to handle the error with arguments (func,
693
+ path, exc_info) where func is platform and implementation dependent;
694
+ path is the argument to that function that caused it to fail; and
695
+ exc_info is a tuple returned by sys.exc_info(). If ignore_errors
696
+ is false and onerror is None, an exception is raised.
697
+
698
+ """
699
+ sys.audit("shutil.rmtree", path)
700
+ if ignore_errors:
701
+ def onerror(*args):
702
+ pass
703
+ elif onerror is None:
704
+ def onerror(*args):
705
+ raise
706
+ if _use_fd_functions:
707
+ # While the unsafe rmtree works fine on bytes, the fd based does not.
708
+ if isinstance(path, bytes):
709
+ path = os.fsdecode(path)
710
+ # Note: To guard against symlink races, we use the standard
711
+ # lstat()/open()/fstat() trick.
712
+ try:
713
+ orig_st = os.lstat(path)
714
+ except Exception:
715
+ onerror(os.lstat, path, sys.exc_info())
716
+ return
717
+ try:
718
+ fd = os.open(path, os.O_RDONLY)
719
+ fd_closed = False
720
+ except Exception:
721
+ onerror(os.open, path, sys.exc_info())
722
+ return
723
+ try:
724
+ if os.path.samestat(orig_st, os.fstat(fd)):
725
+ _rmtree_safe_fd(fd, path, onerror)
726
+ try:
727
+ os.close(fd)
728
+ fd_closed = True
729
+ os.rmdir(path)
730
+ except OSError:
731
+ onerror(os.rmdir, path, sys.exc_info())
732
+ else:
733
+ try:
734
+ # symlinks to directories are forbidden, see bug #1669
735
+ raise OSError("Cannot call rmtree on a symbolic link")
736
+ except OSError:
737
+ onerror(os.path.islink, path, sys.exc_info())
738
+ finally:
739
+ if not fd_closed:
740
+ os.close(fd)
741
+ else:
742
+ try:
743
+ if _rmtree_islink(path):
744
+ # symlinks to directories are forbidden, see bug #1669
745
+ raise OSError("Cannot call rmtree on a symbolic link")
746
+ except OSError:
747
+ onerror(os.path.islink, path, sys.exc_info())
748
+ # can't continue even if onerror hook returns
749
+ return
750
+ return _rmtree_unsafe(path, onerror)
751
+
752
+ # Allow introspection of whether or not the hardening against symlink
753
+ # attacks is supported on the current platform
754
+ rmtree.avoids_symlink_attacks = _use_fd_functions
755
+
756
+ def _basename(path):
757
+ """A basename() variant which first strips the trailing slash, if present.
758
+ Thus we always get the last component of the path, even for directories.
759
+
760
+ path: Union[PathLike, str]
761
+
762
+ e.g.
763
+ >>> os.path.basename('/bar/foo')
764
+ 'foo'
765
+ >>> os.path.basename('/bar/foo/')
766
+ ''
767
+ >>> _basename('/bar/foo/')
768
+ 'foo'
769
+ """
770
+ path = os.fspath(path)
771
+ sep = os.path.sep + (os.path.altsep or '')
772
+ return os.path.basename(path.rstrip(sep))
773
+
774
+ def move(src, dst, copy_function=copy2):
775
+ """Recursively move a file or directory to another location. This is
776
+ similar to the Unix "mv" command. Return the file or directory's
777
+ destination.
778
+
779
+ If the destination is a directory or a symlink to a directory, the source
780
+ is moved inside the directory. The destination path must not already
781
+ exist.
782
+
783
+ If the destination already exists but is not a directory, it may be
784
+ overwritten depending on os.rename() semantics.
785
+
786
+ If the destination is on our current filesystem, then rename() is used.
787
+ Otherwise, src is copied to the destination and then removed. Symlinks are
788
+ recreated under the new name if os.rename() fails because of cross
789
+ filesystem renames.
790
+
791
+ The optional `copy_function` argument is a callable that will be used
792
+ to copy the source or it will be delegated to `copytree`.
793
+ By default, copy2() is used, but any function that supports the same
794
+ signature (like copy()) can be used.
795
+
796
+ A lot more could be done here... A look at a mv.c shows a lot of
797
+ the issues this implementation glosses over.
798
+
799
+ """
800
+ sys.audit("shutil.move", src, dst)
801
+ real_dst = dst
802
+ if os.path.isdir(dst):
803
+ if _samefile(src, dst):
804
+ # We might be on a case insensitive filesystem,
805
+ # perform the rename anyway.
806
+ os.rename(src, dst)
807
+ return
808
+
809
+ # Using _basename instead of os.path.basename is important, as we must
810
+ # ignore any trailing slash to avoid the basename returning ''
811
+ real_dst = os.path.join(dst, _basename(src))
812
+
813
+ if os.path.exists(real_dst):
814
+ raise Error("Destination path '%s' already exists" % real_dst)
815
+ try:
816
+ os.rename(src, real_dst)
817
+ except OSError:
818
+ if os.path.islink(src):
819
+ linkto = os.readlink(src)
820
+ os.symlink(linkto, real_dst)
821
+ os.unlink(src)
822
+ elif os.path.isdir(src):
823
+ if _destinsrc(src, dst):
824
+ raise Error("Cannot move a directory '%s' into itself"
825
+ " '%s'." % (src, dst))
826
+ if (_is_immutable(src)
827
+ or (not os.access(src, os.W_OK) and os.listdir(src)
828
+ and sys.platform == 'darwin')):
829
+ raise PermissionError("Cannot move the non-empty directory "
830
+ "'%s': Lacking write permission to '%s'."
831
+ % (src, src))
832
+ copytree(src, real_dst, copy_function=copy_function,
833
+ symlinks=True)
834
+ rmtree(src)
835
+ else:
836
+ copy_function(src, real_dst)
837
+ os.unlink(src)
838
+ return real_dst
839
+
840
+ def _destinsrc(src, dst):
841
+ src = os.path.abspath(src)
842
+ dst = os.path.abspath(dst)
843
+ if not src.endswith(os.path.sep):
844
+ src += os.path.sep
845
+ if not dst.endswith(os.path.sep):
846
+ dst += os.path.sep
847
+ return dst.startswith(src)
848
+
849
+ def _is_immutable(src):
850
+ st = _stat(src)
851
+ immutable_states = [stat.UF_IMMUTABLE, stat.SF_IMMUTABLE]
852
+ return hasattr(st, 'st_flags') and st.st_flags in immutable_states
853
+
854
+ def _get_gid(name):
855
+ """Returns a gid, given a group name."""
856
+ if name is None:
857
+ return None
858
+
859
+ try:
860
+ from grp import getgrnam
861
+ except ImportError:
862
+ return None
863
+
864
+ try:
865
+ result = getgrnam(name)
866
+ except KeyError:
867
+ result = None
868
+ if result is not None:
869
+ return result[2]
870
+ return None
871
+
872
+ def _get_uid(name):
873
+ """Returns an uid, given a user name."""
874
+ if name is None:
875
+ return None
876
+
877
+ try:
878
+ from pwd import getpwnam
879
+ except ImportError:
880
+ return None
881
+
882
+ try:
883
+ result = getpwnam(name)
884
+ except KeyError:
885
+ result = None
886
+ if result is not None:
887
+ return result[2]
888
+ return None
889
+
890
+ def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
891
+ owner=None, group=None, logger=None, root_dir=None):
892
+ """Create a (possibly compressed) tar file from all the files under
893
+ 'base_dir'.
894
+
895
+ 'compress' must be "gzip" (the default), "bzip2", "xz", or None.
896
+
897
+ 'owner' and 'group' can be used to define an owner and a group for the
898
+ archive that is being built. If not provided, the current owner and group
899
+ will be used.
900
+
901
+ The output tar file will be named 'base_name' + ".tar", possibly plus
902
+ the appropriate compression extension (".gz", ".bz2", or ".xz").
903
+
904
+ Returns the output filename.
905
+ """
906
+ if compress is None:
907
+ tar_compression = ''
908
+ elif _ZLIB_SUPPORTED and compress == 'gzip':
909
+ tar_compression = 'gz'
910
+ elif _BZ2_SUPPORTED and compress == 'bzip2':
911
+ tar_compression = 'bz2'
912
+ elif _LZMA_SUPPORTED and compress == 'xz':
913
+ tar_compression = 'xz'
914
+ else:
915
+ raise ValueError("bad value for 'compress', or compression format not "
916
+ "supported : {0}".format(compress))
917
+
918
+ import tarfile # late import for breaking circular dependency
919
+
920
+ compress_ext = '.' + tar_compression if compress else ''
921
+ archive_name = base_name + '.tar' + compress_ext
922
+ archive_dir = os.path.dirname(archive_name)
923
+
924
+ if archive_dir and not os.path.exists(archive_dir):
925
+ if logger is not None:
926
+ logger.info("creating %s", archive_dir)
927
+ if not dry_run:
928
+ os.makedirs(archive_dir)
929
+
930
+ # creating the tarball
931
+ if logger is not None:
932
+ logger.info('Creating tar archive')
933
+
934
+ uid = _get_uid(owner)
935
+ gid = _get_gid(group)
936
+
937
+ def _set_uid_gid(tarinfo):
938
+ if gid is not None:
939
+ tarinfo.gid = gid
940
+ tarinfo.gname = group
941
+ if uid is not None:
942
+ tarinfo.uid = uid
943
+ tarinfo.uname = owner
944
+ return tarinfo
945
+
946
+ if not dry_run:
947
+ tar = tarfile.open(archive_name, 'w|%s' % tar_compression)
948
+ arcname = base_dir
949
+ if root_dir is not None:
950
+ base_dir = os.path.join(root_dir, base_dir)
951
+ try:
952
+ tar.add(base_dir, arcname, filter=_set_uid_gid)
953
+ finally:
954
+ tar.close()
955
+
956
+ if root_dir is not None:
957
+ archive_name = os.path.abspath(archive_name)
958
+ return archive_name
959
+
960
+ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0,
961
+ logger=None, owner=None, group=None, root_dir=None):
962
+ """Create a zip file from all the files under 'base_dir'.
963
+
964
+ The output zip file will be named 'base_name' + ".zip". Returns the
965
+ name of the output zip file.
966
+ """
967
+ import zipfile # late import for breaking circular dependency
968
+
969
+ zip_filename = base_name + ".zip"
970
+ archive_dir = os.path.dirname(base_name)
971
+
972
+ if archive_dir and not os.path.exists(archive_dir):
973
+ if logger is not None:
974
+ logger.info("creating %s", archive_dir)
975
+ if not dry_run:
976
+ os.makedirs(archive_dir)
977
+
978
+ if logger is not None:
979
+ logger.info("creating '%s' and adding '%s' to it",
980
+ zip_filename, base_dir)
981
+
982
+ if not dry_run:
983
+ with zipfile.ZipFile(zip_filename, "w",
984
+ compression=zipfile.ZIP_DEFLATED) as zf:
985
+ arcname = os.path.normpath(base_dir)
986
+ if root_dir is not None:
987
+ base_dir = os.path.join(root_dir, base_dir)
988
+ base_dir = os.path.normpath(base_dir)
989
+ if arcname != os.curdir:
990
+ zf.write(base_dir, arcname)
991
+ if logger is not None:
992
+ logger.info("adding '%s'", base_dir)
993
+ for dirpath, dirnames, filenames in os.walk(base_dir):
994
+ arcdirpath = dirpath
995
+ if root_dir is not None:
996
+ arcdirpath = os.path.relpath(arcdirpath, root_dir)
997
+ arcdirpath = os.path.normpath(arcdirpath)
998
+ for name in sorted(dirnames):
999
+ path = os.path.join(dirpath, name)
1000
+ arcname = os.path.join(arcdirpath, name)
1001
+ zf.write(path, arcname)
1002
+ if logger is not None:
1003
+ logger.info("adding '%s'", path)
1004
+ for name in filenames:
1005
+ path = os.path.join(dirpath, name)
1006
+ path = os.path.normpath(path)
1007
+ if os.path.isfile(path):
1008
+ arcname = os.path.join(arcdirpath, name)
1009
+ zf.write(path, arcname)
1010
+ if logger is not None:
1011
+ logger.info("adding '%s'", path)
1012
+
1013
+ if root_dir is not None:
1014
+ zip_filename = os.path.abspath(zip_filename)
1015
+ return zip_filename
1016
+
1017
+ # Maps the name of the archive format to a tuple containing:
1018
+ # * the archiving function
1019
+ # * extra keyword arguments
1020
+ # * description
1021
+ # * does it support the root_dir argument?
1022
+ _ARCHIVE_FORMATS = {
1023
+ 'tar': (_make_tarball, [('compress', None)],
1024
+ "uncompressed tar file", True),
1025
+ }
1026
+
1027
+ if _ZLIB_SUPPORTED:
1028
+ _ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')],
1029
+ "gzip'ed tar-file", True)
1030
+ _ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file", True)
1031
+
1032
+ if _BZ2_SUPPORTED:
1033
+ _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
1034
+ "bzip2'ed tar-file", True)
1035
+
1036
+ if _LZMA_SUPPORTED:
1037
+ _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')],
1038
+ "xz'ed tar-file", True)
1039
+
1040
+ def get_archive_formats():
1041
+ """Returns a list of supported formats for archiving and unarchiving.
1042
+
1043
+ Each element of the returned sequence is a tuple (name, description)
1044
+ """
1045
+ formats = [(name, registry[2]) for name, registry in
1046
+ _ARCHIVE_FORMATS.items()]
1047
+ formats.sort()
1048
+ return formats
1049
+
1050
+ def register_archive_format(name, function, extra_args=None, description=''):
1051
+ """Registers an archive format.
1052
+
1053
+ name is the name of the format. function is the callable that will be
1054
+ used to create archives. If provided, extra_args is a sequence of
1055
+ (name, value) tuples that will be passed as arguments to the callable.
1056
+ description can be provided to describe the format, and will be returned
1057
+ by the get_archive_formats() function.
1058
+ """
1059
+ if extra_args is None:
1060
+ extra_args = []
1061
+ if not callable(function):
1062
+ raise TypeError('The %s object is not callable' % function)
1063
+ if not isinstance(extra_args, (tuple, list)):
1064
+ raise TypeError('extra_args needs to be a sequence')
1065
+ for element in extra_args:
1066
+ if not isinstance(element, (tuple, list)) or len(element) !=2:
1067
+ raise TypeError('extra_args elements are : (arg_name, value)')
1068
+
1069
+ _ARCHIVE_FORMATS[name] = (function, extra_args, description, False)
1070
+
1071
+ def unregister_archive_format(name):
1072
+ del _ARCHIVE_FORMATS[name]
1073
+
1074
+ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
1075
+ dry_run=0, owner=None, group=None, logger=None):
1076
+ """Create an archive file (eg. zip or tar).
1077
+
1078
+ 'base_name' is the name of the file to create, minus any format-specific
1079
+ extension; 'format' is the archive format: one of "zip", "tar", "gztar",
1080
+ "bztar", or "xztar". Or any other registered format.
1081
+
1082
+ 'root_dir' is a directory that will be the root directory of the
1083
+ archive; ie. we typically chdir into 'root_dir' before creating the
1084
+ archive. 'base_dir' is the directory where we start archiving from;
1085
+ ie. 'base_dir' will be the common prefix of all files and
1086
+ directories in the archive. 'root_dir' and 'base_dir' both default
1087
+ to the current directory. Returns the name of the archive file.
1088
+
1089
+ 'owner' and 'group' are used when creating a tar archive. By default,
1090
+ uses the current owner and group.
1091
+ """
1092
+ sys.audit("shutil.make_archive", base_name, format, root_dir, base_dir)
1093
+ try:
1094
+ format_info = _ARCHIVE_FORMATS[format]
1095
+ except KeyError:
1096
+ raise ValueError("unknown archive format '%s'" % format) from None
1097
+
1098
+ kwargs = {'dry_run': dry_run, 'logger': logger,
1099
+ 'owner': owner, 'group': group}
1100
+
1101
+ func = format_info[0]
1102
+ for arg, val in format_info[1]:
1103
+ kwargs[arg] = val
1104
+
1105
+ if base_dir is None:
1106
+ base_dir = os.curdir
1107
+
1108
+ support_root_dir = format_info[3]
1109
+ save_cwd = None
1110
+ if root_dir is not None:
1111
+ if support_root_dir:
1112
+ # Support path-like base_name here for backwards-compatibility.
1113
+ base_name = os.fspath(base_name)
1114
+ kwargs['root_dir'] = root_dir
1115
+ else:
1116
+ save_cwd = os.getcwd()
1117
+ if logger is not None:
1118
+ logger.debug("changing into '%s'", root_dir)
1119
+ base_name = os.path.abspath(base_name)
1120
+ if not dry_run:
1121
+ os.chdir(root_dir)
1122
+
1123
+ try:
1124
+ filename = func(base_name, base_dir, **kwargs)
1125
+ finally:
1126
+ if save_cwd is not None:
1127
+ if logger is not None:
1128
+ logger.debug("changing back to '%s'", save_cwd)
1129
+ os.chdir(save_cwd)
1130
+
1131
+ return filename
1132
+
1133
+
1134
+ def get_unpack_formats():
1135
+ """Returns a list of supported formats for unpacking.
1136
+
1137
+ Each element of the returned sequence is a tuple
1138
+ (name, extensions, description)
1139
+ """
1140
+ formats = [(name, info[0], info[3]) for name, info in
1141
+ _UNPACK_FORMATS.items()]
1142
+ formats.sort()
1143
+ return formats
1144
+
1145
+ def _check_unpack_options(extensions, function, extra_args):
1146
+ """Checks what gets registered as an unpacker."""
1147
+ # first make sure no other unpacker is registered for this extension
1148
+ existing_extensions = {}
1149
+ for name, info in _UNPACK_FORMATS.items():
1150
+ for ext in info[0]:
1151
+ existing_extensions[ext] = name
1152
+
1153
+ for extension in extensions:
1154
+ if extension in existing_extensions:
1155
+ msg = '%s is already registered for "%s"'
1156
+ raise RegistryError(msg % (extension,
1157
+ existing_extensions[extension]))
1158
+
1159
+ if not callable(function):
1160
+ raise TypeError('The registered function must be a callable')
1161
+
1162
+
1163
+ def register_unpack_format(name, extensions, function, extra_args=None,
1164
+ description=''):
1165
+ """Registers an unpack format.
1166
+
1167
+ `name` is the name of the format. `extensions` is a list of extensions
1168
+ corresponding to the format.
1169
+
1170
+ `function` is the callable that will be
1171
+ used to unpack archives. The callable will receive archives to unpack.
1172
+ If it's unable to handle an archive, it needs to raise a ReadError
1173
+ exception.
1174
+
1175
+ If provided, `extra_args` is a sequence of
1176
+ (name, value) tuples that will be passed as arguments to the callable.
1177
+ description can be provided to describe the format, and will be returned
1178
+ by the get_unpack_formats() function.
1179
+ """
1180
+ if extra_args is None:
1181
+ extra_args = []
1182
+ _check_unpack_options(extensions, function, extra_args)
1183
+ _UNPACK_FORMATS[name] = extensions, function, extra_args, description
1184
+
1185
+ def unregister_unpack_format(name):
1186
+ """Removes the pack format from the registry."""
1187
+ del _UNPACK_FORMATS[name]
1188
+
1189
+ def _ensure_directory(path):
1190
+ """Ensure that the parent directory of `path` exists"""
1191
+ dirname = os.path.dirname(path)
1192
+ if not os.path.isdir(dirname):
1193
+ os.makedirs(dirname)
1194
+
1195
+ def _unpack_zipfile(filename, extract_dir):
1196
+ """Unpack zip `filename` to `extract_dir`
1197
+ """
1198
+ import zipfile # late import for breaking circular dependency
1199
+
1200
+ if not zipfile.is_zipfile(filename):
1201
+ raise ReadError("%s is not a zip file" % filename)
1202
+
1203
+ zip = zipfile.ZipFile(filename)
1204
+ try:
1205
+ for info in zip.infolist():
1206
+ name = info.filename
1207
+
1208
+ # don't extract absolute paths or ones with .. in them
1209
+ if name.startswith('/') or '..' in name:
1210
+ continue
1211
+
1212
+ targetpath = os.path.join(extract_dir, *name.split('/'))
1213
+ if not targetpath:
1214
+ continue
1215
+
1216
+ _ensure_directory(targetpath)
1217
+ if not name.endswith('/'):
1218
+ # file
1219
+ with zip.open(name, 'r') as source, \
1220
+ open(targetpath, 'wb') as target:
1221
+ copyfileobj(source, target)
1222
+ finally:
1223
+ zip.close()
1224
+
1225
+ def _unpack_tarfile(filename, extract_dir, *, filter=None):
1226
+ """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
1227
+ """
1228
+ import tarfile # late import for breaking circular dependency
1229
+ try:
1230
+ tarobj = tarfile.open(filename)
1231
+ except tarfile.TarError:
1232
+ raise ReadError(
1233
+ "%s is not a compressed or uncompressed tar file" % filename)
1234
+ try:
1235
+ tarobj.extractall(extract_dir, filter=filter)
1236
+ finally:
1237
+ tarobj.close()
1238
+
1239
+ # Maps the name of the unpack format to a tuple containing:
1240
+ # * extensions
1241
+ # * the unpacking function
1242
+ # * extra keyword arguments
1243
+ # * description
1244
+ _UNPACK_FORMATS = {
1245
+ 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
1246
+ 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file"),
1247
+ }
1248
+
1249
+ if _ZLIB_SUPPORTED:
1250
+ _UNPACK_FORMATS['gztar'] = (['.tar.gz', '.tgz'], _unpack_tarfile, [],
1251
+ "gzip'ed tar-file")
1252
+
1253
+ if _BZ2_SUPPORTED:
1254
+ _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [],
1255
+ "bzip2'ed tar-file")
1256
+
1257
+ if _LZMA_SUPPORTED:
1258
+ _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [],
1259
+ "xz'ed tar-file")
1260
+
1261
+ def _find_unpack_format(filename):
1262
+ for name, info in _UNPACK_FORMATS.items():
1263
+ for extension in info[0]:
1264
+ if filename.endswith(extension):
1265
+ return name
1266
+ return None
1267
+
1268
+ def unpack_archive(filename, extract_dir=None, format=None, *, filter=None):
1269
+ """Unpack an archive.
1270
+
1271
+ `filename` is the name of the archive.
1272
+
1273
+ `extract_dir` is the name of the target directory, where the archive
1274
+ is unpacked. If not provided, the current working directory is used.
1275
+
1276
+ `format` is the archive format: one of "zip", "tar", "gztar", "bztar",
1277
+ or "xztar". Or any other registered format. If not provided,
1278
+ unpack_archive will use the filename extension and see if an unpacker
1279
+ was registered for that extension.
1280
+
1281
+ In case none is found, a ValueError is raised.
1282
+
1283
+ If `filter` is given, it is passed to the underlying
1284
+ extraction function.
1285
+ """
1286
+ sys.audit("shutil.unpack_archive", filename, extract_dir, format)
1287
+
1288
+ if extract_dir is None:
1289
+ extract_dir = os.getcwd()
1290
+
1291
+ extract_dir = os.fspath(extract_dir)
1292
+ filename = os.fspath(filename)
1293
+
1294
+ if filter is None:
1295
+ filter_kwargs = {}
1296
+ else:
1297
+ filter_kwargs = {'filter': filter}
1298
+ if format is not None:
1299
+ try:
1300
+ format_info = _UNPACK_FORMATS[format]
1301
+ except KeyError:
1302
+ raise ValueError("Unknown unpack format '{0}'".format(format)) from None
1303
+
1304
+ func = format_info[1]
1305
+ func(filename, extract_dir, **dict(format_info[2]), **filter_kwargs)
1306
+ else:
1307
+ # we need to look at the registered unpackers supported extensions
1308
+ format = _find_unpack_format(filename)
1309
+ if format is None:
1310
+ raise ReadError("Unknown archive format '{0}'".format(filename))
1311
+
1312
+ func = _UNPACK_FORMATS[format][1]
1313
+ kwargs = dict(_UNPACK_FORMATS[format][2]) | filter_kwargs
1314
+ func(filename, extract_dir, **kwargs)
1315
+
1316
+
1317
+ if hasattr(os, 'statvfs'):
1318
+
1319
+ __all__.append('disk_usage')
1320
+ _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
1321
+ _ntuple_diskusage.total.__doc__ = 'Total space in bytes'
1322
+ _ntuple_diskusage.used.__doc__ = 'Used space in bytes'
1323
+ _ntuple_diskusage.free.__doc__ = 'Free space in bytes'
1324
+
1325
+ def disk_usage(path):
1326
+ """Return disk usage statistics about the given path.
1327
+
1328
+ Returned value is a named tuple with attributes 'total', 'used' and
1329
+ 'free', which are the amount of total, used and free space, in bytes.
1330
+ """
1331
+ st = os.statvfs(path)
1332
+ free = st.f_bavail * st.f_frsize
1333
+ total = st.f_blocks * st.f_frsize
1334
+ used = (st.f_blocks - st.f_bfree) * st.f_frsize
1335
+ return _ntuple_diskusage(total, used, free)
1336
+
1337
+ elif _WINDOWS:
1338
+
1339
+ __all__.append('disk_usage')
1340
+ _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
1341
+
1342
+ def disk_usage(path):
1343
+ """Return disk usage statistics about the given path.
1344
+
1345
+ Returned values is a named tuple with attributes 'total', 'used' and
1346
+ 'free', which are the amount of total, used and free space, in bytes.
1347
+ """
1348
+ total, free = nt._getdiskusage(path)
1349
+ used = total - free
1350
+ return _ntuple_diskusage(total, used, free)
1351
+
1352
+
1353
+ def chown(path, user=None, group=None):
1354
+ """Change owner user and group of the given path.
1355
+
1356
+ user and group can be the uid/gid or the user/group names, and in that case,
1357
+ they are converted to their respective uid/gid.
1358
+ """
1359
+ sys.audit('shutil.chown', path, user, group)
1360
+
1361
+ if user is None and group is None:
1362
+ raise ValueError("user and/or group must be set")
1363
+
1364
+ _user = user
1365
+ _group = group
1366
+
1367
+ # -1 means don't change it
1368
+ if user is None:
1369
+ _user = -1
1370
+ # user can either be an int (the uid) or a string (the system username)
1371
+ elif isinstance(user, str):
1372
+ _user = _get_uid(user)
1373
+ if _user is None:
1374
+ raise LookupError("no such user: {!r}".format(user))
1375
+
1376
+ if group is None:
1377
+ _group = -1
1378
+ elif not isinstance(group, int):
1379
+ _group = _get_gid(group)
1380
+ if _group is None:
1381
+ raise LookupError("no such group: {!r}".format(group))
1382
+
1383
+ os.chown(path, _user, _group)
1384
+
1385
+ def get_terminal_size(fallback=(80, 24)):
1386
+ """Get the size of the terminal window.
1387
+
1388
+ For each of the two dimensions, the environment variable, COLUMNS
1389
+ and LINES respectively, is checked. If the variable is defined and
1390
+ the value is a positive integer, it is used.
1391
+
1392
+ When COLUMNS or LINES is not defined, which is the common case,
1393
+ the terminal connected to sys.__stdout__ is queried
1394
+ by invoking os.get_terminal_size.
1395
+
1396
+ If the terminal size cannot be successfully queried, either because
1397
+ the system doesn't support querying, or because we are not
1398
+ connected to a terminal, the value given in fallback parameter
1399
+ is used. Fallback defaults to (80, 24) which is the default
1400
+ size used by many terminal emulators.
1401
+
1402
+ The value returned is a named tuple of type os.terminal_size.
1403
+ """
1404
+ # columns, lines are the working values
1405
+ try:
1406
+ columns = int(os.environ['COLUMNS'])
1407
+ except (KeyError, ValueError):
1408
+ columns = 0
1409
+
1410
+ try:
1411
+ lines = int(os.environ['LINES'])
1412
+ except (KeyError, ValueError):
1413
+ lines = 0
1414
+
1415
+ # only query if necessary
1416
+ if columns <= 0 or lines <= 0:
1417
+ try:
1418
+ size = os.get_terminal_size(sys.__stdout__.fileno())
1419
+ except (AttributeError, ValueError, OSError):
1420
+ # stdout is None, closed, detached, or not a terminal, or
1421
+ # os.get_terminal_size() is unsupported
1422
+ size = os.terminal_size(fallback)
1423
+ if columns <= 0:
1424
+ columns = size.columns
1425
+ if lines <= 0:
1426
+ lines = size.lines
1427
+
1428
+ return os.terminal_size((columns, lines))
1429
+
1430
+
1431
+ # Check that a given file can be accessed with the correct mode.
1432
+ # Additionally check that `file` is not a directory, as on Windows
1433
+ # directories pass the os.access check.
1434
+ def _access_check(fn, mode):
1435
+ return (os.path.exists(fn) and os.access(fn, mode)
1436
+ and not os.path.isdir(fn))
1437
+
1438
+
1439
+ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
1440
+ """Given a command, mode, and a PATH string, return the path which
1441
+ conforms to the given mode on the PATH, or None if there is no such
1442
+ file.
1443
+
1444
+ `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1445
+ of os.environ.get("PATH"), or can be overridden with a custom search
1446
+ path.
1447
+
1448
+ """
1449
+ # If we're given a path with a directory part, look it up directly rather
1450
+ # than referring to PATH directories. This includes checking relative to the
1451
+ # current directory, e.g. ./script
1452
+ if os.path.dirname(cmd):
1453
+ if _access_check(cmd, mode):
1454
+ return cmd
1455
+ return None
1456
+
1457
+ use_bytes = isinstance(cmd, bytes)
1458
+
1459
+ if path is None:
1460
+ path = os.environ.get("PATH", None)
1461
+ if path is None:
1462
+ try:
1463
+ path = os.confstr("CS_PATH")
1464
+ except (AttributeError, ValueError):
1465
+ # os.confstr() or CS_PATH is not available
1466
+ path = os.defpath
1467
+ # bpo-35755: Don't use os.defpath if the PATH environment variable is
1468
+ # set to an empty string
1469
+
1470
+ # PATH='' doesn't match, whereas PATH=':' looks in the current directory
1471
+ if not path:
1472
+ return None
1473
+
1474
+ if use_bytes:
1475
+ path = os.fsencode(path)
1476
+ path = path.split(os.fsencode(os.pathsep))
1477
+ else:
1478
+ path = os.fsdecode(path)
1479
+ path = path.split(os.pathsep)
1480
+
1481
+ if sys.platform == "win32":
1482
+ # The current directory takes precedence on Windows.
1483
+ curdir = os.curdir
1484
+ if use_bytes:
1485
+ curdir = os.fsencode(curdir)
1486
+ if curdir not in path:
1487
+ path.insert(0, curdir)
1488
+
1489
+ # PATHEXT is necessary to check on Windows.
1490
+ pathext_source = os.getenv("PATHEXT") or _WIN_DEFAULT_PATHEXT
1491
+ pathext = [ext for ext in pathext_source.split(os.pathsep) if ext]
1492
+
1493
+ if use_bytes:
1494
+ pathext = [os.fsencode(ext) for ext in pathext]
1495
+ # See if the given file matches any of the expected path extensions.
1496
+ # This will allow us to short circuit when given "python.exe".
1497
+ # If it does match, only test that one, otherwise we have to try
1498
+ # others.
1499
+ if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1500
+ files = [cmd]
1501
+ else:
1502
+ files = [cmd + ext for ext in pathext]
1503
+ else:
1504
+ # On other platforms you don't have things like PATHEXT to tell you
1505
+ # what file suffixes are executable, so just pass on cmd as-is.
1506
+ files = [cmd]
1507
+
1508
+ seen = set()
1509
+ for dir in path:
1510
+ normdir = os.path.normcase(dir)
1511
+ if not normdir in seen:
1512
+ seen.add(normdir)
1513
+ for thefile in files:
1514
+ name = os.path.join(dir, thefile)
1515
+ if _access_check(name, mode):
1516
+ return name
1517
+ return None
lib/python3.10/signal.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import _signal
2
+ from _signal import *
3
+ from enum import IntEnum as _IntEnum
4
+
5
+ _globals = globals()
6
+
7
+ _IntEnum._convert_(
8
+ 'Signals', __name__,
9
+ lambda name:
10
+ name.isupper()
11
+ and (name.startswith('SIG') and not name.startswith('SIG_'))
12
+ or name.startswith('CTRL_'))
13
+
14
+ _IntEnum._convert_(
15
+ 'Handlers', __name__,
16
+ lambda name: name in ('SIG_DFL', 'SIG_IGN'))
17
+
18
+ if 'pthread_sigmask' in _globals:
19
+ _IntEnum._convert_(
20
+ 'Sigmasks', __name__,
21
+ lambda name: name in ('SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'))
22
+
23
+
24
+ def _int_to_enum(value, enum_klass):
25
+ """Convert a numeric value to an IntEnum member.
26
+ If it's not a known member, return the numeric value itself.
27
+ """
28
+ try:
29
+ return enum_klass(value)
30
+ except ValueError:
31
+ return value
32
+
33
+
34
+ def _enum_to_int(value):
35
+ """Convert an IntEnum member to a numeric value.
36
+ If it's not an IntEnum member return the value itself.
37
+ """
38
+ try:
39
+ return int(value)
40
+ except (ValueError, TypeError):
41
+ return value
42
+
43
+
44
+ # Similar to functools.wraps(), but only assign __doc__.
45
+ # __module__ should be preserved,
46
+ # __name__ and __qualname__ are already fine,
47
+ # __annotations__ is not set.
48
+ def _wraps(wrapped):
49
+ def decorator(wrapper):
50
+ wrapper.__doc__ = wrapped.__doc__
51
+ return wrapper
52
+ return decorator
53
+
54
+ @_wraps(_signal.signal)
55
+ def signal(signalnum, handler):
56
+ handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
57
+ return _int_to_enum(handler, Handlers)
58
+
59
+
60
+ @_wraps(_signal.getsignal)
61
+ def getsignal(signalnum):
62
+ handler = _signal.getsignal(signalnum)
63
+ return _int_to_enum(handler, Handlers)
64
+
65
+
66
+ if 'pthread_sigmask' in _globals:
67
+ @_wraps(_signal.pthread_sigmask)
68
+ def pthread_sigmask(how, mask):
69
+ sigs_set = _signal.pthread_sigmask(how, mask)
70
+ return set(_int_to_enum(x, Signals) for x in sigs_set)
71
+
72
+
73
+ if 'sigpending' in _globals:
74
+ @_wraps(_signal.sigpending)
75
+ def sigpending():
76
+ return {_int_to_enum(x, Signals) for x in _signal.sigpending()}
77
+
78
+
79
+ if 'sigwait' in _globals:
80
+ @_wraps(_signal.sigwait)
81
+ def sigwait(sigset):
82
+ retsig = _signal.sigwait(sigset)
83
+ return _int_to_enum(retsig, Signals)
84
+
85
+
86
+ if 'valid_signals' in _globals:
87
+ @_wraps(_signal.valid_signals)
88
+ def valid_signals():
89
+ return {_int_to_enum(x, Signals) for x in _signal.valid_signals()}
90
+
91
+
92
+ del _globals, _wraps
lib/python3.10/uu.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #! /usr/bin/env python3
2
+
3
+ # Copyright 1994 by Lance Ellinghouse
4
+ # Cathedral City, California Republic, United States of America.
5
+ # All Rights Reserved
6
+ # Permission to use, copy, modify, and distribute this software and its
7
+ # documentation for any purpose and without fee is hereby granted,
8
+ # provided that the above copyright notice appear in all copies and that
9
+ # both that copyright notice and this permission notice appear in
10
+ # supporting documentation, and that the name of Lance Ellinghouse
11
+ # not be used in advertising or publicity pertaining to distribution
12
+ # of the software without specific, written prior permission.
13
+ # LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
14
+ # THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
15
+ # FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE
16
+ # FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
+ # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
+ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19
+ # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
+ #
21
+ # Modified by Jack Jansen, CWI, July 1995:
22
+ # - Use binascii module to do the actual line-by-line conversion
23
+ # between ascii and binary. This results in a 1000-fold speedup. The C
24
+ # version is still 5 times faster, though.
25
+ # - Arguments more compliant with python standard
26
+
27
+ """Implementation of the UUencode and UUdecode functions.
28
+
29
+ encode(in_file, out_file [,name, mode], *, backtick=False)
30
+ decode(in_file [, out_file, mode, quiet])
31
+ """
32
+
33
+ import binascii
34
+ import os
35
+ import sys
36
+
37
+ __all__ = ["Error", "encode", "decode"]
38
+
39
+ class Error(Exception):
40
+ pass
41
+
42
+ def encode(in_file, out_file, name=None, mode=None, *, backtick=False):
43
+ """Uuencode file"""
44
+ #
45
+ # If in_file is a pathname open it and change defaults
46
+ #
47
+ opened_files = []
48
+ try:
49
+ if in_file == '-':
50
+ in_file = sys.stdin.buffer
51
+ elif isinstance(in_file, str):
52
+ if name is None:
53
+ name = os.path.basename(in_file)
54
+ if mode is None:
55
+ try:
56
+ mode = os.stat(in_file).st_mode
57
+ except AttributeError:
58
+ pass
59
+ in_file = open(in_file, 'rb')
60
+ opened_files.append(in_file)
61
+ #
62
+ # Open out_file if it is a pathname
63
+ #
64
+ if out_file == '-':
65
+ out_file = sys.stdout.buffer
66
+ elif isinstance(out_file, str):
67
+ out_file = open(out_file, 'wb')
68
+ opened_files.append(out_file)
69
+ #
70
+ # Set defaults for name and mode
71
+ #
72
+ if name is None:
73
+ name = '-'
74
+ if mode is None:
75
+ mode = 0o666
76
+
77
+ #
78
+ # Remove newline chars from name
79
+ #
80
+ name = name.replace('\n','\\n')
81
+ name = name.replace('\r','\\r')
82
+
83
+ #
84
+ # Write the data
85
+ #
86
+ out_file.write(('begin %o %s\n' % ((mode & 0o777), name)).encode("ascii"))
87
+ data = in_file.read(45)
88
+ while len(data) > 0:
89
+ out_file.write(binascii.b2a_uu(data, backtick=backtick))
90
+ data = in_file.read(45)
91
+ if backtick:
92
+ out_file.write(b'`\nend\n')
93
+ else:
94
+ out_file.write(b' \nend\n')
95
+ finally:
96
+ for f in opened_files:
97
+ f.close()
98
+
99
+
100
+ def decode(in_file, out_file=None, mode=None, quiet=False):
101
+ """Decode uuencoded file"""
102
+ #
103
+ # Open the input file, if needed.
104
+ #
105
+ opened_files = []
106
+ if in_file == '-':
107
+ in_file = sys.stdin.buffer
108
+ elif isinstance(in_file, str):
109
+ in_file = open(in_file, 'rb')
110
+ opened_files.append(in_file)
111
+
112
+ try:
113
+ #
114
+ # Read until a begin is encountered or we've exhausted the file
115
+ #
116
+ while True:
117
+ hdr = in_file.readline()
118
+ if not hdr:
119
+ raise Error('No valid begin line found in input file')
120
+ if not hdr.startswith(b'begin'):
121
+ continue
122
+ hdrfields = hdr.split(b' ', 2)
123
+ if len(hdrfields) == 3 and hdrfields[0] == b'begin':
124
+ try:
125
+ int(hdrfields[1], 8)
126
+ break
127
+ except ValueError:
128
+ pass
129
+ if out_file is None:
130
+ # If the filename isn't ASCII, what's up with that?!?
131
+ out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii")
132
+ if os.path.exists(out_file):
133
+ raise Error(f'Cannot overwrite existing file: {out_file}')
134
+ if (out_file.startswith(os.sep) or
135
+ f'..{os.sep}' in out_file or (
136
+ os.altsep and
137
+ (out_file.startswith(os.altsep) or
138
+ f'..{os.altsep}' in out_file))
139
+ ):
140
+ raise Error(f'Refusing to write to {out_file} due to directory traversal')
141
+ if mode is None:
142
+ mode = int(hdrfields[1], 8)
143
+ #
144
+ # Open the output file
145
+ #
146
+ if out_file == '-':
147
+ out_file = sys.stdout.buffer
148
+ elif isinstance(out_file, str):
149
+ fp = open(out_file, 'wb')
150
+ os.chmod(out_file, mode)
151
+ out_file = fp
152
+ opened_files.append(out_file)
153
+ #
154
+ # Main decoding loop
155
+ #
156
+ s = in_file.readline()
157
+ while s and s.strip(b' \t\r\n\f') != b'end':
158
+ try:
159
+ data = binascii.a2b_uu(s)
160
+ except binascii.Error as v:
161
+ # Workaround for broken uuencoders by /Fredrik Lundh
162
+ nbytes = (((s[0]-32) & 63) * 4 + 5) // 3
163
+ data = binascii.a2b_uu(s[:nbytes])
164
+ if not quiet:
165
+ sys.stderr.write("Warning: %s\n" % v)
166
+ out_file.write(data)
167
+ s = in_file.readline()
168
+ if not s:
169
+ raise Error('Truncated input file')
170
+ finally:
171
+ for f in opened_files:
172
+ f.close()
173
+
174
+ def test():
175
+ """uuencode/uudecode main program"""
176
+
177
+ import optparse
178
+ parser = optparse.OptionParser(usage='usage: %prog [-d] [-t] [input [output]]')
179
+ parser.add_option('-d', '--decode', dest='decode', help='Decode (instead of encode)?', default=False, action='store_true')
180
+ parser.add_option('-t', '--text', dest='text', help='data is text, encoded format unix-compatible text?', default=False, action='store_true')
181
+
182
+ (options, args) = parser.parse_args()
183
+ if len(args) > 2:
184
+ parser.error('incorrect number of arguments')
185
+ sys.exit(1)
186
+
187
+ # Use the binary streams underlying stdin/stdout
188
+ input = sys.stdin.buffer
189
+ output = sys.stdout.buffer
190
+ if len(args) > 0:
191
+ input = args[0]
192
+ if len(args) > 1:
193
+ output = args[1]
194
+
195
+ if options.decode:
196
+ if options.text:
197
+ if isinstance(output, str):
198
+ output = open(output, 'wb')
199
+ else:
200
+ print(sys.argv[0], ': cannot do -t to stdout')
201
+ sys.exit(1)
202
+ decode(input, output)
203
+ else:
204
+ if options.text:
205
+ if isinstance(input, str):
206
+ input = open(input, 'rb')
207
+ else:
208
+ print(sys.argv[0], ': cannot do -t from stdin')
209
+ sys.exit(1)
210
+ encode(input, output)
211
+
212
+ if __name__ == '__main__':
213
+ test()
lib/python3.10/uuid.py ADDED
@@ -0,0 +1,733 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ r"""UUID objects (universally unique identifiers) according to RFC 4122.
2
+
3
+ This module provides immutable UUID objects (class UUID) and the functions
4
+ uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5
5
+ UUIDs as specified in RFC 4122.
6
+
7
+ If all you want is a unique ID, you should probably call uuid1() or uuid4().
8
+ Note that uuid1() may compromise privacy since it creates a UUID containing
9
+ the computer's network address. uuid4() creates a random UUID.
10
+
11
+ Typical usage:
12
+
13
+ >>> import uuid
14
+
15
+ # make a UUID based on the host ID and current time
16
+ >>> uuid.uuid1() # doctest: +SKIP
17
+ UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
18
+
19
+ # make a UUID using an MD5 hash of a namespace UUID and a name
20
+ >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
21
+ UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
22
+
23
+ # make a random UUID
24
+ >>> uuid.uuid4() # doctest: +SKIP
25
+ UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
26
+
27
+ # make a UUID using a SHA-1 hash of a namespace UUID and a name
28
+ >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
29
+ UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
30
+
31
+ # make a UUID from a string of hex digits (braces and hyphens ignored)
32
+ >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
33
+
34
+ # convert a UUID to a string of hex digits in standard form
35
+ >>> str(x)
36
+ '00010203-0405-0607-0809-0a0b0c0d0e0f'
37
+
38
+ # get the raw 16 bytes of the UUID
39
+ >>> x.bytes
40
+ b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
41
+
42
+ # make a UUID from a 16-byte string
43
+ >>> uuid.UUID(bytes=x.bytes)
44
+ UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
45
+ """
46
+
47
+ import os
48
+ import sys
49
+
50
+ from enum import Enum
51
+
52
+
53
+ __author__ = 'Ka-Ping Yee <ping@zesty.ca>'
54
+
55
+ # The recognized platforms - known behaviors
56
+ if sys.platform in ('win32', 'darwin'):
57
+ _AIX = _LINUX = False
58
+ else:
59
+ import platform
60
+ _platform_system = platform.system()
61
+ _AIX = _platform_system == 'AIX'
62
+ _LINUX = _platform_system == 'Linux'
63
+
64
+ _MAC_DELIM = b':'
65
+ _MAC_OMITS_LEADING_ZEROES = False
66
+ if _AIX:
67
+ _MAC_DELIM = b'.'
68
+ _MAC_OMITS_LEADING_ZEROES = True
69
+
70
+ RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
71
+ 'reserved for NCS compatibility', 'specified in RFC 4122',
72
+ 'reserved for Microsoft compatibility', 'reserved for future definition']
73
+
74
+ int_ = int # The built-in int type
75
+ bytes_ = bytes # The built-in bytes type
76
+
77
+
78
+ class SafeUUID(Enum):
79
+ safe = 0
80
+ unsafe = -1
81
+ unknown = None
82
+
83
+
84
+ class UUID:
85
+ """Instances of the UUID class represent UUIDs as specified in RFC 4122.
86
+ UUID objects are immutable, hashable, and usable as dictionary keys.
87
+ Converting a UUID to a string with str() yields something in the form
88
+ '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
89
+ five possible forms: a similar string of hexadecimal digits, or a tuple
90
+ of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
91
+ 48-bit values respectively) as an argument named 'fields', or a string
92
+ of 16 bytes (with all the integer fields in big-endian order) as an
93
+ argument named 'bytes', or a string of 16 bytes (with the first three
94
+ fields in little-endian order) as an argument named 'bytes_le', or a
95
+ single 128-bit integer as an argument named 'int'.
96
+
97
+ UUIDs have these read-only attributes:
98
+
99
+ bytes the UUID as a 16-byte string (containing the six
100
+ integer fields in big-endian byte order)
101
+
102
+ bytes_le the UUID as a 16-byte string (with time_low, time_mid,
103
+ and time_hi_version in little-endian byte order)
104
+
105
+ fields a tuple of the six integer fields of the UUID,
106
+ which are also available as six individual attributes
107
+ and two derived attributes:
108
+
109
+ time_low the first 32 bits of the UUID
110
+ time_mid the next 16 bits of the UUID
111
+ time_hi_version the next 16 bits of the UUID
112
+ clock_seq_hi_variant the next 8 bits of the UUID
113
+ clock_seq_low the next 8 bits of the UUID
114
+ node the last 48 bits of the UUID
115
+
116
+ time the 60-bit timestamp
117
+ clock_seq the 14-bit sequence number
118
+
119
+ hex the UUID as a 32-character hexadecimal string
120
+
121
+ int the UUID as a 128-bit integer
122
+
123
+ urn the UUID as a URN as specified in RFC 4122
124
+
125
+ variant the UUID variant (one of the constants RESERVED_NCS,
126
+ RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
127
+
128
+ version the UUID version number (1 through 5, meaningful only
129
+ when the variant is RFC_4122)
130
+
131
+ is_safe An enum indicating whether the UUID has been generated in
132
+ a way that is safe for multiprocessing applications, via
133
+ uuid_generate_time_safe(3).
134
+ """
135
+
136
+ __slots__ = ('int', 'is_safe', '__weakref__')
137
+
138
+ def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
139
+ int=None, version=None,
140
+ *, is_safe=SafeUUID.unknown):
141
+ r"""Create a UUID from either a string of 32 hexadecimal digits,
142
+ a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
143
+ in little-endian order as the 'bytes_le' argument, a tuple of six
144
+ integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
145
+ 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
146
+ the 'fields' argument, or a single 128-bit integer as the 'int'
147
+ argument. When a string of hex digits is given, curly braces,
148
+ hyphens, and a URN prefix are all optional. For example, these
149
+ expressions all yield the same UUID:
150
+
151
+ UUID('{12345678-1234-5678-1234-567812345678}')
152
+ UUID('12345678123456781234567812345678')
153
+ UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
154
+ UUID(bytes='\x12\x34\x56\x78'*4)
155
+ UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
156
+ '\x12\x34\x56\x78\x12\x34\x56\x78')
157
+ UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
158
+ UUID(int=0x12345678123456781234567812345678)
159
+
160
+ Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
161
+ be given. The 'version' argument is optional; if given, the resulting
162
+ UUID will have its variant and version set according to RFC 4122,
163
+ overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
164
+
165
+ is_safe is an enum exposed as an attribute on the instance. It
166
+ indicates whether the UUID has been generated in a way that is safe
167
+ for multiprocessing applications, via uuid_generate_time_safe(3).
168
+ """
169
+
170
+ if [hex, bytes, bytes_le, fields, int].count(None) != 4:
171
+ raise TypeError('one of the hex, bytes, bytes_le, fields, '
172
+ 'or int arguments must be given')
173
+ if hex is not None:
174
+ hex = hex.replace('urn:', '').replace('uuid:', '')
175
+ hex = hex.strip('{}').replace('-', '')
176
+ if len(hex) != 32:
177
+ raise ValueError('badly formed hexadecimal UUID string')
178
+ int = int_(hex, 16)
179
+ if bytes_le is not None:
180
+ if len(bytes_le) != 16:
181
+ raise ValueError('bytes_le is not a 16-char string')
182
+ bytes = (bytes_le[4-1::-1] + bytes_le[6-1:4-1:-1] +
183
+ bytes_le[8-1:6-1:-1] + bytes_le[8:])
184
+ if bytes is not None:
185
+ if len(bytes) != 16:
186
+ raise ValueError('bytes is not a 16-char string')
187
+ assert isinstance(bytes, bytes_), repr(bytes)
188
+ int = int_.from_bytes(bytes, byteorder='big')
189
+ if fields is not None:
190
+ if len(fields) != 6:
191
+ raise ValueError('fields is not a 6-tuple')
192
+ (time_low, time_mid, time_hi_version,
193
+ clock_seq_hi_variant, clock_seq_low, node) = fields
194
+ if not 0 <= time_low < 1<<32:
195
+ raise ValueError('field 1 out of range (need a 32-bit value)')
196
+ if not 0 <= time_mid < 1<<16:
197
+ raise ValueError('field 2 out of range (need a 16-bit value)')
198
+ if not 0 <= time_hi_version < 1<<16:
199
+ raise ValueError('field 3 out of range (need a 16-bit value)')
200
+ if not 0 <= clock_seq_hi_variant < 1<<8:
201
+ raise ValueError('field 4 out of range (need an 8-bit value)')
202
+ if not 0 <= clock_seq_low < 1<<8:
203
+ raise ValueError('field 5 out of range (need an 8-bit value)')
204
+ if not 0 <= node < 1<<48:
205
+ raise ValueError('field 6 out of range (need a 48-bit value)')
206
+ clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low
207
+ int = ((time_low << 96) | (time_mid << 80) |
208
+ (time_hi_version << 64) | (clock_seq << 48) | node)
209
+ if int is not None:
210
+ if not 0 <= int < 1<<128:
211
+ raise ValueError('int is out of range (need a 128-bit value)')
212
+ if version is not None:
213
+ if not 1 <= version <= 5:
214
+ raise ValueError('illegal version number')
215
+ # Set the variant to RFC 4122.
216
+ int &= ~(0xc000 << 48)
217
+ int |= 0x8000 << 48
218
+ # Set the version number.
219
+ int &= ~(0xf000 << 64)
220
+ int |= version << 76
221
+ object.__setattr__(self, 'int', int)
222
+ object.__setattr__(self, 'is_safe', is_safe)
223
+
224
+ def __getstate__(self):
225
+ d = {'int': self.int}
226
+ if self.is_safe != SafeUUID.unknown:
227
+ # is_safe is a SafeUUID instance. Return just its value, so that
228
+ # it can be un-pickled in older Python versions without SafeUUID.
229
+ d['is_safe'] = self.is_safe.value
230
+ return d
231
+
232
+ def __setstate__(self, state):
233
+ object.__setattr__(self, 'int', state['int'])
234
+ # is_safe was added in 3.7; it is also omitted when it is "unknown"
235
+ object.__setattr__(self, 'is_safe',
236
+ SafeUUID(state['is_safe'])
237
+ if 'is_safe' in state else SafeUUID.unknown)
238
+
239
+ def __eq__(self, other):
240
+ if isinstance(other, UUID):
241
+ return self.int == other.int
242
+ return NotImplemented
243
+
244
+ # Q. What's the value of being able to sort UUIDs?
245
+ # A. Use them as keys in a B-Tree or similar mapping.
246
+
247
+ def __lt__(self, other):
248
+ if isinstance(other, UUID):
249
+ return self.int < other.int
250
+ return NotImplemented
251
+
252
+ def __gt__(self, other):
253
+ if isinstance(other, UUID):
254
+ return self.int > other.int
255
+ return NotImplemented
256
+
257
+ def __le__(self, other):
258
+ if isinstance(other, UUID):
259
+ return self.int <= other.int
260
+ return NotImplemented
261
+
262
+ def __ge__(self, other):
263
+ if isinstance(other, UUID):
264
+ return self.int >= other.int
265
+ return NotImplemented
266
+
267
+ def __hash__(self):
268
+ return hash(self.int)
269
+
270
+ def __int__(self):
271
+ return self.int
272
+
273
+ def __repr__(self):
274
+ return '%s(%r)' % (self.__class__.__name__, str(self))
275
+
276
+ def __setattr__(self, name, value):
277
+ raise TypeError('UUID objects are immutable')
278
+
279
+ def __str__(self):
280
+ hex = '%032x' % self.int
281
+ return '%s-%s-%s-%s-%s' % (
282
+ hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
283
+
284
+ @property
285
+ def bytes(self):
286
+ return self.int.to_bytes(16, 'big')
287
+
288
+ @property
289
+ def bytes_le(self):
290
+ bytes = self.bytes
291
+ return (bytes[4-1::-1] + bytes[6-1:4-1:-1] + bytes[8-1:6-1:-1] +
292
+ bytes[8:])
293
+
294
+ @property
295
+ def fields(self):
296
+ return (self.time_low, self.time_mid, self.time_hi_version,
297
+ self.clock_seq_hi_variant, self.clock_seq_low, self.node)
298
+
299
+ @property
300
+ def time_low(self):
301
+ return self.int >> 96
302
+
303
+ @property
304
+ def time_mid(self):
305
+ return (self.int >> 80) & 0xffff
306
+
307
+ @property
308
+ def time_hi_version(self):
309
+ return (self.int >> 64) & 0xffff
310
+
311
+ @property
312
+ def clock_seq_hi_variant(self):
313
+ return (self.int >> 56) & 0xff
314
+
315
+ @property
316
+ def clock_seq_low(self):
317
+ return (self.int >> 48) & 0xff
318
+
319
+ @property
320
+ def time(self):
321
+ return (((self.time_hi_version & 0x0fff) << 48) |
322
+ (self.time_mid << 32) | self.time_low)
323
+
324
+ @property
325
+ def clock_seq(self):
326
+ return (((self.clock_seq_hi_variant & 0x3f) << 8) |
327
+ self.clock_seq_low)
328
+
329
+ @property
330
+ def node(self):
331
+ return self.int & 0xffffffffffff
332
+
333
+ @property
334
+ def hex(self):
335
+ return '%032x' % self.int
336
+
337
+ @property
338
+ def urn(self):
339
+ return 'urn:uuid:' + str(self)
340
+
341
+ @property
342
+ def variant(self):
343
+ if not self.int & (0x8000 << 48):
344
+ return RESERVED_NCS
345
+ elif not self.int & (0x4000 << 48):
346
+ return RFC_4122
347
+ elif not self.int & (0x2000 << 48):
348
+ return RESERVED_MICROSOFT
349
+ else:
350
+ return RESERVED_FUTURE
351
+
352
+ @property
353
+ def version(self):
354
+ # The version bits are only meaningful for RFC 4122 UUIDs.
355
+ if self.variant == RFC_4122:
356
+ return int((self.int >> 76) & 0xf)
357
+
358
+
359
+ def _get_command_stdout(command, *args):
360
+ import io, os, shutil, subprocess
361
+
362
+ try:
363
+ path_dirs = os.environ.get('PATH', os.defpath).split(os.pathsep)
364
+ path_dirs.extend(['/sbin', '/usr/sbin'])
365
+ executable = shutil.which(command, path=os.pathsep.join(path_dirs))
366
+ if executable is None:
367
+ return None
368
+ # LC_ALL=C to ensure English output, stderr=DEVNULL to prevent output
369
+ # on stderr (Note: we don't have an example where the words we search
370
+ # for are actually localized, but in theory some system could do so.)
371
+ env = dict(os.environ)
372
+ env['LC_ALL'] = 'C'
373
+ # Empty strings will be quoted by popen so we should just ommit it
374
+ if args != ('',):
375
+ command = (executable, *args)
376
+ else:
377
+ command = (executable,)
378
+ proc = subprocess.Popen(command,
379
+ stdout=subprocess.PIPE,
380
+ stderr=subprocess.DEVNULL,
381
+ env=env)
382
+ if not proc:
383
+ return None
384
+ stdout, stderr = proc.communicate()
385
+ return io.BytesIO(stdout)
386
+ except (OSError, subprocess.SubprocessError):
387
+ return None
388
+
389
+
390
+ # For MAC (a.k.a. IEEE 802, or EUI-48) addresses, the second least significant
391
+ # bit of the first octet signifies whether the MAC address is universally (0)
392
+ # or locally (1) administered. Network cards from hardware manufacturers will
393
+ # always be universally administered to guarantee global uniqueness of the MAC
394
+ # address, but any particular machine may have other interfaces which are
395
+ # locally administered. An example of the latter is the bridge interface to
396
+ # the Touch Bar on MacBook Pros.
397
+ #
398
+ # This bit works out to be the 42nd bit counting from 1 being the least
399
+ # significant, or 1<<41. We'll prefer universally administered MAC addresses
400
+ # over locally administered ones since the former are globally unique, but
401
+ # we'll return the first of the latter found if that's all the machine has.
402
+ #
403
+ # See https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
404
+
405
+ def _is_universal(mac):
406
+ return not (mac & (1 << 41))
407
+
408
+
409
+ def _find_mac_near_keyword(command, args, keywords, get_word_index):
410
+ """Searches a command's output for a MAC address near a keyword.
411
+
412
+ Each line of words in the output is case-insensitively searched for
413
+ any of the given keywords. Upon a match, get_word_index is invoked
414
+ to pick a word from the line, given the index of the match. For
415
+ example, lambda i: 0 would get the first word on the line, while
416
+ lambda i: i - 1 would get the word preceding the keyword.
417
+ """
418
+ stdout = _get_command_stdout(command, args)
419
+ if stdout is None:
420
+ return None
421
+
422
+ first_local_mac = None
423
+ for line in stdout:
424
+ words = line.lower().rstrip().split()
425
+ for i in range(len(words)):
426
+ if words[i] in keywords:
427
+ try:
428
+ word = words[get_word_index(i)]
429
+ mac = int(word.replace(_MAC_DELIM, b''), 16)
430
+ except (ValueError, IndexError):
431
+ # Virtual interfaces, such as those provided by
432
+ # VPNs, do not have a colon-delimited MAC address
433
+ # as expected, but a 16-byte HWAddr separated by
434
+ # dashes. These should be ignored in favor of a
435
+ # real MAC address
436
+ pass
437
+ else:
438
+ if _is_universal(mac):
439
+ return mac
440
+ first_local_mac = first_local_mac or mac
441
+ return first_local_mac or None
442
+
443
+
444
+ def _parse_mac(word):
445
+ # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'),
446
+ # but reject IPv6 address (ex: 'fe80::5054:ff:fe9' or '123:2:3:4:5:6:7:8').
447
+ #
448
+ # Virtual interfaces, such as those provided by VPNs, do not have a
449
+ # colon-delimited MAC address as expected, but a 16-byte HWAddr separated
450
+ # by dashes. These should be ignored in favor of a real MAC address
451
+ parts = word.split(_MAC_DELIM)
452
+ if len(parts) != 6:
453
+ return
454
+ if _MAC_OMITS_LEADING_ZEROES:
455
+ # (Only) on AIX the macaddr value given is not prefixed by 0, e.g.
456
+ # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0
457
+ # not
458
+ # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0
459
+ if not all(1 <= len(part) <= 2 for part in parts):
460
+ return
461
+ hexstr = b''.join(part.rjust(2, b'0') for part in parts)
462
+ else:
463
+ if not all(len(part) == 2 for part in parts):
464
+ return
465
+ hexstr = b''.join(parts)
466
+ try:
467
+ return int(hexstr, 16)
468
+ except ValueError:
469
+ return
470
+
471
+
472
+ def _find_mac_under_heading(command, args, heading):
473
+ """Looks for a MAC address under a heading in a command's output.
474
+
475
+ The first line of words in the output is searched for the given
476
+ heading. Words at the same word index as the heading in subsequent
477
+ lines are then examined to see if they look like MAC addresses.
478
+ """
479
+ stdout = _get_command_stdout(command, args)
480
+ if stdout is None:
481
+ return None
482
+
483
+ keywords = stdout.readline().rstrip().split()
484
+ try:
485
+ column_index = keywords.index(heading)
486
+ except ValueError:
487
+ return None
488
+
489
+ first_local_mac = None
490
+ for line in stdout:
491
+ words = line.rstrip().split()
492
+ try:
493
+ word = words[column_index]
494
+ except IndexError:
495
+ continue
496
+
497
+ mac = _parse_mac(word)
498
+ if mac is None:
499
+ continue
500
+ if _is_universal(mac):
501
+ return mac
502
+ if first_local_mac is None:
503
+ first_local_mac = mac
504
+
505
+ return first_local_mac
506
+
507
+
508
+ # The following functions call external programs to 'get' a macaddr value to
509
+ # be used as basis for an uuid
510
+ def _ifconfig_getnode():
511
+ """Get the hardware address on Unix by running ifconfig."""
512
+ # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
513
+ keywords = (b'hwaddr', b'ether', b'address:', b'lladdr')
514
+ for args in ('', '-a', '-av'):
515
+ mac = _find_mac_near_keyword('ifconfig', args, keywords, lambda i: i+1)
516
+ if mac:
517
+ return mac
518
+ return None
519
+
520
+ def _ip_getnode():
521
+ """Get the hardware address on Unix by running ip."""
522
+ # This works on Linux with iproute2.
523
+ mac = _find_mac_near_keyword('ip', 'link', [b'link/ether'], lambda i: i+1)
524
+ if mac:
525
+ return mac
526
+ return None
527
+
528
+ def _arp_getnode():
529
+ """Get the hardware address on Unix by running arp."""
530
+ import os, socket
531
+ try:
532
+ ip_addr = socket.gethostbyname(socket.gethostname())
533
+ except OSError:
534
+ return None
535
+
536
+ # Try getting the MAC addr from arp based on our IP address (Solaris).
537
+ mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1)
538
+ if mac:
539
+ return mac
540
+
541
+ # This works on OpenBSD
542
+ mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: i+1)
543
+ if mac:
544
+ return mac
545
+
546
+ # This works on Linux, FreeBSD and NetBSD
547
+ mac = _find_mac_near_keyword('arp', '-an', [os.fsencode('(%s)' % ip_addr)],
548
+ lambda i: i+2)
549
+ # Return None instead of 0.
550
+ if mac:
551
+ return mac
552
+ return None
553
+
554
+ def _lanscan_getnode():
555
+ """Get the hardware address on Unix by running lanscan."""
556
+ # This might work on HP-UX.
557
+ return _find_mac_near_keyword('lanscan', '-ai', [b'lan0'], lambda i: 0)
558
+
559
+ def _netstat_getnode():
560
+ """Get the hardware address on Unix by running netstat."""
561
+ # This works on AIX and might work on Tru64 UNIX.
562
+ return _find_mac_under_heading('netstat', '-ian', b'Address')
563
+
564
+ def _ipconfig_getnode():
565
+ """[DEPRECATED] Get the hardware address on Windows."""
566
+ # bpo-40501: UuidCreateSequential() is now the only supported approach
567
+ return _windll_getnode()
568
+
569
+ def _netbios_getnode():
570
+ """[DEPRECATED] Get the hardware address on Windows."""
571
+ # bpo-40501: UuidCreateSequential() is now the only supported approach
572
+ return _windll_getnode()
573
+
574
+
575
+ # Import optional C extension at toplevel, to help disabling it when testing
576
+ try:
577
+ import _uuid
578
+ _generate_time_safe = getattr(_uuid, "generate_time_safe", None)
579
+ _UuidCreate = getattr(_uuid, "UuidCreate", None)
580
+ _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
581
+ except ImportError:
582
+ _uuid = None
583
+ _generate_time_safe = None
584
+ _UuidCreate = None
585
+ _has_uuid_generate_time_safe = None
586
+
587
+
588
+ def _load_system_functions():
589
+ """[DEPRECATED] Platform-specific functions loaded at import time"""
590
+
591
+
592
+ def _unix_getnode():
593
+ """Get the hardware address on Unix using the _uuid extension module."""
594
+ if _generate_time_safe:
595
+ uuid_time, _ = _generate_time_safe()
596
+ return UUID(bytes=uuid_time).node
597
+
598
+ def _windll_getnode():
599
+ """Get the hardware address on Windows using the _uuid extension module."""
600
+ if _UuidCreate:
601
+ uuid_bytes = _UuidCreate()
602
+ return UUID(bytes_le=uuid_bytes).node
603
+
604
+ def _random_getnode():
605
+ """Get a random node ID."""
606
+ # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or
607
+ # pseudo-randomly generated value may be used; see Section 4.5. The
608
+ # multicast bit must be set in such addresses, in order that they will
609
+ # never conflict with addresses obtained from network cards."
610
+ #
611
+ # The "multicast bit" of a MAC address is defined to be "the least
612
+ # significant bit of the first octet". This works out to be the 41st bit
613
+ # counting from 1 being the least significant bit, or 1<<40.
614
+ #
615
+ # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
616
+ import random
617
+ return random.getrandbits(48) | (1 << 40)
618
+
619
+
620
+ # _OS_GETTERS, when known, are targeted for a specific OS or platform.
621
+ # The order is by 'common practice' on the specified platform.
622
+ # Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method
623
+ # which, when successful, means none of these "external" methods are called.
624
+ # _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g.,
625
+ # @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...)
626
+ if _LINUX:
627
+ _OS_GETTERS = [_ip_getnode, _ifconfig_getnode]
628
+ elif sys.platform == 'darwin':
629
+ _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
630
+ elif sys.platform == 'win32':
631
+ # bpo-40201: _windll_getnode will always succeed, so these are not needed
632
+ _OS_GETTERS = []
633
+ elif _AIX:
634
+ _OS_GETTERS = [_netstat_getnode]
635
+ else:
636
+ _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode,
637
+ _netstat_getnode, _lanscan_getnode]
638
+ if os.name == 'posix':
639
+ _GETTERS = [_unix_getnode] + _OS_GETTERS
640
+ elif os.name == 'nt':
641
+ _GETTERS = [_windll_getnode] + _OS_GETTERS
642
+ else:
643
+ _GETTERS = _OS_GETTERS
644
+
645
+ _node = None
646
+
647
+ def getnode():
648
+ """Get the hardware address as a 48-bit positive integer.
649
+
650
+ The first time this runs, it may launch a separate program, which could
651
+ be quite slow. If all attempts to obtain the hardware address fail, we
652
+ choose a random 48-bit number with its eighth bit set to 1 as recommended
653
+ in RFC 4122.
654
+ """
655
+ global _node
656
+ if _node is not None:
657
+ return _node
658
+
659
+ for getter in _GETTERS + [_random_getnode]:
660
+ try:
661
+ _node = getter()
662
+ except:
663
+ continue
664
+ if (_node is not None) and (0 <= _node < (1 << 48)):
665
+ return _node
666
+ assert False, '_random_getnode() returned invalid value: {}'.format(_node)
667
+
668
+
669
+ _last_timestamp = None
670
+
671
+ def uuid1(node=None, clock_seq=None):
672
+ """Generate a UUID from a host ID, sequence number, and the current time.
673
+ If 'node' is not given, getnode() is used to obtain the hardware
674
+ address. If 'clock_seq' is given, it is used as the sequence number;
675
+ otherwise a random 14-bit sequence number is chosen."""
676
+
677
+ # When the system provides a version-1 UUID generator, use it (but don't
678
+ # use UuidCreate here because its UUIDs don't conform to RFC 4122).
679
+ if _generate_time_safe is not None and node is clock_seq is None:
680
+ uuid_time, safely_generated = _generate_time_safe()
681
+ try:
682
+ is_safe = SafeUUID(safely_generated)
683
+ except ValueError:
684
+ is_safe = SafeUUID.unknown
685
+ return UUID(bytes=uuid_time, is_safe=is_safe)
686
+
687
+ global _last_timestamp
688
+ import time
689
+ nanoseconds = time.time_ns()
690
+ # 0x01b21dd213814000 is the number of 100-ns intervals between the
691
+ # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
692
+ timestamp = nanoseconds // 100 + 0x01b21dd213814000
693
+ if _last_timestamp is not None and timestamp <= _last_timestamp:
694
+ timestamp = _last_timestamp + 1
695
+ _last_timestamp = timestamp
696
+ if clock_seq is None:
697
+ import random
698
+ clock_seq = random.getrandbits(14) # instead of stable storage
699
+ time_low = timestamp & 0xffffffff
700
+ time_mid = (timestamp >> 32) & 0xffff
701
+ time_hi_version = (timestamp >> 48) & 0x0fff
702
+ clock_seq_low = clock_seq & 0xff
703
+ clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
704
+ if node is None:
705
+ node = getnode()
706
+ return UUID(fields=(time_low, time_mid, time_hi_version,
707
+ clock_seq_hi_variant, clock_seq_low, node), version=1)
708
+
709
+ def uuid3(namespace, name):
710
+ """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
711
+ from hashlib import md5
712
+ digest = md5(
713
+ namespace.bytes + bytes(name, "utf-8"),
714
+ usedforsecurity=False
715
+ ).digest()
716
+ return UUID(bytes=digest[:16], version=3)
717
+
718
+ def uuid4():
719
+ """Generate a random UUID."""
720
+ return UUID(bytes=os.urandom(16), version=4)
721
+
722
+ def uuid5(namespace, name):
723
+ """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
724
+ from hashlib import sha1
725
+ hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()
726
+ return UUID(bytes=hash[:16], version=5)
727
+
728
+ # The following standard UUIDs are for use with uuid3() or uuid5().
729
+
730
+ NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
731
+ NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
732
+ NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
733
+ NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')
lib/python3.10/warnings.py ADDED
@@ -0,0 +1,549 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Python part of the warnings subsystem."""
2
+
3
+ import sys
4
+
5
+
6
+ __all__ = ["warn", "warn_explicit", "showwarning",
7
+ "formatwarning", "filterwarnings", "simplefilter",
8
+ "resetwarnings", "catch_warnings"]
9
+
10
+ def showwarning(message, category, filename, lineno, file=None, line=None):
11
+ """Hook to write a warning to a file; replace if you like."""
12
+ msg = WarningMessage(message, category, filename, lineno, file, line)
13
+ _showwarnmsg_impl(msg)
14
+
15
+ def formatwarning(message, category, filename, lineno, line=None):
16
+ """Function to format a warning the standard way."""
17
+ msg = WarningMessage(message, category, filename, lineno, None, line)
18
+ return _formatwarnmsg_impl(msg)
19
+
20
+ def _showwarnmsg_impl(msg):
21
+ file = msg.file
22
+ if file is None:
23
+ file = sys.stderr
24
+ if file is None:
25
+ # sys.stderr is None when run with pythonw.exe:
26
+ # warnings get lost
27
+ return
28
+ text = _formatwarnmsg(msg)
29
+ try:
30
+ file.write(text)
31
+ except OSError:
32
+ # the file (probably stderr) is invalid - this warning gets lost.
33
+ pass
34
+
35
+ def _formatwarnmsg_impl(msg):
36
+ category = msg.category.__name__
37
+ s = f"{msg.filename}:{msg.lineno}: {category}: {msg.message}\n"
38
+
39
+ if msg.line is None:
40
+ try:
41
+ import linecache
42
+ line = linecache.getline(msg.filename, msg.lineno)
43
+ except Exception:
44
+ # When a warning is logged during Python shutdown, linecache
45
+ # and the import machinery don't work anymore
46
+ line = None
47
+ linecache = None
48
+ else:
49
+ line = msg.line
50
+ if line:
51
+ line = line.strip()
52
+ s += " %s\n" % line
53
+
54
+ if msg.source is not None:
55
+ try:
56
+ import tracemalloc
57
+ # Logging a warning should not raise a new exception:
58
+ # catch Exception, not only ImportError and RecursionError.
59
+ except Exception:
60
+ # don't suggest to enable tracemalloc if it's not available
61
+ tracing = True
62
+ tb = None
63
+ else:
64
+ tracing = tracemalloc.is_tracing()
65
+ try:
66
+ tb = tracemalloc.get_object_traceback(msg.source)
67
+ except Exception:
68
+ # When a warning is logged during Python shutdown, tracemalloc
69
+ # and the import machinery don't work anymore
70
+ tb = None
71
+
72
+ if tb is not None:
73
+ s += 'Object allocated at (most recent call last):\n'
74
+ for frame in tb:
75
+ s += (' File "%s", lineno %s\n'
76
+ % (frame.filename, frame.lineno))
77
+
78
+ try:
79
+ if linecache is not None:
80
+ line = linecache.getline(frame.filename, frame.lineno)
81
+ else:
82
+ line = None
83
+ except Exception:
84
+ line = None
85
+ if line:
86
+ line = line.strip()
87
+ s += ' %s\n' % line
88
+ elif not tracing:
89
+ s += (f'{category}: Enable tracemalloc to get the object '
90
+ f'allocation traceback\n')
91
+ return s
92
+
93
+ # Keep a reference to check if the function was replaced
94
+ _showwarning_orig = showwarning
95
+
96
+ def _showwarnmsg(msg):
97
+ """Hook to write a warning to a file; replace if you like."""
98
+ try:
99
+ sw = showwarning
100
+ except NameError:
101
+ pass
102
+ else:
103
+ if sw is not _showwarning_orig:
104
+ # warnings.showwarning() was replaced
105
+ if not callable(sw):
106
+ raise TypeError("warnings.showwarning() must be set to a "
107
+ "function or method")
108
+
109
+ sw(msg.message, msg.category, msg.filename, msg.lineno,
110
+ msg.file, msg.line)
111
+ return
112
+ _showwarnmsg_impl(msg)
113
+
114
+ # Keep a reference to check if the function was replaced
115
+ _formatwarning_orig = formatwarning
116
+
117
+ def _formatwarnmsg(msg):
118
+ """Function to format a warning the standard way."""
119
+ try:
120
+ fw = formatwarning
121
+ except NameError:
122
+ pass
123
+ else:
124
+ if fw is not _formatwarning_orig:
125
+ # warnings.formatwarning() was replaced
126
+ return fw(msg.message, msg.category,
127
+ msg.filename, msg.lineno, msg.line)
128
+ return _formatwarnmsg_impl(msg)
129
+
130
+ def filterwarnings(action, message="", category=Warning, module="", lineno=0,
131
+ append=False):
132
+ """Insert an entry into the list of warnings filters (at the front).
133
+
134
+ 'action' -- one of "error", "ignore", "always", "default", "module",
135
+ or "once"
136
+ 'message' -- a regex that the warning message must match
137
+ 'category' -- a class that the warning must be a subclass of
138
+ 'module' -- a regex that the module name must match
139
+ 'lineno' -- an integer line number, 0 matches all warnings
140
+ 'append' -- if true, append to the list of filters
141
+ """
142
+ assert action in ("error", "ignore", "always", "default", "module",
143
+ "once"), "invalid action: %r" % (action,)
144
+ assert isinstance(message, str), "message must be a string"
145
+ assert isinstance(category, type), "category must be a class"
146
+ assert issubclass(category, Warning), "category must be a Warning subclass"
147
+ assert isinstance(module, str), "module must be a string"
148
+ assert isinstance(lineno, int) and lineno >= 0, \
149
+ "lineno must be an int >= 0"
150
+
151
+ if message or module:
152
+ import re
153
+
154
+ if message:
155
+ message = re.compile(message, re.I)
156
+ else:
157
+ message = None
158
+ if module:
159
+ module = re.compile(module)
160
+ else:
161
+ module = None
162
+
163
+ _add_filter(action, message, category, module, lineno, append=append)
164
+
165
+ def simplefilter(action, category=Warning, lineno=0, append=False):
166
+ """Insert a simple entry into the list of warnings filters (at the front).
167
+
168
+ A simple filter matches all modules and messages.
169
+ 'action' -- one of "error", "ignore", "always", "default", "module",
170
+ or "once"
171
+ 'category' -- a class that the warning must be a subclass of
172
+ 'lineno' -- an integer line number, 0 matches all warnings
173
+ 'append' -- if true, append to the list of filters
174
+ """
175
+ assert action in ("error", "ignore", "always", "default", "module",
176
+ "once"), "invalid action: %r" % (action,)
177
+ assert isinstance(lineno, int) and lineno >= 0, \
178
+ "lineno must be an int >= 0"
179
+ _add_filter(action, None, category, None, lineno, append=append)
180
+
181
+ def _add_filter(*item, append):
182
+ # Remove possible duplicate filters, so new one will be placed
183
+ # in correct place. If append=True and duplicate exists, do nothing.
184
+ if not append:
185
+ try:
186
+ filters.remove(item)
187
+ except ValueError:
188
+ pass
189
+ filters.insert(0, item)
190
+ else:
191
+ if item not in filters:
192
+ filters.append(item)
193
+ _filters_mutated()
194
+
195
+ def resetwarnings():
196
+ """Clear the list of warning filters, so that no filters are active."""
197
+ filters[:] = []
198
+ _filters_mutated()
199
+
200
+ class _OptionError(Exception):
201
+ """Exception used by option processing helpers."""
202
+ pass
203
+
204
+ # Helper to process -W options passed via sys.warnoptions
205
+ def _processoptions(args):
206
+ for arg in args:
207
+ try:
208
+ _setoption(arg)
209
+ except _OptionError as msg:
210
+ print("Invalid -W option ignored:", msg, file=sys.stderr)
211
+
212
+ # Helper for _processoptions()
213
+ def _setoption(arg):
214
+ parts = arg.split(':')
215
+ if len(parts) > 5:
216
+ raise _OptionError("too many fields (max 5): %r" % (arg,))
217
+ while len(parts) < 5:
218
+ parts.append('')
219
+ action, message, category, module, lineno = [s.strip()
220
+ for s in parts]
221
+ action = _getaction(action)
222
+ category = _getcategory(category)
223
+ if message or module:
224
+ import re
225
+ if message:
226
+ message = re.escape(message)
227
+ if module:
228
+ module = re.escape(module) + r'\Z'
229
+ if lineno:
230
+ try:
231
+ lineno = int(lineno)
232
+ if lineno < 0:
233
+ raise ValueError
234
+ except (ValueError, OverflowError):
235
+ raise _OptionError("invalid lineno %r" % (lineno,)) from None
236
+ else:
237
+ lineno = 0
238
+ filterwarnings(action, message, category, module, lineno)
239
+
240
+ # Helper for _setoption()
241
+ def _getaction(action):
242
+ if not action:
243
+ return "default"
244
+ if action == "all": return "always" # Alias
245
+ for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
246
+ if a.startswith(action):
247
+ return a
248
+ raise _OptionError("invalid action: %r" % (action,))
249
+
250
+ # Helper for _setoption()
251
+ def _getcategory(category):
252
+ if not category:
253
+ return Warning
254
+ if '.' not in category:
255
+ import builtins as m
256
+ klass = category
257
+ else:
258
+ module, _, klass = category.rpartition('.')
259
+ try:
260
+ m = __import__(module, None, None, [klass])
261
+ except ImportError:
262
+ raise _OptionError("invalid module name: %r" % (module,)) from None
263
+ try:
264
+ cat = getattr(m, klass)
265
+ except AttributeError:
266
+ raise _OptionError("unknown warning category: %r" % (category,)) from None
267
+ if not issubclass(cat, Warning):
268
+ raise _OptionError("invalid warning category: %r" % (category,))
269
+ return cat
270
+
271
+
272
+ def _is_internal_frame(frame):
273
+ """Signal whether the frame is an internal CPython implementation detail."""
274
+ filename = frame.f_code.co_filename
275
+ return 'importlib' in filename and '_bootstrap' in filename
276
+
277
+
278
+ def _next_external_frame(frame):
279
+ """Find the next frame that doesn't involve CPython internals."""
280
+ frame = frame.f_back
281
+ while frame is not None and _is_internal_frame(frame):
282
+ frame = frame.f_back
283
+ return frame
284
+
285
+
286
+ # Code typically replaced by _warnings
287
+ def warn(message, category=None, stacklevel=1, source=None):
288
+ """Issue a warning, or maybe ignore it or raise an exception."""
289
+ # Check if message is already a Warning object
290
+ if isinstance(message, Warning):
291
+ category = message.__class__
292
+ # Check category argument
293
+ if category is None:
294
+ category = UserWarning
295
+ if not (isinstance(category, type) and issubclass(category, Warning)):
296
+ raise TypeError("category must be a Warning subclass, "
297
+ "not '{:s}'".format(type(category).__name__))
298
+ # Get context information
299
+ try:
300
+ if stacklevel <= 1 or _is_internal_frame(sys._getframe(1)):
301
+ # If frame is too small to care or if the warning originated in
302
+ # internal code, then do not try to hide any frames.
303
+ frame = sys._getframe(stacklevel)
304
+ else:
305
+ frame = sys._getframe(1)
306
+ # Look for one frame less since the above line starts us off.
307
+ for x in range(stacklevel-1):
308
+ frame = _next_external_frame(frame)
309
+ if frame is None:
310
+ raise ValueError
311
+ except ValueError:
312
+ globals = sys.__dict__
313
+ filename = "sys"
314
+ lineno = 1
315
+ else:
316
+ globals = frame.f_globals
317
+ filename = frame.f_code.co_filename
318
+ lineno = frame.f_lineno
319
+ if '__name__' in globals:
320
+ module = globals['__name__']
321
+ else:
322
+ module = "<string>"
323
+ registry = globals.setdefault("__warningregistry__", {})
324
+ warn_explicit(message, category, filename, lineno, module, registry,
325
+ globals, source)
326
+
327
+ def warn_explicit(message, category, filename, lineno,
328
+ module=None, registry=None, module_globals=None,
329
+ source=None):
330
+ lineno = int(lineno)
331
+ if module is None:
332
+ module = filename or "<unknown>"
333
+ if module[-3:].lower() == ".py":
334
+ module = module[:-3] # XXX What about leading pathname?
335
+ if registry is None:
336
+ registry = {}
337
+ if registry.get('version', 0) != _filters_version:
338
+ registry.clear()
339
+ registry['version'] = _filters_version
340
+ if isinstance(message, Warning):
341
+ text = str(message)
342
+ category = message.__class__
343
+ else:
344
+ text = message
345
+ message = category(message)
346
+ key = (text, category, lineno)
347
+ # Quick test for common case
348
+ if registry.get(key):
349
+ return
350
+ # Search the filters
351
+ for item in filters:
352
+ action, msg, cat, mod, ln = item
353
+ if ((msg is None or msg.match(text)) and
354
+ issubclass(category, cat) and
355
+ (mod is None or mod.match(module)) and
356
+ (ln == 0 or lineno == ln)):
357
+ break
358
+ else:
359
+ action = defaultaction
360
+ # Early exit actions
361
+ if action == "ignore":
362
+ return
363
+
364
+ # Prime the linecache for formatting, in case the
365
+ # "file" is actually in a zipfile or something.
366
+ import linecache
367
+ linecache.getlines(filename, module_globals)
368
+
369
+ if action == "error":
370
+ raise message
371
+ # Other actions
372
+ if action == "once":
373
+ registry[key] = 1
374
+ oncekey = (text, category)
375
+ if onceregistry.get(oncekey):
376
+ return
377
+ onceregistry[oncekey] = 1
378
+ elif action == "always":
379
+ pass
380
+ elif action == "module":
381
+ registry[key] = 1
382
+ altkey = (text, category, 0)
383
+ if registry.get(altkey):
384
+ return
385
+ registry[altkey] = 1
386
+ elif action == "default":
387
+ registry[key] = 1
388
+ else:
389
+ # Unrecognized actions are errors
390
+ raise RuntimeError(
391
+ "Unrecognized action (%r) in warnings.filters:\n %s" %
392
+ (action, item))
393
+ # Print message and context
394
+ msg = WarningMessage(message, category, filename, lineno, source)
395
+ _showwarnmsg(msg)
396
+
397
+
398
+ class WarningMessage(object):
399
+
400
+ _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
401
+ "line", "source")
402
+
403
+ def __init__(self, message, category, filename, lineno, file=None,
404
+ line=None, source=None):
405
+ self.message = message
406
+ self.category = category
407
+ self.filename = filename
408
+ self.lineno = lineno
409
+ self.file = file
410
+ self.line = line
411
+ self.source = source
412
+ self._category_name = category.__name__ if category else None
413
+
414
+ def __str__(self):
415
+ return ("{message : %r, category : %r, filename : %r, lineno : %s, "
416
+ "line : %r}" % (self.message, self._category_name,
417
+ self.filename, self.lineno, self.line))
418
+
419
+
420
+ class catch_warnings(object):
421
+
422
+ """A context manager that copies and restores the warnings filter upon
423
+ exiting the context.
424
+
425
+ The 'record' argument specifies whether warnings should be captured by a
426
+ custom implementation of warnings.showwarning() and be appended to a list
427
+ returned by the context manager. Otherwise None is returned by the context
428
+ manager. The objects appended to the list are arguments whose attributes
429
+ mirror the arguments to showwarning().
430
+
431
+ The 'module' argument is to specify an alternative module to the module
432
+ named 'warnings' and imported under that name. This argument is only useful
433
+ when testing the warnings module itself.
434
+
435
+ """
436
+
437
+ def __init__(self, *, record=False, module=None):
438
+ """Specify whether to record warnings and if an alternative module
439
+ should be used other than sys.modules['warnings'].
440
+
441
+ For compatibility with Python 3.0, please consider all arguments to be
442
+ keyword-only.
443
+
444
+ """
445
+ self._record = record
446
+ self._module = sys.modules['warnings'] if module is None else module
447
+ self._entered = False
448
+
449
+ def __repr__(self):
450
+ args = []
451
+ if self._record:
452
+ args.append("record=True")
453
+ if self._module is not sys.modules['warnings']:
454
+ args.append("module=%r" % self._module)
455
+ name = type(self).__name__
456
+ return "%s(%s)" % (name, ", ".join(args))
457
+
458
+ def __enter__(self):
459
+ if self._entered:
460
+ raise RuntimeError("Cannot enter %r twice" % self)
461
+ self._entered = True
462
+ self._filters = self._module.filters
463
+ self._module.filters = self._filters[:]
464
+ self._module._filters_mutated()
465
+ self._showwarning = self._module.showwarning
466
+ self._showwarnmsg_impl = self._module._showwarnmsg_impl
467
+ if self._record:
468
+ log = []
469
+ self._module._showwarnmsg_impl = log.append
470
+ # Reset showwarning() to the default implementation to make sure
471
+ # that _showwarnmsg() calls _showwarnmsg_impl()
472
+ self._module.showwarning = self._module._showwarning_orig
473
+ return log
474
+ else:
475
+ return None
476
+
477
+ def __exit__(self, *exc_info):
478
+ if not self._entered:
479
+ raise RuntimeError("Cannot exit %r without entering first" % self)
480
+ self._module.filters = self._filters
481
+ self._module._filters_mutated()
482
+ self._module.showwarning = self._showwarning
483
+ self._module._showwarnmsg_impl = self._showwarnmsg_impl
484
+
485
+
486
+ # Private utility function called by _PyErr_WarnUnawaitedCoroutine
487
+ def _warn_unawaited_coroutine(coro):
488
+ msg_lines = [
489
+ f"coroutine '{coro.__qualname__}' was never awaited\n"
490
+ ]
491
+ if coro.cr_origin is not None:
492
+ import linecache, traceback
493
+ def extract():
494
+ for filename, lineno, funcname in reversed(coro.cr_origin):
495
+ line = linecache.getline(filename, lineno)
496
+ yield (filename, lineno, funcname, line)
497
+ msg_lines.append("Coroutine created at (most recent call last)\n")
498
+ msg_lines += traceback.format_list(list(extract()))
499
+ msg = "".join(msg_lines).rstrip("\n")
500
+ # Passing source= here means that if the user happens to have tracemalloc
501
+ # enabled and tracking where the coroutine was created, the warning will
502
+ # contain that traceback. This does mean that if they have *both*
503
+ # coroutine origin tracking *and* tracemalloc enabled, they'll get two
504
+ # partially-redundant tracebacks. If we wanted to be clever we could
505
+ # probably detect this case and avoid it, but for now we don't bother.
506
+ warn(msg, category=RuntimeWarning, stacklevel=2, source=coro)
507
+
508
+
509
+ # filters contains a sequence of filter 5-tuples
510
+ # The components of the 5-tuple are:
511
+ # - an action: error, ignore, always, default, module, or once
512
+ # - a compiled regex that must match the warning message
513
+ # - a class representing the warning category
514
+ # - a compiled regex that must match the module that is being warned
515
+ # - a line number for the line being warning, or 0 to mean any line
516
+ # If either if the compiled regexs are None, match anything.
517
+ try:
518
+ from _warnings import (filters, _defaultaction, _onceregistry,
519
+ warn, warn_explicit, _filters_mutated)
520
+ defaultaction = _defaultaction
521
+ onceregistry = _onceregistry
522
+ _warnings_defaults = True
523
+ except ImportError:
524
+ filters = []
525
+ defaultaction = "default"
526
+ onceregistry = {}
527
+
528
+ _filters_version = 1
529
+
530
+ def _filters_mutated():
531
+ global _filters_version
532
+ _filters_version += 1
533
+
534
+ _warnings_defaults = False
535
+
536
+
537
+ # Module initialization
538
+ _processoptions(sys.warnoptions)
539
+ if not _warnings_defaults:
540
+ # Several warning categories are ignored by default in regular builds
541
+ if not hasattr(sys, 'gettotalrefcount'):
542
+ filterwarnings("default", category=DeprecationWarning,
543
+ module="__main__", append=1)
544
+ simplefilter("ignore", category=DeprecationWarning, append=1)
545
+ simplefilter("ignore", category=PendingDeprecationWarning, append=1)
546
+ simplefilter("ignore", category=ImportWarning, append=1)
547
+ simplefilter("ignore", category=ResourceWarning, append=1)
548
+
549
+ del _warnings_defaults
lib/python3.10/wave.py ADDED
@@ -0,0 +1,513 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Stuff to parse WAVE files.
2
+
3
+ Usage.
4
+
5
+ Reading WAVE files:
6
+ f = wave.open(file, 'r')
7
+ where file is either the name of a file or an open file pointer.
8
+ The open file pointer must have methods read(), seek(), and close().
9
+ When the setpos() and rewind() methods are not used, the seek()
10
+ method is not necessary.
11
+
12
+ This returns an instance of a class with the following public methods:
13
+ getnchannels() -- returns number of audio channels (1 for
14
+ mono, 2 for stereo)
15
+ getsampwidth() -- returns sample width in bytes
16
+ getframerate() -- returns sampling frequency
17
+ getnframes() -- returns number of audio frames
18
+ getcomptype() -- returns compression type ('NONE' for linear samples)
19
+ getcompname() -- returns human-readable version of
20
+ compression type ('not compressed' linear samples)
21
+ getparams() -- returns a namedtuple consisting of all of the
22
+ above in the above order
23
+ getmarkers() -- returns None (for compatibility with the
24
+ aifc module)
25
+ getmark(id) -- raises an error since the mark does not
26
+ exist (for compatibility with the aifc module)
27
+ readframes(n) -- returns at most n frames of audio
28
+ rewind() -- rewind to the beginning of the audio stream
29
+ setpos(pos) -- seek to the specified position
30
+ tell() -- return the current position
31
+ close() -- close the instance (make it unusable)
32
+ The position returned by tell() and the position given to setpos()
33
+ are compatible and have nothing to do with the actual position in the
34
+ file.
35
+ The close() method is called automatically when the class instance
36
+ is destroyed.
37
+
38
+ Writing WAVE files:
39
+ f = wave.open(file, 'w')
40
+ where file is either the name of a file or an open file pointer.
41
+ The open file pointer must have methods write(), tell(), seek(), and
42
+ close().
43
+
44
+ This returns an instance of a class with the following public methods:
45
+ setnchannels(n) -- set the number of channels
46
+ setsampwidth(n) -- set the sample width
47
+ setframerate(n) -- set the frame rate
48
+ setnframes(n) -- set the number of frames
49
+ setcomptype(type, name)
50
+ -- set the compression type and the
51
+ human-readable compression type
52
+ setparams(tuple)
53
+ -- set all parameters at once
54
+ tell() -- return current position in output file
55
+ writeframesraw(data)
56
+ -- write audio frames without patching up the
57
+ file header
58
+ writeframes(data)
59
+ -- write audio frames and patch up the file header
60
+ close() -- patch up the file header and close the
61
+ output file
62
+ You should set the parameters before the first writeframesraw or
63
+ writeframes. The total number of frames does not need to be set,
64
+ but when it is set to the correct value, the header does not have to
65
+ be patched up.
66
+ It is best to first set all parameters, perhaps possibly the
67
+ compression type, and then write audio frames using writeframesraw.
68
+ When all frames have been written, either call writeframes(b'') or
69
+ close() to patch up the sizes in the header.
70
+ The close() method is called automatically when the class instance
71
+ is destroyed.
72
+ """
73
+
74
+ from chunk import Chunk
75
+ from collections import namedtuple
76
+ import audioop
77
+ import builtins
78
+ import struct
79
+ import sys
80
+
81
+
82
+ __all__ = ["open", "Error", "Wave_read", "Wave_write"]
83
+
84
+ class Error(Exception):
85
+ pass
86
+
87
+ WAVE_FORMAT_PCM = 0x0001
88
+
89
+ _array_fmts = None, 'b', 'h', None, 'i'
90
+
91
+ _wave_params = namedtuple('_wave_params',
92
+ 'nchannels sampwidth framerate nframes comptype compname')
93
+
94
+ class Wave_read:
95
+ """Variables used in this class:
96
+
97
+ These variables are available to the user though appropriate
98
+ methods of this class:
99
+ _file -- the open file with methods read(), close(), and seek()
100
+ set through the __init__() method
101
+ _nchannels -- the number of audio channels
102
+ available through the getnchannels() method
103
+ _nframes -- the number of audio frames
104
+ available through the getnframes() method
105
+ _sampwidth -- the number of bytes per audio sample
106
+ available through the getsampwidth() method
107
+ _framerate -- the sampling frequency
108
+ available through the getframerate() method
109
+ _comptype -- the AIFF-C compression type ('NONE' if AIFF)
110
+ available through the getcomptype() method
111
+ _compname -- the human-readable AIFF-C compression type
112
+ available through the getcomptype() method
113
+ _soundpos -- the position in the audio stream
114
+ available through the tell() method, set through the
115
+ setpos() method
116
+
117
+ These variables are used internally only:
118
+ _fmt_chunk_read -- 1 iff the FMT chunk has been read
119
+ _data_seek_needed -- 1 iff positioned correctly in audio
120
+ file for readframes()
121
+ _data_chunk -- instantiation of a chunk class for the DATA chunk
122
+ _framesize -- size of one frame in the file
123
+ """
124
+
125
+ def initfp(self, file):
126
+ self._convert = None
127
+ self._soundpos = 0
128
+ self._file = Chunk(file, bigendian = 0)
129
+ if self._file.getname() != b'RIFF':
130
+ raise Error('file does not start with RIFF id')
131
+ if self._file.read(4) != b'WAVE':
132
+ raise Error('not a WAVE file')
133
+ self._fmt_chunk_read = 0
134
+ self._data_chunk = None
135
+ while 1:
136
+ self._data_seek_needed = 1
137
+ try:
138
+ chunk = Chunk(self._file, bigendian = 0)
139
+ except EOFError:
140
+ break
141
+ chunkname = chunk.getname()
142
+ if chunkname == b'fmt ':
143
+ self._read_fmt_chunk(chunk)
144
+ self._fmt_chunk_read = 1
145
+ elif chunkname == b'data':
146
+ if not self._fmt_chunk_read:
147
+ raise Error('data chunk before fmt chunk')
148
+ self._data_chunk = chunk
149
+ self._nframes = chunk.chunksize // self._framesize
150
+ self._data_seek_needed = 0
151
+ break
152
+ chunk.skip()
153
+ if not self._fmt_chunk_read or not self._data_chunk:
154
+ raise Error('fmt chunk and/or data chunk missing')
155
+
156
+ def __init__(self, f):
157
+ self._i_opened_the_file = None
158
+ if isinstance(f, str):
159
+ f = builtins.open(f, 'rb')
160
+ self._i_opened_the_file = f
161
+ # else, assume it is an open file object already
162
+ try:
163
+ self.initfp(f)
164
+ except:
165
+ if self._i_opened_the_file:
166
+ f.close()
167
+ raise
168
+
169
+ def __del__(self):
170
+ self.close()
171
+
172
+ def __enter__(self):
173
+ return self
174
+
175
+ def __exit__(self, *args):
176
+ self.close()
177
+
178
+ #
179
+ # User visible methods.
180
+ #
181
+ def getfp(self):
182
+ return self._file
183
+
184
+ def rewind(self):
185
+ self._data_seek_needed = 1
186
+ self._soundpos = 0
187
+
188
+ def close(self):
189
+ self._file = None
190
+ file = self._i_opened_the_file
191
+ if file:
192
+ self._i_opened_the_file = None
193
+ file.close()
194
+
195
+ def tell(self):
196
+ return self._soundpos
197
+
198
+ def getnchannels(self):
199
+ return self._nchannels
200
+
201
+ def getnframes(self):
202
+ return self._nframes
203
+
204
+ def getsampwidth(self):
205
+ return self._sampwidth
206
+
207
+ def getframerate(self):
208
+ return self._framerate
209
+
210
+ def getcomptype(self):
211
+ return self._comptype
212
+
213
+ def getcompname(self):
214
+ return self._compname
215
+
216
+ def getparams(self):
217
+ return _wave_params(self.getnchannels(), self.getsampwidth(),
218
+ self.getframerate(), self.getnframes(),
219
+ self.getcomptype(), self.getcompname())
220
+
221
+ def getmarkers(self):
222
+ return None
223
+
224
+ def getmark(self, id):
225
+ raise Error('no marks')
226
+
227
+ def setpos(self, pos):
228
+ if pos < 0 or pos > self._nframes:
229
+ raise Error('position not in range')
230
+ self._soundpos = pos
231
+ self._data_seek_needed = 1
232
+
233
+ def readframes(self, nframes):
234
+ if self._data_seek_needed:
235
+ self._data_chunk.seek(0, 0)
236
+ pos = self._soundpos * self._framesize
237
+ if pos:
238
+ self._data_chunk.seek(pos, 0)
239
+ self._data_seek_needed = 0
240
+ if nframes == 0:
241
+ return b''
242
+ data = self._data_chunk.read(nframes * self._framesize)
243
+ if self._sampwidth != 1 and sys.byteorder == 'big':
244
+ data = audioop.byteswap(data, self._sampwidth)
245
+ if self._convert and data:
246
+ data = self._convert(data)
247
+ self._soundpos = self._soundpos + len(data) // (self._nchannels * self._sampwidth)
248
+ return data
249
+
250
+ #
251
+ # Internal methods.
252
+ #
253
+
254
+ def _read_fmt_chunk(self, chunk):
255
+ try:
256
+ wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))
257
+ except struct.error:
258
+ raise EOFError from None
259
+ if wFormatTag == WAVE_FORMAT_PCM:
260
+ try:
261
+ sampwidth = struct.unpack_from('<H', chunk.read(2))[0]
262
+ except struct.error:
263
+ raise EOFError from None
264
+ self._sampwidth = (sampwidth + 7) // 8
265
+ if not self._sampwidth:
266
+ raise Error('bad sample width')
267
+ else:
268
+ raise Error('unknown format: %r' % (wFormatTag,))
269
+ if not self._nchannels:
270
+ raise Error('bad # of channels')
271
+ self._framesize = self._nchannels * self._sampwidth
272
+ self._comptype = 'NONE'
273
+ self._compname = 'not compressed'
274
+
275
+ class Wave_write:
276
+ """Variables used in this class:
277
+
278
+ These variables are user settable through appropriate methods
279
+ of this class:
280
+ _file -- the open file with methods write(), close(), tell(), seek()
281
+ set through the __init__() method
282
+ _comptype -- the AIFF-C compression type ('NONE' in AIFF)
283
+ set through the setcomptype() or setparams() method
284
+ _compname -- the human-readable AIFF-C compression type
285
+ set through the setcomptype() or setparams() method
286
+ _nchannels -- the number of audio channels
287
+ set through the setnchannels() or setparams() method
288
+ _sampwidth -- the number of bytes per audio sample
289
+ set through the setsampwidth() or setparams() method
290
+ _framerate -- the sampling frequency
291
+ set through the setframerate() or setparams() method
292
+ _nframes -- the number of audio frames written to the header
293
+ set through the setnframes() or setparams() method
294
+
295
+ These variables are used internally only:
296
+ _datalength -- the size of the audio samples written to the header
297
+ _nframeswritten -- the number of frames actually written
298
+ _datawritten -- the size of the audio samples actually written
299
+ """
300
+
301
+ def __init__(self, f):
302
+ self._i_opened_the_file = None
303
+ if isinstance(f, str):
304
+ f = builtins.open(f, 'wb')
305
+ self._i_opened_the_file = f
306
+ try:
307
+ self.initfp(f)
308
+ except:
309
+ if self._i_opened_the_file:
310
+ f.close()
311
+ raise
312
+
313
+ def initfp(self, file):
314
+ self._file = file
315
+ self._convert = None
316
+ self._nchannels = 0
317
+ self._sampwidth = 0
318
+ self._framerate = 0
319
+ self._nframes = 0
320
+ self._nframeswritten = 0
321
+ self._datawritten = 0
322
+ self._datalength = 0
323
+ self._headerwritten = False
324
+
325
+ def __del__(self):
326
+ self.close()
327
+
328
+ def __enter__(self):
329
+ return self
330
+
331
+ def __exit__(self, *args):
332
+ self.close()
333
+
334
+ #
335
+ # User visible methods.
336
+ #
337
+ def setnchannels(self, nchannels):
338
+ if self._datawritten:
339
+ raise Error('cannot change parameters after starting to write')
340
+ if nchannels < 1:
341
+ raise Error('bad # of channels')
342
+ self._nchannels = nchannels
343
+
344
+ def getnchannels(self):
345
+ if not self._nchannels:
346
+ raise Error('number of channels not set')
347
+ return self._nchannels
348
+
349
+ def setsampwidth(self, sampwidth):
350
+ if self._datawritten:
351
+ raise Error('cannot change parameters after starting to write')
352
+ if sampwidth < 1 or sampwidth > 4:
353
+ raise Error('bad sample width')
354
+ self._sampwidth = sampwidth
355
+
356
+ def getsampwidth(self):
357
+ if not self._sampwidth:
358
+ raise Error('sample width not set')
359
+ return self._sampwidth
360
+
361
+ def setframerate(self, framerate):
362
+ if self._datawritten:
363
+ raise Error('cannot change parameters after starting to write')
364
+ if framerate <= 0:
365
+ raise Error('bad frame rate')
366
+ self._framerate = int(round(framerate))
367
+
368
+ def getframerate(self):
369
+ if not self._framerate:
370
+ raise Error('frame rate not set')
371
+ return self._framerate
372
+
373
+ def setnframes(self, nframes):
374
+ if self._datawritten:
375
+ raise Error('cannot change parameters after starting to write')
376
+ self._nframes = nframes
377
+
378
+ def getnframes(self):
379
+ return self._nframeswritten
380
+
381
+ def setcomptype(self, comptype, compname):
382
+ if self._datawritten:
383
+ raise Error('cannot change parameters after starting to write')
384
+ if comptype not in ('NONE',):
385
+ raise Error('unsupported compression type')
386
+ self._comptype = comptype
387
+ self._compname = compname
388
+
389
+ def getcomptype(self):
390
+ return self._comptype
391
+
392
+ def getcompname(self):
393
+ return self._compname
394
+
395
+ def setparams(self, params):
396
+ nchannels, sampwidth, framerate, nframes, comptype, compname = params
397
+ if self._datawritten:
398
+ raise Error('cannot change parameters after starting to write')
399
+ self.setnchannels(nchannels)
400
+ self.setsampwidth(sampwidth)
401
+ self.setframerate(framerate)
402
+ self.setnframes(nframes)
403
+ self.setcomptype(comptype, compname)
404
+
405
+ def getparams(self):
406
+ if not self._nchannels or not self._sampwidth or not self._framerate:
407
+ raise Error('not all parameters set')
408
+ return _wave_params(self._nchannels, self._sampwidth, self._framerate,
409
+ self._nframes, self._comptype, self._compname)
410
+
411
+ def setmark(self, id, pos, name):
412
+ raise Error('setmark() not supported')
413
+
414
+ def getmark(self, id):
415
+ raise Error('no marks')
416
+
417
+ def getmarkers(self):
418
+ return None
419
+
420
+ def tell(self):
421
+ return self._nframeswritten
422
+
423
+ def writeframesraw(self, data):
424
+ if not isinstance(data, (bytes, bytearray)):
425
+ data = memoryview(data).cast('B')
426
+ self._ensure_header_written(len(data))
427
+ nframes = len(data) // (self._sampwidth * self._nchannels)
428
+ if self._convert:
429
+ data = self._convert(data)
430
+ if self._sampwidth != 1 and sys.byteorder == 'big':
431
+ data = audioop.byteswap(data, self._sampwidth)
432
+ self._file.write(data)
433
+ self._datawritten += len(data)
434
+ self._nframeswritten = self._nframeswritten + nframes
435
+
436
+ def writeframes(self, data):
437
+ self.writeframesraw(data)
438
+ if self._datalength != self._datawritten:
439
+ self._patchheader()
440
+
441
+ def close(self):
442
+ try:
443
+ if self._file:
444
+ self._ensure_header_written(0)
445
+ if self._datalength != self._datawritten:
446
+ self._patchheader()
447
+ self._file.flush()
448
+ finally:
449
+ self._file = None
450
+ file = self._i_opened_the_file
451
+ if file:
452
+ self._i_opened_the_file = None
453
+ file.close()
454
+
455
+ #
456
+ # Internal methods.
457
+ #
458
+
459
+ def _ensure_header_written(self, datasize):
460
+ if not self._headerwritten:
461
+ if not self._nchannels:
462
+ raise Error('# channels not specified')
463
+ if not self._sampwidth:
464
+ raise Error('sample width not specified')
465
+ if not self._framerate:
466
+ raise Error('sampling rate not specified')
467
+ self._write_header(datasize)
468
+
469
+ def _write_header(self, initlength):
470
+ assert not self._headerwritten
471
+ self._file.write(b'RIFF')
472
+ if not self._nframes:
473
+ self._nframes = initlength // (self._nchannels * self._sampwidth)
474
+ self._datalength = self._nframes * self._nchannels * self._sampwidth
475
+ try:
476
+ self._form_length_pos = self._file.tell()
477
+ except (AttributeError, OSError):
478
+ self._form_length_pos = None
479
+ self._file.write(struct.pack('<L4s4sLHHLLHH4s',
480
+ 36 + self._datalength, b'WAVE', b'fmt ', 16,
481
+ WAVE_FORMAT_PCM, self._nchannels, self._framerate,
482
+ self._nchannels * self._framerate * self._sampwidth,
483
+ self._nchannels * self._sampwidth,
484
+ self._sampwidth * 8, b'data'))
485
+ if self._form_length_pos is not None:
486
+ self._data_length_pos = self._file.tell()
487
+ self._file.write(struct.pack('<L', self._datalength))
488
+ self._headerwritten = True
489
+
490
+ def _patchheader(self):
491
+ assert self._headerwritten
492
+ if self._datawritten == self._datalength:
493
+ return
494
+ curpos = self._file.tell()
495
+ self._file.seek(self._form_length_pos, 0)
496
+ self._file.write(struct.pack('<L', 36 + self._datawritten))
497
+ self._file.seek(self._data_length_pos, 0)
498
+ self._file.write(struct.pack('<L', self._datawritten))
499
+ self._file.seek(curpos, 0)
500
+ self._datalength = self._datawritten
501
+
502
+ def open(f, mode=None):
503
+ if mode is None:
504
+ if hasattr(f, 'mode'):
505
+ mode = f.mode
506
+ else:
507
+ mode = 'rb'
508
+ if mode in ('r', 'rb'):
509
+ return Wave_read(f)
510
+ elif mode in ('w', 'wb'):
511
+ return Wave_write(f)
512
+ else:
513
+ raise Error("mode must be 'r', 'rb', 'w', or 'wb'")
lib/python3.10/weakref.py ADDED
@@ -0,0 +1,675 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Weak reference support for Python.
2
+
3
+ This module is an implementation of PEP 205:
4
+
5
+ https://www.python.org/dev/peps/pep-0205/
6
+ """
7
+
8
+ # Naming convention: Variables named "wr" are weak reference objects;
9
+ # they are called this instead of "ref" to avoid name collisions with
10
+ # the module-global ref() function imported from _weakref.
11
+
12
+ from _weakref import (
13
+ getweakrefcount,
14
+ getweakrefs,
15
+ ref,
16
+ proxy,
17
+ CallableProxyType,
18
+ ProxyType,
19
+ ReferenceType,
20
+ _remove_dead_weakref)
21
+
22
+ from _weakrefset import WeakSet, _IterationGuard
23
+
24
+ import _collections_abc # Import after _weakref to avoid circular import.
25
+ import sys
26
+ import itertools
27
+
28
+ ProxyTypes = (ProxyType, CallableProxyType)
29
+
30
+ __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
31
+ "WeakKeyDictionary", "ReferenceType", "ProxyType",
32
+ "CallableProxyType", "ProxyTypes", "WeakValueDictionary",
33
+ "WeakSet", "WeakMethod", "finalize"]
34
+
35
+
36
+ _collections_abc.Set.register(WeakSet)
37
+ _collections_abc.MutableSet.register(WeakSet)
38
+
39
+ class WeakMethod(ref):
40
+ """
41
+ A custom `weakref.ref` subclass which simulates a weak reference to
42
+ a bound method, working around the lifetime problem of bound methods.
43
+ """
44
+
45
+ __slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__"
46
+
47
+ def __new__(cls, meth, callback=None):
48
+ try:
49
+ obj = meth.__self__
50
+ func = meth.__func__
51
+ except AttributeError:
52
+ raise TypeError("argument should be a bound method, not {}"
53
+ .format(type(meth))) from None
54
+ def _cb(arg):
55
+ # The self-weakref trick is needed to avoid creating a reference
56
+ # cycle.
57
+ self = self_wr()
58
+ if self._alive:
59
+ self._alive = False
60
+ if callback is not None:
61
+ callback(self)
62
+ self = ref.__new__(cls, obj, _cb)
63
+ self._func_ref = ref(func, _cb)
64
+ self._meth_type = type(meth)
65
+ self._alive = True
66
+ self_wr = ref(self)
67
+ return self
68
+
69
+ def __call__(self):
70
+ obj = super().__call__()
71
+ func = self._func_ref()
72
+ if obj is None or func is None:
73
+ return None
74
+ return self._meth_type(func, obj)
75
+
76
+ def __eq__(self, other):
77
+ if isinstance(other, WeakMethod):
78
+ if not self._alive or not other._alive:
79
+ return self is other
80
+ return ref.__eq__(self, other) and self._func_ref == other._func_ref
81
+ return NotImplemented
82
+
83
+ def __ne__(self, other):
84
+ if isinstance(other, WeakMethod):
85
+ if not self._alive or not other._alive:
86
+ return self is not other
87
+ return ref.__ne__(self, other) or self._func_ref != other._func_ref
88
+ return NotImplemented
89
+
90
+ __hash__ = ref.__hash__
91
+
92
+
93
+ class WeakValueDictionary(_collections_abc.MutableMapping):
94
+ """Mapping class that references values weakly.
95
+
96
+ Entries in the dictionary will be discarded when no strong
97
+ reference to the value exists anymore
98
+ """
99
+ # We inherit the constructor without worrying about the input
100
+ # dictionary; since it uses our .update() method, we get the right
101
+ # checks (if the other dictionary is a WeakValueDictionary,
102
+ # objects are unwrapped on the way out, and we always wrap on the
103
+ # way in).
104
+
105
+ def __init__(self, other=(), /, **kw):
106
+ def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
107
+ self = selfref()
108
+ if self is not None:
109
+ if self._iterating:
110
+ self._pending_removals.append(wr.key)
111
+ else:
112
+ # Atomic removal is necessary since this function
113
+ # can be called asynchronously by the GC
114
+ _atomic_removal(self.data, wr.key)
115
+ self._remove = remove
116
+ # A list of keys to be removed
117
+ self._pending_removals = []
118
+ self._iterating = set()
119
+ self.data = {}
120
+ self.update(other, **kw)
121
+
122
+ def _commit_removals(self, _atomic_removal=_remove_dead_weakref):
123
+ pop = self._pending_removals.pop
124
+ d = self.data
125
+ # We shouldn't encounter any KeyError, because this method should
126
+ # always be called *before* mutating the dict.
127
+ while True:
128
+ try:
129
+ key = pop()
130
+ except IndexError:
131
+ return
132
+ _atomic_removal(d, key)
133
+
134
+ def __getitem__(self, key):
135
+ if self._pending_removals:
136
+ self._commit_removals()
137
+ o = self.data[key]()
138
+ if o is None:
139
+ raise KeyError(key)
140
+ else:
141
+ return o
142
+
143
+ def __delitem__(self, key):
144
+ if self._pending_removals:
145
+ self._commit_removals()
146
+ del self.data[key]
147
+
148
+ def __len__(self):
149
+ if self._pending_removals:
150
+ self._commit_removals()
151
+ return len(self.data)
152
+
153
+ def __contains__(self, key):
154
+ if self._pending_removals:
155
+ self._commit_removals()
156
+ try:
157
+ o = self.data[key]()
158
+ except KeyError:
159
+ return False
160
+ return o is not None
161
+
162
+ def __repr__(self):
163
+ return "<%s at %#x>" % (self.__class__.__name__, id(self))
164
+
165
+ def __setitem__(self, key, value):
166
+ if self._pending_removals:
167
+ self._commit_removals()
168
+ self.data[key] = KeyedRef(value, self._remove, key)
169
+
170
+ def copy(self):
171
+ if self._pending_removals:
172
+ self._commit_removals()
173
+ new = WeakValueDictionary()
174
+ with _IterationGuard(self):
175
+ for key, wr in self.data.items():
176
+ o = wr()
177
+ if o is not None:
178
+ new[key] = o
179
+ return new
180
+
181
+ __copy__ = copy
182
+
183
+ def __deepcopy__(self, memo):
184
+ from copy import deepcopy
185
+ if self._pending_removals:
186
+ self._commit_removals()
187
+ new = self.__class__()
188
+ with _IterationGuard(self):
189
+ for key, wr in self.data.items():
190
+ o = wr()
191
+ if o is not None:
192
+ new[deepcopy(key, memo)] = o
193
+ return new
194
+
195
+ def get(self, key, default=None):
196
+ if self._pending_removals:
197
+ self._commit_removals()
198
+ try:
199
+ wr = self.data[key]
200
+ except KeyError:
201
+ return default
202
+ else:
203
+ o = wr()
204
+ if o is None:
205
+ # This should only happen
206
+ return default
207
+ else:
208
+ return o
209
+
210
+ def items(self):
211
+ if self._pending_removals:
212
+ self._commit_removals()
213
+ with _IterationGuard(self):
214
+ for k, wr in self.data.items():
215
+ v = wr()
216
+ if v is not None:
217
+ yield k, v
218
+
219
+ def keys(self):
220
+ if self._pending_removals:
221
+ self._commit_removals()
222
+ with _IterationGuard(self):
223
+ for k, wr in self.data.items():
224
+ if wr() is not None:
225
+ yield k
226
+
227
+ __iter__ = keys
228
+
229
+ def itervaluerefs(self):
230
+ """Return an iterator that yields the weak references to the values.
231
+
232
+ The references are not guaranteed to be 'live' at the time
233
+ they are used, so the result of calling the references needs
234
+ to be checked before being used. This can be used to avoid
235
+ creating references that will cause the garbage collector to
236
+ keep the values around longer than needed.
237
+
238
+ """
239
+ if self._pending_removals:
240
+ self._commit_removals()
241
+ with _IterationGuard(self):
242
+ yield from self.data.values()
243
+
244
+ def values(self):
245
+ if self._pending_removals:
246
+ self._commit_removals()
247
+ with _IterationGuard(self):
248
+ for wr in self.data.values():
249
+ obj = wr()
250
+ if obj is not None:
251
+ yield obj
252
+
253
+ def popitem(self):
254
+ if self._pending_removals:
255
+ self._commit_removals()
256
+ while True:
257
+ key, wr = self.data.popitem()
258
+ o = wr()
259
+ if o is not None:
260
+ return key, o
261
+
262
+ def pop(self, key, *args):
263
+ if self._pending_removals:
264
+ self._commit_removals()
265
+ try:
266
+ o = self.data.pop(key)()
267
+ except KeyError:
268
+ o = None
269
+ if o is None:
270
+ if args:
271
+ return args[0]
272
+ else:
273
+ raise KeyError(key)
274
+ else:
275
+ return o
276
+
277
+ def setdefault(self, key, default=None):
278
+ try:
279
+ o = self.data[key]()
280
+ except KeyError:
281
+ o = None
282
+ if o is None:
283
+ if self._pending_removals:
284
+ self._commit_removals()
285
+ self.data[key] = KeyedRef(default, self._remove, key)
286
+ return default
287
+ else:
288
+ return o
289
+
290
+ def update(self, other=None, /, **kwargs):
291
+ if self._pending_removals:
292
+ self._commit_removals()
293
+ d = self.data
294
+ if other is not None:
295
+ if not hasattr(other, "items"):
296
+ other = dict(other)
297
+ for key, o in other.items():
298
+ d[key] = KeyedRef(o, self._remove, key)
299
+ for key, o in kwargs.items():
300
+ d[key] = KeyedRef(o, self._remove, key)
301
+
302
+ def valuerefs(self):
303
+ """Return a list of weak references to the values.
304
+
305
+ The references are not guaranteed to be 'live' at the time
306
+ they are used, so the result of calling the references needs
307
+ to be checked before being used. This can be used to avoid
308
+ creating references that will cause the garbage collector to
309
+ keep the values around longer than needed.
310
+
311
+ """
312
+ if self._pending_removals:
313
+ self._commit_removals()
314
+ return list(self.data.values())
315
+
316
+ def __ior__(self, other):
317
+ self.update(other)
318
+ return self
319
+
320
+ def __or__(self, other):
321
+ if isinstance(other, _collections_abc.Mapping):
322
+ c = self.copy()
323
+ c.update(other)
324
+ return c
325
+ return NotImplemented
326
+
327
+ def __ror__(self, other):
328
+ if isinstance(other, _collections_abc.Mapping):
329
+ c = self.__class__()
330
+ c.update(other)
331
+ c.update(self)
332
+ return c
333
+ return NotImplemented
334
+
335
+
336
+ class KeyedRef(ref):
337
+ """Specialized reference that includes a key corresponding to the value.
338
+
339
+ This is used in the WeakValueDictionary to avoid having to create
340
+ a function object for each key stored in the mapping. A shared
341
+ callback object can use the 'key' attribute of a KeyedRef instead
342
+ of getting a reference to the key from an enclosing scope.
343
+
344
+ """
345
+
346
+ __slots__ = "key",
347
+
348
+ def __new__(type, ob, callback, key):
349
+ self = ref.__new__(type, ob, callback)
350
+ self.key = key
351
+ return self
352
+
353
+ def __init__(self, ob, callback, key):
354
+ super().__init__(ob, callback)
355
+
356
+
357
+ class WeakKeyDictionary(_collections_abc.MutableMapping):
358
+ """ Mapping class that references keys weakly.
359
+
360
+ Entries in the dictionary will be discarded when there is no
361
+ longer a strong reference to the key. This can be used to
362
+ associate additional data with an object owned by other parts of
363
+ an application without adding attributes to those objects. This
364
+ can be especially useful with objects that override attribute
365
+ accesses.
366
+ """
367
+
368
+ def __init__(self, dict=None):
369
+ self.data = {}
370
+ def remove(k, selfref=ref(self)):
371
+ self = selfref()
372
+ if self is not None:
373
+ if self._iterating:
374
+ self._pending_removals.append(k)
375
+ else:
376
+ try:
377
+ del self.data[k]
378
+ except KeyError:
379
+ pass
380
+ self._remove = remove
381
+ # A list of dead weakrefs (keys to be removed)
382
+ self._pending_removals = []
383
+ self._iterating = set()
384
+ self._dirty_len = False
385
+ if dict is not None:
386
+ self.update(dict)
387
+
388
+ def _commit_removals(self):
389
+ # NOTE: We don't need to call this method before mutating the dict,
390
+ # because a dead weakref never compares equal to a live weakref,
391
+ # even if they happened to refer to equal objects.
392
+ # However, it means keys may already have been removed.
393
+ pop = self._pending_removals.pop
394
+ d = self.data
395
+ while True:
396
+ try:
397
+ key = pop()
398
+ except IndexError:
399
+ return
400
+
401
+ try:
402
+ del d[key]
403
+ except KeyError:
404
+ pass
405
+
406
+ def _scrub_removals(self):
407
+ d = self.data
408
+ self._pending_removals = [k for k in self._pending_removals if k in d]
409
+ self._dirty_len = False
410
+
411
+ def __delitem__(self, key):
412
+ self._dirty_len = True
413
+ del self.data[ref(key)]
414
+
415
+ def __getitem__(self, key):
416
+ return self.data[ref(key)]
417
+
418
+ def __len__(self):
419
+ if self._dirty_len and self._pending_removals:
420
+ # self._pending_removals may still contain keys which were
421
+ # explicitly removed, we have to scrub them (see issue #21173).
422
+ self._scrub_removals()
423
+ return len(self.data) - len(self._pending_removals)
424
+
425
+ def __repr__(self):
426
+ return "<%s at %#x>" % (self.__class__.__name__, id(self))
427
+
428
+ def __setitem__(self, key, value):
429
+ self.data[ref(key, self._remove)] = value
430
+
431
+ def copy(self):
432
+ new = WeakKeyDictionary()
433
+ with _IterationGuard(self):
434
+ for key, value in self.data.items():
435
+ o = key()
436
+ if o is not None:
437
+ new[o] = value
438
+ return new
439
+
440
+ __copy__ = copy
441
+
442
+ def __deepcopy__(self, memo):
443
+ from copy import deepcopy
444
+ new = self.__class__()
445
+ with _IterationGuard(self):
446
+ for key, value in self.data.items():
447
+ o = key()
448
+ if o is not None:
449
+ new[o] = deepcopy(value, memo)
450
+ return new
451
+
452
+ def get(self, key, default=None):
453
+ return self.data.get(ref(key),default)
454
+
455
+ def __contains__(self, key):
456
+ try:
457
+ wr = ref(key)
458
+ except TypeError:
459
+ return False
460
+ return wr in self.data
461
+
462
+ def items(self):
463
+ with _IterationGuard(self):
464
+ for wr, value in self.data.items():
465
+ key = wr()
466
+ if key is not None:
467
+ yield key, value
468
+
469
+ def keys(self):
470
+ with _IterationGuard(self):
471
+ for wr in self.data:
472
+ obj = wr()
473
+ if obj is not None:
474
+ yield obj
475
+
476
+ __iter__ = keys
477
+
478
+ def values(self):
479
+ with _IterationGuard(self):
480
+ for wr, value in self.data.items():
481
+ if wr() is not None:
482
+ yield value
483
+
484
+ def keyrefs(self):
485
+ """Return a list of weak references to the keys.
486
+
487
+ The references are not guaranteed to be 'live' at the time
488
+ they are used, so the result of calling the references needs
489
+ to be checked before being used. This can be used to avoid
490
+ creating references that will cause the garbage collector to
491
+ keep the keys around longer than needed.
492
+
493
+ """
494
+ return list(self.data)
495
+
496
+ def popitem(self):
497
+ self._dirty_len = True
498
+ while True:
499
+ key, value = self.data.popitem()
500
+ o = key()
501
+ if o is not None:
502
+ return o, value
503
+
504
+ def pop(self, key, *args):
505
+ self._dirty_len = True
506
+ return self.data.pop(ref(key), *args)
507
+
508
+ def setdefault(self, key, default=None):
509
+ return self.data.setdefault(ref(key, self._remove),default)
510
+
511
+ def update(self, dict=None, /, **kwargs):
512
+ d = self.data
513
+ if dict is not None:
514
+ if not hasattr(dict, "items"):
515
+ dict = type({})(dict)
516
+ for key, value in dict.items():
517
+ d[ref(key, self._remove)] = value
518
+ if len(kwargs):
519
+ self.update(kwargs)
520
+
521
+ def __ior__(self, other):
522
+ self.update(other)
523
+ return self
524
+
525
+ def __or__(self, other):
526
+ if isinstance(other, _collections_abc.Mapping):
527
+ c = self.copy()
528
+ c.update(other)
529
+ return c
530
+ return NotImplemented
531
+
532
+ def __ror__(self, other):
533
+ if isinstance(other, _collections_abc.Mapping):
534
+ c = self.__class__()
535
+ c.update(other)
536
+ c.update(self)
537
+ return c
538
+ return NotImplemented
539
+
540
+
541
+ class finalize:
542
+ """Class for finalization of weakrefable objects
543
+
544
+ finalize(obj, func, *args, **kwargs) returns a callable finalizer
545
+ object which will be called when obj is garbage collected. The
546
+ first time the finalizer is called it evaluates func(*arg, **kwargs)
547
+ and returns the result. After this the finalizer is dead, and
548
+ calling it just returns None.
549
+
550
+ When the program exits any remaining finalizers for which the
551
+ atexit attribute is true will be run in reverse order of creation.
552
+ By default atexit is true.
553
+ """
554
+
555
+ # Finalizer objects don't have any state of their own. They are
556
+ # just used as keys to lookup _Info objects in the registry. This
557
+ # ensures that they cannot be part of a ref-cycle.
558
+
559
+ __slots__ = ()
560
+ _registry = {}
561
+ _shutdown = False
562
+ _index_iter = itertools.count()
563
+ _dirty = False
564
+ _registered_with_atexit = False
565
+
566
+ class _Info:
567
+ __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index")
568
+
569
+ def __init__(self, obj, func, /, *args, **kwargs):
570
+ if not self._registered_with_atexit:
571
+ # We may register the exit function more than once because
572
+ # of a thread race, but that is harmless
573
+ import atexit
574
+ atexit.register(self._exitfunc)
575
+ finalize._registered_with_atexit = True
576
+ info = self._Info()
577
+ info.weakref = ref(obj, self)
578
+ info.func = func
579
+ info.args = args
580
+ info.kwargs = kwargs or None
581
+ info.atexit = True
582
+ info.index = next(self._index_iter)
583
+ self._registry[self] = info
584
+ finalize._dirty = True
585
+
586
+ def __call__(self, _=None):
587
+ """If alive then mark as dead and return func(*args, **kwargs);
588
+ otherwise return None"""
589
+ info = self._registry.pop(self, None)
590
+ if info and not self._shutdown:
591
+ return info.func(*info.args, **(info.kwargs or {}))
592
+
593
+ def detach(self):
594
+ """If alive then mark as dead and return (obj, func, args, kwargs);
595
+ otherwise return None"""
596
+ info = self._registry.get(self)
597
+ obj = info and info.weakref()
598
+ if obj is not None and self._registry.pop(self, None):
599
+ return (obj, info.func, info.args, info.kwargs or {})
600
+
601
+ def peek(self):
602
+ """If alive then return (obj, func, args, kwargs);
603
+ otherwise return None"""
604
+ info = self._registry.get(self)
605
+ obj = info and info.weakref()
606
+ if obj is not None:
607
+ return (obj, info.func, info.args, info.kwargs or {})
608
+
609
+ @property
610
+ def alive(self):
611
+ """Whether finalizer is alive"""
612
+ return self in self._registry
613
+
614
+ @property
615
+ def atexit(self):
616
+ """Whether finalizer should be called at exit"""
617
+ info = self._registry.get(self)
618
+ return bool(info) and info.atexit
619
+
620
+ @atexit.setter
621
+ def atexit(self, value):
622
+ info = self._registry.get(self)
623
+ if info:
624
+ info.atexit = bool(value)
625
+
626
+ def __repr__(self):
627
+ info = self._registry.get(self)
628
+ obj = info and info.weakref()
629
+ if obj is None:
630
+ return '<%s object at %#x; dead>' % (type(self).__name__, id(self))
631
+ else:
632
+ return '<%s object at %#x; for %r at %#x>' % \
633
+ (type(self).__name__, id(self), type(obj).__name__, id(obj))
634
+
635
+ @classmethod
636
+ def _select_for_exit(cls):
637
+ # Return live finalizers marked for exit, oldest first
638
+ L = [(f,i) for (f,i) in cls._registry.items() if i.atexit]
639
+ L.sort(key=lambda item:item[1].index)
640
+ return [f for (f,i) in L]
641
+
642
+ @classmethod
643
+ def _exitfunc(cls):
644
+ # At shutdown invoke finalizers for which atexit is true.
645
+ # This is called once all other non-daemonic threads have been
646
+ # joined.
647
+ reenable_gc = False
648
+ try:
649
+ if cls._registry:
650
+ import gc
651
+ if gc.isenabled():
652
+ reenable_gc = True
653
+ gc.disable()
654
+ pending = None
655
+ while True:
656
+ if pending is None or finalize._dirty:
657
+ pending = cls._select_for_exit()
658
+ finalize._dirty = False
659
+ if not pending:
660
+ break
661
+ f = pending.pop()
662
+ try:
663
+ # gc is disabled, so (assuming no daemonic
664
+ # threads) the following is the only line in
665
+ # this function which might trigger creation
666
+ # of a new finalizer
667
+ f()
668
+ except Exception:
669
+ sys.excepthook(*sys.exc_info())
670
+ assert f not in cls._registry
671
+ finally:
672
+ # prevent any more finalizers from executing during shutdown
673
+ finalize._shutdown = True
674
+ if reenable_gc:
675
+ gc.enable()
lib/sqlite3.44.2/pkgIndex.tcl ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- tcl -*-
2
+ # Tcl package index file, version 1.1
3
+ #
4
+ # Note sqlite*3* init specifically
5
+ #
6
+ if {[package vsatisfies [package provide Tcl] 9.0-]} {
7
+ package ifneeded sqlite3 3.44.2 \
8
+ [list load [file join $dir libtcl9sqlite3.44.2.so] Sqlite3]
9
+ } else {
10
+ package ifneeded sqlite3 3.44.2 \
11
+ [list load [file join $dir libsqlite3.44.2.so] Sqlite3]
12
+ }
lib/tcl8.6/auto.tcl ADDED
@@ -0,0 +1,648 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # auto.tcl --
2
+ #
3
+ # utility procs formerly in init.tcl dealing with auto execution of commands
4
+ # and can be auto loaded themselves.
5
+ #
6
+ # Copyright (c) 1991-1993 The Regents of the University of California.
7
+ # Copyright (c) 1994-1998 Sun Microsystems, Inc.
8
+ #
9
+ # See the file "license.terms" for information on usage and redistribution of
10
+ # this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
+ #
12
+
13
+ # auto_reset --
14
+ #
15
+ # Destroy all cached information for auto-loading and auto-execution, so that
16
+ # the information gets recomputed the next time it's needed. Also delete any
17
+ # commands that are listed in the auto-load index.
18
+ #
19
+ # Arguments:
20
+ # None.
21
+
22
+ proc auto_reset {} {
23
+ global auto_execs auto_index auto_path
24
+ if {[array exists auto_index]} {
25
+ foreach cmdName [array names auto_index] {
26
+ set fqcn [namespace which $cmdName]
27
+ if {$fqcn eq ""} {
28
+ continue
29
+ }
30
+ rename $fqcn {}
31
+ }
32
+ }
33
+ unset -nocomplain auto_execs auto_index ::tcl::auto_oldpath
34
+ if {[catch {llength $auto_path}]} {
35
+ set auto_path [list [info library]]
36
+ } elseif {[info library] ni $auto_path} {
37
+ lappend auto_path [info library]
38
+ }
39
+ }
40
+
41
+ # tcl_findLibrary --
42
+ #
43
+ # This is a utility for extensions that searches for a library directory
44
+ # using a canonical searching algorithm. A side effect is to source the
45
+ # initialization script and set a global library variable.
46
+ #
47
+ # Arguments:
48
+ # basename Prefix of the directory name, (e.g., "tk")
49
+ # version Version number of the package, (e.g., "8.0")
50
+ # patch Patchlevel of the package, (e.g., "8.0.3")
51
+ # initScript Initialization script to source (e.g., tk.tcl)
52
+ # enVarName environment variable to honor (e.g., TK_LIBRARY)
53
+ # varName Global variable to set when done (e.g., tk_library)
54
+
55
+ proc tcl_findLibrary {basename version patch initScript enVarName varName} {
56
+ upvar #0 $varName the_library
57
+ global auto_path env tcl_platform
58
+
59
+ set dirs {}
60
+ set errors {}
61
+
62
+ # The C application may have hardwired a path, which we honor
63
+
64
+ if {[info exists the_library] && $the_library ne ""} {
65
+ lappend dirs $the_library
66
+ } else {
67
+ # Do the canonical search
68
+
69
+ # 1. From an environment variable, if it exists. Placing this first
70
+ # gives the end-user ultimate control to work-around any bugs, or
71
+ # to customize.
72
+
73
+ if {[info exists env($enVarName)]} {
74
+ lappend dirs $env($enVarName)
75
+ }
76
+
77
+ # 2. In the package script directory registered within the
78
+ # configuration of the package itself.
79
+
80
+ catch {
81
+ lappend dirs [::${basename}::pkgconfig get scriptdir,runtime]
82
+ }
83
+
84
+ # 3. Relative to auto_path directories. This checks relative to the
85
+ # Tcl library as well as allowing loading of libraries added to the
86
+ # auto_path that is not relative to the core library or binary paths.
87
+ foreach d $auto_path {
88
+ lappend dirs [file join $d $basename$version]
89
+ if {$tcl_platform(platform) eq "unix"
90
+ && $tcl_platform(os) eq "Darwin"} {
91
+ # 4. On MacOSX, check the Resources/Scripts subdir too
92
+ lappend dirs [file join $d $basename$version Resources Scripts]
93
+ }
94
+ }
95
+
96
+ # 3. Various locations relative to the executable
97
+ # ../lib/foo1.0 (From bin directory in install hierarchy)
98
+ # ../../lib/foo1.0 (From bin/arch directory in install hierarchy)
99
+ # ../library (From unix directory in build hierarchy)
100
+ #
101
+ # Remaining locations are out of date (when relevant, they ought to be
102
+ # covered by the $::auto_path seach above) and disabled.
103
+ #
104
+ # ../../library (From unix/arch directory in build hierarchy)
105
+ # ../../foo1.0.1/library
106
+ # (From unix directory in parallel build hierarchy)
107
+ # ../../../foo1.0.1/library
108
+ # (From unix/arch directory in parallel build hierarchy)
109
+
110
+ set parentDir [file dirname [file dirname [info nameofexecutable]]]
111
+ set grandParentDir [file dirname $parentDir]
112
+ lappend dirs [file join $parentDir lib $basename$version]
113
+ lappend dirs [file join $grandParentDir lib $basename$version]
114
+ lappend dirs [file join $parentDir library]
115
+ if {0} {
116
+ lappend dirs [file join $grandParentDir library]
117
+ lappend dirs [file join $grandParentDir $basename$patch library]
118
+ lappend dirs [file join [file dirname $grandParentDir] \
119
+ $basename$patch library]
120
+ }
121
+ }
122
+ # make $dirs unique, preserving order
123
+ array set seen {}
124
+ foreach i $dirs {
125
+ # Make sure $i is unique under normalization. Avoid repeated [source].
126
+ if {[interp issafe]} {
127
+ # Safe interps have no [file normalize].
128
+ set norm $i
129
+ } else {
130
+ set norm [file normalize $i]
131
+ }
132
+ if {[info exists seen($norm)]} {
133
+ continue
134
+ }
135
+ set seen($norm) {}
136
+
137
+ set the_library $i
138
+ set file [file join $i $initScript]
139
+
140
+ # source everything when in a safe interpreter because we have a
141
+ # source command, but no file exists command
142
+
143
+ if {[interp issafe] || [file exists $file]} {
144
+ if {![catch {uplevel #0 [list source $file]} msg opts]} {
145
+ return
146
+ }
147
+ append errors "$file: $msg\n"
148
+ append errors [dict get $opts -errorinfo]\n
149
+ }
150
+ }
151
+ unset -nocomplain the_library
152
+ set msg "Can't find a usable $initScript in the following directories: \n"
153
+ append msg " $dirs\n\n"
154
+ append msg "$errors\n\n"
155
+ append msg "This probably means that $basename wasn't installed properly.\n"
156
+ error $msg
157
+ }
158
+
159
+
160
+ # ----------------------------------------------------------------------
161
+ # auto_mkindex
162
+ # ----------------------------------------------------------------------
163
+ # The following procedures are used to generate the tclIndex file from Tcl
164
+ # source files. They use a special safe interpreter to parse Tcl source
165
+ # files, writing out index entries as "proc" commands are encountered. This
166
+ # implementation won't work in a safe interpreter, since a safe interpreter
167
+ # can't create the special parser and mess with its commands.
168
+
169
+ if {[interp issafe]} {
170
+ return ;# Stop sourcing the file here
171
+ }
172
+
173
+ # auto_mkindex --
174
+ # Regenerate a tclIndex file from Tcl source files. Takes as argument the
175
+ # name of the directory in which the tclIndex file is to be placed, followed
176
+ # by any number of glob patterns to use in that directory to locate all of the
177
+ # relevant files.
178
+ #
179
+ # Arguments:
180
+ # dir - Name of the directory in which to create an index.
181
+
182
+ # args - Any number of additional arguments giving the names of files
183
+ # within dir. If no additional are given auto_mkindex will look
184
+ # for *.tcl.
185
+
186
+ proc auto_mkindex {dir args} {
187
+ if {[interp issafe]} {
188
+ error "can't generate index within safe interpreter"
189
+ }
190
+
191
+ set oldDir [pwd]
192
+ cd $dir
193
+
194
+ append index "# Tcl autoload index file, version 2.0\n"
195
+ append index "# This file is generated by the \"auto_mkindex\" command\n"
196
+ append index "# and sourced to set up indexing information for one or\n"
197
+ append index "# more commands. Typically each line is a command that\n"
198
+ append index "# sets an element in the auto_index array, where the\n"
199
+ append index "# element name is the name of a command and the value is\n"
200
+ append index "# a script that loads the command.\n\n"
201
+ if {![llength $args]} {
202
+ set args *.tcl
203
+ }
204
+
205
+ auto_mkindex_parser::init
206
+ foreach file [lsort [glob -- {*}$args]] {
207
+ try {
208
+ append index [auto_mkindex_parser::mkindex $file]
209
+ } on error {msg opts} {
210
+ cd $oldDir
211
+ return -options $opts $msg
212
+ }
213
+ }
214
+ auto_mkindex_parser::cleanup
215
+
216
+ set fid [open "tclIndex" w]
217
+ puts -nonewline $fid $index
218
+ close $fid
219
+ cd $oldDir
220
+ }
221
+
222
+ # Original version of auto_mkindex that just searches the source code for
223
+ # "proc" at the beginning of the line.
224
+
225
+ proc auto_mkindex_old {dir args} {
226
+ set oldDir [pwd]
227
+ cd $dir
228
+ set dir [pwd]
229
+ append index "# Tcl autoload index file, version 2.0\n"
230
+ append index "# This file is generated by the \"auto_mkindex\" command\n"
231
+ append index "# and sourced to set up indexing information for one or\n"
232
+ append index "# more commands. Typically each line is a command that\n"
233
+ append index "# sets an element in the auto_index array, where the\n"
234
+ append index "# element name is the name of a command and the value is\n"
235
+ append index "# a script that loads the command.\n\n"
236
+ if {![llength $args]} {
237
+ set args *.tcl
238
+ }
239
+ foreach file [lsort [glob -- {*}$args]] {
240
+ set f ""
241
+ set error [catch {
242
+ set f [open $file]
243
+ fconfigure $f -eofchar "\x1A {}"
244
+ while {[gets $f line] >= 0} {
245
+ if {[regexp {^proc[ ]+([^ ]*)} $line match procName]} {
246
+ set procName [lindex [auto_qualify $procName "::"] 0]
247
+ append index "set [list auto_index($procName)]"
248
+ append index " \[list source \[file join \$dir [list $file]\]\]\n"
249
+ }
250
+ }
251
+ close $f
252
+ } msg opts]
253
+ if {$error} {
254
+ catch {close $f}
255
+ cd $oldDir
256
+ return -options $opts $msg
257
+ }
258
+ }
259
+ set f ""
260
+ set error [catch {
261
+ set f [open tclIndex w]
262
+ puts -nonewline $f $index
263
+ close $f
264
+ cd $oldDir
265
+ } msg opts]
266
+ if {$error} {
267
+ catch {close $f}
268
+ cd $oldDir
269
+ error $msg $info $code
270
+ return -options $opts $msg
271
+ }
272
+ }
273
+
274
+ # Create a safe interpreter that can be used to parse Tcl source files
275
+ # generate a tclIndex file for autoloading. This interp contains commands for
276
+ # things that need index entries. Each time a command is executed, it writes
277
+ # an entry out to the index file.
278
+
279
+ namespace eval auto_mkindex_parser {
280
+ variable parser "" ;# parser used to build index
281
+ variable index "" ;# maintains index as it is built
282
+ variable scriptFile "" ;# name of file being processed
283
+ variable contextStack "" ;# stack of namespace scopes
284
+ variable imports "" ;# keeps track of all imported cmds
285
+ variable initCommands ;# list of commands that create aliases
286
+ if {![info exists initCommands]} {
287
+ set initCommands [list]
288
+ }
289
+
290
+ proc init {} {
291
+ variable parser
292
+ variable initCommands
293
+
294
+ if {![interp issafe]} {
295
+ set parser [interp create -safe]
296
+ $parser hide info
297
+ $parser hide rename
298
+ $parser hide proc
299
+ $parser hide namespace
300
+ $parser hide eval
301
+ $parser hide puts
302
+ foreach ns [$parser invokehidden namespace children ::] {
303
+ # MUST NOT DELETE "::tcl" OR BAD THINGS HAPPEN!
304
+ if {$ns eq "::tcl"} continue
305
+ $parser invokehidden namespace delete $ns
306
+ }
307
+ foreach cmd [$parser invokehidden info commands ::*] {
308
+ $parser invokehidden rename $cmd {}
309
+ }
310
+ $parser invokehidden proc unknown {args} {}
311
+
312
+ # We'll need access to the "namespace" command within the
313
+ # interp. Put it back, but move it out of the way.
314
+
315
+ $parser expose namespace
316
+ $parser invokehidden rename namespace _%@namespace
317
+ $parser expose eval
318
+ $parser invokehidden rename eval _%@eval
319
+
320
+ # Install all the registered pseudo-command implementations
321
+
322
+ foreach cmd $initCommands {
323
+ eval $cmd
324
+ }
325
+ }
326
+ }
327
+ proc cleanup {} {
328
+ variable parser
329
+ interp delete $parser
330
+ unset parser
331
+ }
332
+ }
333
+
334
+ # auto_mkindex_parser::mkindex --
335
+ #
336
+ # Used by the "auto_mkindex" command to create a "tclIndex" file for the given
337
+ # Tcl source file. Executes the commands in the file, and handles things like
338
+ # the "proc" command by adding an entry for the index file. Returns a string
339
+ # that represents the index file.
340
+ #
341
+ # Arguments:
342
+ # file Name of Tcl source file to be indexed.
343
+
344
+ proc auto_mkindex_parser::mkindex {file} {
345
+ variable parser
346
+ variable index
347
+ variable scriptFile
348
+ variable contextStack
349
+ variable imports
350
+
351
+ set scriptFile $file
352
+
353
+ set fid [open $file]
354
+ fconfigure $fid -eofchar "\x1A {}"
355
+ set contents [read $fid]
356
+ close $fid
357
+
358
+ # There is one problem with sourcing files into the safe interpreter:
359
+ # references like "$x" will fail since code is not really being executed
360
+ # and variables do not really exist. To avoid this, we replace all $ with
361
+ # \0 (literally, the null char) later, when getting proc names we will
362
+ # have to reverse this replacement, in case there were any $ in the proc
363
+ # name. This will cause a problem if somebody actually tries to have a \0
364
+ # in their proc name. Too bad for them.
365
+ set contents [string map [list \$ \0] $contents]
366
+
367
+ set index ""
368
+ set contextStack ""
369
+ set imports ""
370
+
371
+ $parser eval $contents
372
+
373
+ foreach name $imports {
374
+ catch {$parser eval [list _%@namespace forget $name]}
375
+ }
376
+ return $index
377
+ }
378
+
379
+ # auto_mkindex_parser::hook command
380
+ #
381
+ # Registers a Tcl command to evaluate when initializing the child interpreter
382
+ # used by the mkindex parser. The command is evaluated in the parent
383
+ # interpreter, and can use the variable auto_mkindex_parser::parser to get to
384
+ # the child
385
+
386
+ proc auto_mkindex_parser::hook {cmd} {
387
+ variable initCommands
388
+
389
+ lappend initCommands $cmd
390
+ }
391
+
392
+ # auto_mkindex_parser::slavehook command
393
+ #
394
+ # Registers a Tcl command to evaluate when initializing the child interpreter
395
+ # used by the mkindex parser. The command is evaluated in the child
396
+ # interpreter.
397
+
398
+ proc auto_mkindex_parser::slavehook {cmd} {
399
+ variable initCommands
400
+
401
+ # The $parser variable is defined to be the name of the child interpreter
402
+ # when this command is used later.
403
+
404
+ lappend initCommands "\$parser eval [list $cmd]"
405
+ }
406
+
407
+ # auto_mkindex_parser::command --
408
+ #
409
+ # Registers a new command with the "auto_mkindex_parser" interpreter that
410
+ # parses Tcl files. These commands are fake versions of things like the
411
+ # "proc" command. When you execute them, they simply write out an entry to a
412
+ # "tclIndex" file for auto-loading.
413
+ #
414
+ # This procedure allows extensions to register their own commands with the
415
+ # auto_mkindex facility. For example, a package like [incr Tcl] might
416
+ # register a "class" command so that class definitions could be added to a
417
+ # "tclIndex" file for auto-loading.
418
+ #
419
+ # Arguments:
420
+ # name Name of command recognized in Tcl files.
421
+ # arglist Argument list for command.
422
+ # body Implementation of command to handle indexing.
423
+
424
+ proc auto_mkindex_parser::command {name arglist body} {
425
+ hook [list auto_mkindex_parser::commandInit $name $arglist $body]
426
+ }
427
+
428
+ # auto_mkindex_parser::commandInit --
429
+ #
430
+ # This does the actual work set up by auto_mkindex_parser::command. This is
431
+ # called when the interpreter used by the parser is created.
432
+ #
433
+ # Arguments:
434
+ # name Name of command recognized in Tcl files.
435
+ # arglist Argument list for command.
436
+ # body Implementation of command to handle indexing.
437
+
438
+ proc auto_mkindex_parser::commandInit {name arglist body} {
439
+ variable parser
440
+
441
+ set ns [namespace qualifiers $name]
442
+ set tail [namespace tail $name]
443
+ if {$ns eq ""} {
444
+ set fakeName [namespace current]::_%@fake_$tail
445
+ } else {
446
+ set fakeName [namespace current]::[string map {:: _} _%@fake_$name]
447
+ }
448
+ proc $fakeName $arglist $body
449
+
450
+ # YUK! Tcl won't let us alias fully qualified command names, so we can't
451
+ # handle names like "::itcl::class". Instead, we have to build procs with
452
+ # the fully qualified names, and have the procs point to the aliases.
453
+
454
+ if {[string match *::* $name]} {
455
+ set exportCmd [list _%@namespace export [namespace tail $name]]
456
+ $parser eval [list _%@namespace eval $ns $exportCmd]
457
+
458
+ # The following proc definition does not work if you want to tolerate
459
+ # space or something else diabolical in the procedure name, (i.e.,
460
+ # space in $alias). The following does not work:
461
+ # "_%@eval {$alias} \$args"
462
+ # because $alias gets concat'ed to $args. The following does not work
463
+ # because $cmd is somehow undefined
464
+ # "set cmd {$alias} \; _%@eval {\$cmd} \$args"
465
+ # A gold star to someone that can make test autoMkindex-3.3 work
466
+ # properly
467
+
468
+ set alias [namespace tail $fakeName]
469
+ $parser invokehidden proc $name {args} "_%@eval {$alias} \$args"
470
+ $parser alias $alias $fakeName
471
+ } else {
472
+ $parser alias $name $fakeName
473
+ }
474
+ return
475
+ }
476
+
477
+ # auto_mkindex_parser::fullname --
478
+ #
479
+ # Used by commands like "proc" within the auto_mkindex parser. Returns the
480
+ # qualified namespace name for the "name" argument. If the "name" does not
481
+ # start with "::", elements are added from the current namespace stack to
482
+ # produce a qualified name. Then, the name is examined to see whether or not
483
+ # it should really be qualified. If the name has more than the leading "::",
484
+ # it is returned as a fully qualified name. Otherwise, it is returned as a
485
+ # simple name. That way, the Tcl autoloader will recognize it properly.
486
+ #
487
+ # Arguments:
488
+ # name - Name that is being added to index.
489
+
490
+ proc auto_mkindex_parser::fullname {name} {
491
+ variable contextStack
492
+
493
+ if {![string match ::* $name]} {
494
+ foreach ns $contextStack {
495
+ set name "${ns}::$name"
496
+ if {[string match ::* $name]} {
497
+ break
498
+ }
499
+ }
500
+ }
501
+
502
+ if {[namespace qualifiers $name] eq ""} {
503
+ set name [namespace tail $name]
504
+ } elseif {![string match ::* $name]} {
505
+ set name "::$name"
506
+ }
507
+
508
+ # Earlier, mkindex replaced all $'s with \0. Now, we have to reverse that
509
+ # replacement.
510
+ return [string map [list \0 \$] $name]
511
+ }
512
+
513
+ # auto_mkindex_parser::indexEntry --
514
+ #
515
+ # Used by commands like "proc" within the auto_mkindex parser to add a
516
+ # correctly-quoted entry to the index. This is shared code so it is done
517
+ # *right*, in one place.
518
+ #
519
+ # Arguments:
520
+ # name - Name that is being added to index.
521
+
522
+ proc auto_mkindex_parser::indexEntry {name} {
523
+ variable index
524
+ variable scriptFile
525
+
526
+ # We convert all metacharacters to their backslashed form, and pre-split
527
+ # the file name that we know about (which will be a proper list, and so
528
+ # correctly quoted).
529
+
530
+ set name [string range [list \}[fullname $name]] 2 end]
531
+ set filenameParts [file split $scriptFile]
532
+
533
+ append index [format \
534
+ {set auto_index(%s) [list source [file join $dir %s]]%s} \
535
+ $name $filenameParts \n]
536
+ return
537
+ }
538
+
539
+ if {[llength $::auto_mkindex_parser::initCommands]} {
540
+ return
541
+ }
542
+
543
+ # Register all of the procedures for the auto_mkindex parser that will build
544
+ # the "tclIndex" file.
545
+
546
+ # AUTO MKINDEX: proc name arglist body
547
+ # Adds an entry to the auto index list for the given procedure name.
548
+
549
+ auto_mkindex_parser::command proc {name args} {
550
+ indexEntry $name
551
+ }
552
+
553
+ # Conditionally add support for Tcl byte code files. There are some tricky
554
+ # details here. First, we need to get the tbcload library initialized in the
555
+ # current interpreter. We cannot load tbcload into the child until we have
556
+ # done so because it needs access to the tcl_patchLevel variable. Second,
557
+ # because the package index file may defer loading the library until we invoke
558
+ # a command, we need to explicitly invoke auto_load to force it to be loaded.
559
+ # This should be a noop if the package has already been loaded
560
+
561
+ auto_mkindex_parser::hook {
562
+ try {
563
+ package require tbcload
564
+ } on error {} {
565
+ # OK, don't have it so do nothing
566
+ } on ok {} {
567
+ if {[namespace which -command tbcload::bcproc] eq ""} {
568
+ auto_load tbcload::bcproc
569
+ }
570
+ load {} tbcload $auto_mkindex_parser::parser
571
+
572
+ # AUTO MKINDEX: tbcload::bcproc name arglist body
573
+ # Adds an entry to the auto index list for the given precompiled
574
+ # procedure name.
575
+
576
+ auto_mkindex_parser::commandInit tbcload::bcproc {name args} {
577
+ indexEntry $name
578
+ }
579
+ }
580
+ }
581
+
582
+ # AUTO MKINDEX: namespace eval name command ?arg arg...?
583
+ # Adds the namespace name onto the context stack and evaluates the associated
584
+ # body of commands.
585
+ #
586
+ # AUTO MKINDEX: namespace import ?-force? pattern ?pattern...?
587
+ # Performs the "import" action in the parser interpreter. This is important
588
+ # for any commands contained in a namespace that affect the index. For
589
+ # example, a script may say "itcl::class ...", or it may import "itcl::*" and
590
+ # then say "class ...". This procedure does the import operation, but keeps
591
+ # track of imported patterns so we can remove the imports later.
592
+
593
+ auto_mkindex_parser::command namespace {op args} {
594
+ switch -- $op {
595
+ eval {
596
+ variable parser
597
+ variable contextStack
598
+
599
+ set name [lindex $args 0]
600
+ set args [lrange $args 1 end]
601
+
602
+ set contextStack [linsert $contextStack 0 $name]
603
+ $parser eval [list _%@namespace eval $name] $args
604
+ set contextStack [lrange $contextStack 1 end]
605
+ }
606
+ import {
607
+ variable parser
608
+ variable imports
609
+ foreach pattern $args {
610
+ if {$pattern ne "-force"} {
611
+ lappend imports $pattern
612
+ }
613
+ }
614
+ catch {$parser eval "_%@namespace import $args"}
615
+ }
616
+ ensemble {
617
+ variable parser
618
+ variable contextStack
619
+ if {[lindex $args 0] eq "create"} {
620
+ set name ::[join [lreverse $contextStack] ::]
621
+ catch {
622
+ set name [dict get [lrange $args 1 end] -command]
623
+ if {![string match ::* $name]} {
624
+ set name ::[join [lreverse $contextStack] ::]$name
625
+ }
626
+ regsub -all ::+ $name :: name
627
+ }
628
+ # create artificial proc to force an entry in the tclIndex
629
+ $parser eval [list ::proc $name {} {}]
630
+ }
631
+ }
632
+ }
633
+ }
634
+
635
+ # AUTO MKINDEX: oo::class create name ?definition?
636
+ # Adds an entry to the auto index list for the given class name.
637
+ auto_mkindex_parser::command oo::class {op name {body ""}} {
638
+ if {$op eq "create"} {
639
+ indexEntry $name
640
+ }
641
+ }
642
+ auto_mkindex_parser::command class {op name {body ""}} {
643
+ if {$op eq "create"} {
644
+ indexEntry $name
645
+ }
646
+ }
647
+
648
+ return
lib/tcl8.6/clock.tcl ADDED
The diff for this file is too large to render. See raw diff
 
lib/tcl8.6/history.tcl ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # history.tcl --
2
+ #
3
+ # Implementation of the history command.
4
+ #
5
+ # Copyright (c) 1997 Sun Microsystems, Inc.
6
+ #
7
+ # See the file "license.terms" for information on usage and redistribution of
8
+ # this file, and for a DISCLAIMER OF ALL WARRANTIES.
9
+ #
10
+
11
+ # The tcl::history array holds the history list and some additional
12
+ # bookkeeping variables.
13
+ #
14
+ # nextid the index used for the next history list item.
15
+ # keep the max size of the history list
16
+ # oldest the index of the oldest item in the history.
17
+
18
+ namespace eval ::tcl {
19
+ variable history
20
+ if {![info exists history]} {
21
+ array set history {
22
+ nextid 0
23
+ keep 20
24
+ oldest -20
25
+ }
26
+ }
27
+
28
+ namespace ensemble create -command ::tcl::history -map {
29
+ add ::tcl::HistAdd
30
+ change ::tcl::HistChange
31
+ clear ::tcl::HistClear
32
+ event ::tcl::HistEvent
33
+ info ::tcl::HistInfo
34
+ keep ::tcl::HistKeep
35
+ nextid ::tcl::HistNextID
36
+ redo ::tcl::HistRedo
37
+ }
38
+ }
39
+
40
+ # history --
41
+ #
42
+ # This is the main history command. See the man page for its interface.
43
+ # This does some argument checking and calls the helper ensemble in the
44
+ # tcl namespace.
45
+
46
+ proc ::history {args} {
47
+ # If no command given, we're doing 'history info'. Can't be done with an
48
+ # ensemble unknown handler, as those don't fire when no subcommand is
49
+ # given at all.
50
+
51
+ if {![llength $args]} {
52
+ set args info
53
+ }
54
+
55
+ # Tricky stuff needed to make stack and errors come out right!
56
+ tailcall apply {arglist {tailcall ::tcl::history {*}$arglist} ::tcl} $args
57
+ }
58
+
59
+ # (unnamed) --
60
+ #
61
+ # Callback when [::history] is destroyed. Destroys the implementation.
62
+ #
63
+ # Parameters:
64
+ # oldName what the command was called.
65
+ # newName what the command is now called (an empty string).
66
+ # op the operation (= delete).
67
+ #
68
+ # Results:
69
+ # none
70
+ #
71
+ # Side Effects:
72
+ # The implementation of the [::history] command ceases to exist.
73
+
74
+ trace add command ::history delete [list apply {{oldName newName op} {
75
+ variable history
76
+ unset -nocomplain history
77
+ foreach c [info procs ::tcl::Hist*] {
78
+ rename $c {}
79
+ }
80
+ rename ::tcl::history {}
81
+ } ::tcl}]
82
+
83
+ # tcl::HistAdd --
84
+ #
85
+ # Add an item to the history, and optionally eval it at the global scope
86
+ #
87
+ # Parameters:
88
+ # event the command to add
89
+ # exec (optional) a substring of "exec" causes the command to
90
+ # be evaled.
91
+ # Results:
92
+ # If executing, then the results of the command are returned
93
+ #
94
+ # Side Effects:
95
+ # Adds to the history list
96
+
97
+ proc ::tcl::HistAdd {event {exec {}}} {
98
+ variable history
99
+
100
+ if {
101
+ [prefix longest {exec {}} $exec] eq ""
102
+ && [llength [info level 0]] == 3
103
+ } then {
104
+ return -code error "bad argument \"$exec\": should be \"exec\""
105
+ }
106
+
107
+ # Do not add empty commands to the history
108
+ if {[string trim $event] eq ""} {
109
+ return ""
110
+ }
111
+
112
+ # Maintain the history
113
+ set history([incr history(nextid)]) $event
114
+ unset -nocomplain history([incr history(oldest)])
115
+
116
+ # Only execute if 'exec' (or non-empty prefix of it) given
117
+ if {$exec eq ""} {
118
+ return ""
119
+ }
120
+ tailcall eval $event
121
+ }
122
+
123
+ # tcl::HistKeep --
124
+ #
125
+ # Set or query the limit on the length of the history list
126
+ #
127
+ # Parameters:
128
+ # limit (optional) the length of the history list
129
+ #
130
+ # Results:
131
+ # If no limit is specified, the current limit is returned
132
+ #
133
+ # Side Effects:
134
+ # Updates history(keep) if a limit is specified
135
+
136
+ proc ::tcl::HistKeep {{count {}}} {
137
+ variable history
138
+ if {[llength [info level 0]] == 1} {
139
+ return $history(keep)
140
+ }
141
+ if {![string is integer -strict $count] || ($count < 0)} {
142
+ return -code error "illegal keep count \"$count\""
143
+ }
144
+ set oldold $history(oldest)
145
+ set history(oldest) [expr {$history(nextid) - $count}]
146
+ for {} {$oldold <= $history(oldest)} {incr oldold} {
147
+ unset -nocomplain history($oldold)
148
+ }
149
+ set history(keep) $count
150
+ }
151
+
152
+ # tcl::HistClear --
153
+ #
154
+ # Erase the history list
155
+ #
156
+ # Parameters:
157
+ # none
158
+ #
159
+ # Results:
160
+ # none
161
+ #
162
+ # Side Effects:
163
+ # Resets the history array, except for the keep limit
164
+
165
+ proc ::tcl::HistClear {} {
166
+ variable history
167
+ set keep $history(keep)
168
+ unset history
169
+ array set history [list \
170
+ nextid 0 \
171
+ keep $keep \
172
+ oldest -$keep \
173
+ ]
174
+ }
175
+
176
+ # tcl::HistInfo --
177
+ #
178
+ # Return a pretty-printed version of the history list
179
+ #
180
+ # Parameters:
181
+ # num (optional) the length of the history list to return
182
+ #
183
+ # Results:
184
+ # A formatted history list
185
+
186
+ proc ::tcl::HistInfo {{count {}}} {
187
+ variable history
188
+ if {[llength [info level 0]] == 1} {
189
+ set count [expr {$history(keep) + 1}]
190
+ } elseif {![string is integer -strict $count]} {
191
+ return -code error "bad integer \"$count\""
192
+ }
193
+ set result {}
194
+ set newline ""
195
+ for {set i [expr {$history(nextid) - $count + 1}]} \
196
+ {$i <= $history(nextid)} {incr i} {
197
+ if {![info exists history($i)]} {
198
+ continue
199
+ }
200
+ set cmd [string map [list \n \n\t] [string trimright $history($i) \ \n]]
201
+ append result $newline[format "%6d %s" $i $cmd]
202
+ set newline \n
203
+ }
204
+ return $result
205
+ }
206
+
207
+ # tcl::HistRedo --
208
+ #
209
+ # Fetch the previous or specified event, execute it, and then replace
210
+ # the current history item with that event.
211
+ #
212
+ # Parameters:
213
+ # event (optional) index of history item to redo. Defaults to -1,
214
+ # which means the previous event.
215
+ #
216
+ # Results:
217
+ # Those of the command being redone.
218
+ #
219
+ # Side Effects:
220
+ # Replaces the current history list item with the one being redone.
221
+
222
+ proc ::tcl::HistRedo {{event -1}} {
223
+ variable history
224
+
225
+ set i [HistIndex $event]
226
+ if {$i == $history(nextid)} {
227
+ return -code error "cannot redo the current event"
228
+ }
229
+ set cmd $history($i)
230
+ HistChange $cmd 0
231
+ tailcall eval $cmd
232
+ }
233
+
234
+ # tcl::HistIndex --
235
+ #
236
+ # Map from an event specifier to an index in the history list.
237
+ #
238
+ # Parameters:
239
+ # event index of history item to redo.
240
+ # If this is a positive number, it is used directly.
241
+ # If it is a negative number, then it counts back to a previous
242
+ # event, where -1 is the most recent event.
243
+ # A string can be matched, either by being the prefix of a
244
+ # command or by matching a command with string match.
245
+ #
246
+ # Results:
247
+ # The index into history, or an error if the index didn't match.
248
+
249
+ proc ::tcl::HistIndex {event} {
250
+ variable history
251
+ if {![string is integer -strict $event]} {
252
+ for {set i [expr {$history(nextid)-1}]} {[info exists history($i)]} \
253
+ {incr i -1} {
254
+ if {[string match $event* $history($i)]} {
255
+ return $i
256
+ }
257
+ if {[string match $event $history($i)]} {
258
+ return $i
259
+ }
260
+ }
261
+ return -code error "no event matches \"$event\""
262
+ } elseif {$event <= 0} {
263
+ set i [expr {$history(nextid) + $event}]
264
+ } else {
265
+ set i $event
266
+ }
267
+ if {$i <= $history(oldest)} {
268
+ return -code error "event \"$event\" is too far in the past"
269
+ }
270
+ if {$i > $history(nextid)} {
271
+ return -code error "event \"$event\" hasn't occurred yet"
272
+ }
273
+ return $i
274
+ }
275
+
276
+ # tcl::HistEvent --
277
+ #
278
+ # Map from an event specifier to the value in the history list.
279
+ #
280
+ # Parameters:
281
+ # event index of history item to redo. See index for a description of
282
+ # possible event patterns.
283
+ #
284
+ # Results:
285
+ # The value from the history list.
286
+
287
+ proc ::tcl::HistEvent {{event -1}} {
288
+ variable history
289
+ set i [HistIndex $event]
290
+ if {![info exists history($i)]} {
291
+ return ""
292
+ }
293
+ return [string trimright $history($i) \ \n]
294
+ }
295
+
296
+ # tcl::HistChange --
297
+ #
298
+ # Replace a value in the history list.
299
+ #
300
+ # Parameters:
301
+ # newValue The new value to put into the history list.
302
+ # event (optional) index of history item to redo. See index for a
303
+ # description of possible event patterns. This defaults to 0,
304
+ # which specifies the current event.
305
+ #
306
+ # Side Effects:
307
+ # Changes the history list.
308
+
309
+ proc ::tcl::HistChange {newValue {event 0}} {
310
+ variable history
311
+ set i [HistIndex $event]
312
+ set history($i) $newValue
313
+ }
314
+
315
+ # tcl::HistNextID --
316
+ #
317
+ # Returns the number of the next history event.
318
+ #
319
+ # Parameters:
320
+ # None.
321
+ #
322
+ # Side Effects:
323
+ # None.
324
+
325
+ proc ::tcl::HistNextID {} {
326
+ variable history
327
+ return [expr {$history(nextid) + 1}]
328
+ }
329
+
330
+ return
331
+
332
+ # Local Variables:
333
+ # mode: tcl
334
+ # fill-column: 78
335
+ # End:
lib/tcl8.6/init.tcl ADDED
@@ -0,0 +1,827 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # init.tcl --
2
+ #
3
+ # Default system startup file for Tcl-based applications. Defines
4
+ # "unknown" procedure and auto-load facilities.
5
+ #
6
+ # Copyright (c) 1991-1993 The Regents of the University of California.
7
+ # Copyright (c) 1994-1996 Sun Microsystems, Inc.
8
+ # Copyright (c) 1998-1999 Scriptics Corporation.
9
+ # Copyright (c) 2004 Kevin B. Kenny. All rights reserved.
10
+ #
11
+ # See the file "license.terms" for information on usage and redistribution
12
+ # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
+ #
14
+
15
+ # This test intentionally written in pre-7.5 Tcl
16
+ if {[info commands package] == ""} {
17
+ error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]"
18
+ }
19
+ package require -exact Tcl 8.6.14
20
+
21
+ # Compute the auto path to use in this interpreter.
22
+ # The values on the path come from several locations:
23
+ #
24
+ # The environment variable TCLLIBPATH
25
+ #
26
+ # tcl_library, which is the directory containing this init.tcl script.
27
+ # [tclInit] (Tcl_Init()) searches around for the directory containing this
28
+ # init.tcl and defines tcl_library to that location before sourcing it.
29
+ #
30
+ # The parent directory of tcl_library. Adding the parent
31
+ # means that packages in peer directories will be found automatically.
32
+ #
33
+ # Also add the directory ../lib relative to the directory where the
34
+ # executable is located. This is meant to find binary packages for the
35
+ # same architecture as the current executable.
36
+ #
37
+ # tcl_pkgPath, which is set by the platform-specific initialization routines
38
+ # On UNIX it is compiled in
39
+ # On Windows, it is not used
40
+ #
41
+ # (Ticket 41c9857bdd) In a safe interpreter, this file does not set
42
+ # ::auto_path (other than to {} if it is undefined). The caller, typically
43
+ # a Safe Base command, is responsible for setting ::auto_path.
44
+
45
+ if {![info exists auto_path]} {
46
+ if {[info exists env(TCLLIBPATH)] && (![interp issafe])} {
47
+ set auto_path $env(TCLLIBPATH)
48
+ } else {
49
+ set auto_path ""
50
+ }
51
+ }
52
+ namespace eval tcl {
53
+ if {![interp issafe]} {
54
+ variable Dir
55
+ foreach Dir [list $::tcl_library [file dirname $::tcl_library]] {
56
+ if {$Dir ni $::auto_path} {
57
+ lappend ::auto_path $Dir
58
+ }
59
+ }
60
+ set Dir [file join [file dirname [file dirname \
61
+ [info nameofexecutable]]] lib]
62
+ if {$Dir ni $::auto_path} {
63
+ lappend ::auto_path $Dir
64
+ }
65
+ if {[info exists ::tcl_pkgPath]} { catch {
66
+ foreach Dir $::tcl_pkgPath {
67
+ if {$Dir ni $::auto_path} {
68
+ lappend ::auto_path $Dir
69
+ }
70
+ }
71
+ }}
72
+
73
+ variable Path [encoding dirs]
74
+ set Dir [file join $::tcl_library encoding]
75
+ if {$Dir ni $Path} {
76
+ lappend Path $Dir
77
+ encoding dirs $Path
78
+ }
79
+ unset Dir Path
80
+ }
81
+
82
+ # TIP #255 min and max functions
83
+ namespace eval mathfunc {
84
+ proc min {args} {
85
+ if {![llength $args]} {
86
+ return -code error \
87
+ "not enough arguments to math function \"min\""
88
+ }
89
+ set val Inf
90
+ foreach arg $args {
91
+ # This will handle forcing the numeric value without
92
+ # ruining the internal type of a numeric object
93
+ if {[catch {expr {double($arg)}} err]} {
94
+ return -code error $err
95
+ }
96
+ if {$arg < $val} {set val $arg}
97
+ }
98
+ return $val
99
+ }
100
+ proc max {args} {
101
+ if {![llength $args]} {
102
+ return -code error \
103
+ "not enough arguments to math function \"max\""
104
+ }
105
+ set val -Inf
106
+ foreach arg $args {
107
+ # This will handle forcing the numeric value without
108
+ # ruining the internal type of a numeric object
109
+ if {[catch {expr {double($arg)}} err]} {
110
+ return -code error $err
111
+ }
112
+ if {$arg > $val} {set val $arg}
113
+ }
114
+ return $val
115
+ }
116
+ namespace export min max
117
+ }
118
+ }
119
+
120
+ # Windows specific end of initialization
121
+
122
+ if {(![interp issafe]) && ($tcl_platform(platform) eq "windows")} {
123
+ namespace eval tcl {
124
+ proc EnvTraceProc {lo n1 n2 op} {
125
+ global env
126
+ set x $env($n2)
127
+ set env($lo) $x
128
+ set env([string toupper $lo]) $x
129
+ }
130
+ proc InitWinEnv {} {
131
+ global env tcl_platform
132
+ foreach p [array names env] {
133
+ set u [string toupper $p]
134
+ if {$u ne $p} {
135
+ switch -- $u {
136
+ COMSPEC -
137
+ PATH {
138
+ set temp $env($p)
139
+ unset env($p)
140
+ set env($u) $temp
141
+ trace add variable env($p) write \
142
+ [namespace code [list EnvTraceProc $p]]
143
+ trace add variable env($u) write \
144
+ [namespace code [list EnvTraceProc $p]]
145
+ }
146
+ }
147
+ }
148
+ }
149
+ if {![info exists env(COMSPEC)]} {
150
+ set env(COMSPEC) cmd.exe
151
+ }
152
+ }
153
+ InitWinEnv
154
+ }
155
+ }
156
+
157
+ # Setup the unknown package handler
158
+
159
+
160
+ if {[interp issafe]} {
161
+ package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
162
+ } else {
163
+ # Set up search for Tcl Modules (TIP #189).
164
+ # and setup platform specific unknown package handlers
165
+ if {$tcl_platform(os) eq "Darwin"
166
+ && $tcl_platform(platform) eq "unix"} {
167
+ package unknown {::tcl::tm::UnknownHandler \
168
+ {::tcl::MacOSXPkgUnknown ::tclPkgUnknown}}
169
+ } else {
170
+ package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
171
+ }
172
+
173
+ # Set up the 'clock' ensemble
174
+
175
+ namespace eval ::tcl::clock [list variable TclLibDir $::tcl_library]
176
+
177
+ proc ::tcl::initClock {} {
178
+ # Auto-loading stubs for 'clock.tcl'
179
+
180
+ foreach cmd {add format scan} {
181
+ proc ::tcl::clock::$cmd args {
182
+ variable TclLibDir
183
+ source -encoding utf-8 [file join $TclLibDir clock.tcl]
184
+ return [uplevel 1 [info level 0]]
185
+ }
186
+ }
187
+
188
+ rename ::tcl::initClock {}
189
+ }
190
+ ::tcl::initClock
191
+ }
192
+
193
+ # Conditionalize for presence of exec.
194
+
195
+ if {[namespace which -command exec] eq ""} {
196
+
197
+ # Some machines do not have exec. Also, on all
198
+ # platforms, safe interpreters do not have exec.
199
+
200
+ set auto_noexec 1
201
+ }
202
+
203
+ # Define a log command (which can be overwritten to log errors
204
+ # differently, specially when stderr is not available)
205
+
206
+ if {[namespace which -command tclLog] eq ""} {
207
+ proc tclLog {string} {
208
+ catch {puts stderr $string}
209
+ }
210
+ }
211
+
212
+ # unknown --
213
+ # This procedure is called when a Tcl command is invoked that doesn't
214
+ # exist in the interpreter. It takes the following steps to make the
215
+ # command available:
216
+ #
217
+ # 1. See if the autoload facility can locate the command in a
218
+ # Tcl script file. If so, load it and execute it.
219
+ # 2. If the command was invoked interactively at top-level:
220
+ # (a) see if the command exists as an executable UNIX program.
221
+ # If so, "exec" the command.
222
+ # (b) see if the command requests csh-like history substitution
223
+ # in one of the common forms !!, !<number>, or ^old^new. If
224
+ # so, emulate csh's history substitution.
225
+ # (c) see if the command is a unique abbreviation for another
226
+ # command. If so, invoke the command.
227
+ #
228
+ # Arguments:
229
+ # args - A list whose elements are the words of the original
230
+ # command, including the command name.
231
+
232
+ proc unknown args {
233
+ variable ::tcl::UnknownPending
234
+ global auto_noexec auto_noload env tcl_interactive errorInfo errorCode
235
+
236
+ if {[info exists errorInfo]} {
237
+ set savedErrorInfo $errorInfo
238
+ }
239
+ if {[info exists errorCode]} {
240
+ set savedErrorCode $errorCode
241
+ }
242
+
243
+ set name [lindex $args 0]
244
+ if {![info exists auto_noload]} {
245
+ #
246
+ # Make sure we're not trying to load the same proc twice.
247
+ #
248
+ if {[info exists UnknownPending($name)]} {
249
+ return -code error "self-referential recursion\
250
+ in \"unknown\" for command \"$name\""
251
+ }
252
+ set UnknownPending($name) pending
253
+ set ret [catch {
254
+ auto_load $name [uplevel 1 {::namespace current}]
255
+ } msg opts]
256
+ unset UnknownPending($name)
257
+ if {$ret != 0} {
258
+ dict append opts -errorinfo "\n (autoloading \"$name\")"
259
+ return -options $opts $msg
260
+ }
261
+ if {![array size UnknownPending]} {
262
+ unset UnknownPending
263
+ }
264
+ if {$msg} {
265
+ if {[info exists savedErrorCode]} {
266
+ set ::errorCode $savedErrorCode
267
+ } else {
268
+ unset -nocomplain ::errorCode
269
+ }
270
+ if {[info exists savedErrorInfo]} {
271
+ set errorInfo $savedErrorInfo
272
+ } else {
273
+ unset -nocomplain errorInfo
274
+ }
275
+ set code [catch {uplevel 1 $args} msg opts]
276
+ if {$code == 1} {
277
+ #
278
+ # Compute stack trace contribution from the [uplevel].
279
+ # Note the dependence on how Tcl_AddErrorInfo, etc.
280
+ # construct the stack trace.
281
+ #
282
+ set errInfo [dict get $opts -errorinfo]
283
+ set errCode [dict get $opts -errorcode]
284
+ set cinfo $args
285
+ if {[string bytelength $cinfo] > 150} {
286
+ set cinfo [string range $cinfo 0 150]
287
+ while {[string bytelength $cinfo] > 150} {
288
+ set cinfo [string range $cinfo 0 end-1]
289
+ }
290
+ append cinfo ...
291
+ }
292
+ set tail "\n (\"uplevel\" body line 1)\n invoked\
293
+ from within\n\"uplevel 1 \$args\""
294
+ set expect "$msg\n while executing\n\"$cinfo\"$tail"
295
+ if {$errInfo eq $expect} {
296
+ #
297
+ # The stack has only the eval from the expanded command
298
+ # Do not generate any stack trace here.
299
+ #
300
+ dict unset opts -errorinfo
301
+ dict incr opts -level
302
+ return -options $opts $msg
303
+ }
304
+ #
305
+ # Stack trace is nested, trim off just the contribution
306
+ # from the extra "eval" of $args due to the "catch" above.
307
+ #
308
+ set last [string last $tail $errInfo]
309
+ if {$last + [string length $tail] != [string length $errInfo]} {
310
+ # Very likely cannot happen
311
+ return -options $opts $msg
312
+ }
313
+ set errInfo [string range $errInfo 0 $last-1]
314
+ set tail "\"$cinfo\""
315
+ set last [string last $tail $errInfo]
316
+ if {$last < 0 || $last + [string length $tail] != [string length $errInfo]} {
317
+ return -code error -errorcode $errCode \
318
+ -errorinfo $errInfo $msg
319
+ }
320
+ set errInfo [string range $errInfo 0 $last-1]
321
+ set tail "\n invoked from within\n"
322
+ set last [string last $tail $errInfo]
323
+ if {$last + [string length $tail] == [string length $errInfo]} {
324
+ return -code error -errorcode $errCode \
325
+ -errorinfo [string range $errInfo 0 $last-1] $msg
326
+ }
327
+ set tail "\n while executing\n"
328
+ set last [string last $tail $errInfo]
329
+ if {$last + [string length $tail] == [string length $errInfo]} {
330
+ return -code error -errorcode $errCode \
331
+ -errorinfo [string range $errInfo 0 $last-1] $msg
332
+ }
333
+ return -options $opts $msg
334
+ } else {
335
+ dict incr opts -level
336
+ return -options $opts $msg
337
+ }
338
+ }
339
+ }
340
+
341
+ if {([info level] == 1) && ([info script] eq "")
342
+ && [info exists tcl_interactive] && $tcl_interactive} {
343
+ if {![info exists auto_noexec]} {
344
+ set new [auto_execok $name]
345
+ if {$new ne ""} {
346
+ set redir ""
347
+ if {[namespace which -command console] eq ""} {
348
+ set redir ">&@stdout <@stdin"
349
+ }
350
+ uplevel 1 [list ::catch \
351
+ [concat exec $redir $new [lrange $args 1 end]] \
352
+ ::tcl::UnknownResult ::tcl::UnknownOptions]
353
+ dict incr ::tcl::UnknownOptions -level
354
+ return -options $::tcl::UnknownOptions $::tcl::UnknownResult
355
+ }
356
+ }
357
+ if {$name eq "!!"} {
358
+ set newcmd [history event]
359
+ } elseif {[regexp {^!(.+)$} $name -> event]} {
360
+ set newcmd [history event $event]
361
+ } elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $name -> old new]} {
362
+ set newcmd [history event -1]
363
+ catch {regsub -all -- $old $newcmd $new newcmd}
364
+ }
365
+ if {[info exists newcmd]} {
366
+ tclLog $newcmd
367
+ history change $newcmd 0
368
+ uplevel 1 [list ::catch $newcmd \
369
+ ::tcl::UnknownResult ::tcl::UnknownOptions]
370
+ dict incr ::tcl::UnknownOptions -level
371
+ return -options $::tcl::UnknownOptions $::tcl::UnknownResult
372
+ }
373
+
374
+ set ret [catch [list uplevel 1 [list info commands $name*]] candidates]
375
+ if {$name eq "::"} {
376
+ set name ""
377
+ }
378
+ if {$ret != 0} {
379
+ dict append opts -errorinfo \
380
+ "\n (expanding command prefix \"$name\" in unknown)"
381
+ return -options $opts $candidates
382
+ }
383
+ # Filter out bogus matches when $name contained
384
+ # a glob-special char [Bug 946952]
385
+ if {$name eq ""} {
386
+ # Handle empty $name separately due to strangeness
387
+ # in [string first] (See RFE 1243354)
388
+ set cmds $candidates
389
+ } else {
390
+ set cmds [list]
391
+ foreach x $candidates {
392
+ if {[string first $name $x] == 0} {
393
+ lappend cmds $x
394
+ }
395
+ }
396
+ }
397
+ if {[llength $cmds] == 1} {
398
+ uplevel 1 [list ::catch [lreplace $args 0 0 [lindex $cmds 0]] \
399
+ ::tcl::UnknownResult ::tcl::UnknownOptions]
400
+ dict incr ::tcl::UnknownOptions -level
401
+ return -options $::tcl::UnknownOptions $::tcl::UnknownResult
402
+ }
403
+ if {[llength $cmds]} {
404
+ return -code error "ambiguous command name \"$name\": [lsort $cmds]"
405
+ }
406
+ }
407
+ return -code error -errorcode [list TCL LOOKUP COMMAND $name] \
408
+ "invalid command name \"$name\""
409
+ }
410
+
411
+ # auto_load --
412
+ # Checks a collection of library directories to see if a procedure
413
+ # is defined in one of them. If so, it sources the appropriate
414
+ # library file to create the procedure. Returns 1 if it successfully
415
+ # loaded the procedure, 0 otherwise.
416
+ #
417
+ # Arguments:
418
+ # cmd - Name of the command to find and load.
419
+ # namespace (optional) The namespace where the command is being used - must be
420
+ # a canonical namespace as returned [namespace current]
421
+ # for instance. If not given, namespace current is used.
422
+
423
+ proc auto_load {cmd {namespace {}}} {
424
+ global auto_index auto_path
425
+
426
+ if {$namespace eq ""} {
427
+ set namespace [uplevel 1 [list ::namespace current]]
428
+ }
429
+ set nameList [auto_qualify $cmd $namespace]
430
+ # workaround non canonical auto_index entries that might be around
431
+ # from older auto_mkindex versions
432
+ lappend nameList $cmd
433
+ foreach name $nameList {
434
+ if {[info exists auto_index($name)]} {
435
+ namespace eval :: $auto_index($name)
436
+ # There's a couple of ways to look for a command of a given
437
+ # name. One is to use
438
+ # info commands $name
439
+ # Unfortunately, if the name has glob-magic chars in it like *
440
+ # or [], it may not match. For our purposes here, a better
441
+ # route is to use
442
+ # namespace which -command $name
443
+ if {[namespace which -command $name] ne ""} {
444
+ return 1
445
+ }
446
+ }
447
+ }
448
+ if {![info exists auto_path]} {
449
+ return 0
450
+ }
451
+
452
+ if {![auto_load_index]} {
453
+ return 0
454
+ }
455
+ foreach name $nameList {
456
+ if {[info exists auto_index($name)]} {
457
+ namespace eval :: $auto_index($name)
458
+ if {[namespace which -command $name] ne ""} {
459
+ return 1
460
+ }
461
+ }
462
+ }
463
+ return 0
464
+ }
465
+
466
+ # auto_load_index --
467
+ # Loads the contents of tclIndex files on the auto_path directory
468
+ # list. This is usually invoked within auto_load to load the index
469
+ # of available commands. Returns 1 if the index is loaded, and 0 if
470
+ # the index is already loaded and up to date.
471
+ #
472
+ # Arguments:
473
+ # None.
474
+
475
+ proc auto_load_index {} {
476
+ variable ::tcl::auto_oldpath
477
+ global auto_index auto_path
478
+
479
+ if {[info exists auto_oldpath] && ($auto_oldpath eq $auto_path)} {
480
+ return 0
481
+ }
482
+ set auto_oldpath $auto_path
483
+
484
+ # Check if we are a safe interpreter. In that case, we support only
485
+ # newer format tclIndex files.
486
+
487
+ set issafe [interp issafe]
488
+ for {set i [expr {[llength $auto_path] - 1}]} {$i >= 0} {incr i -1} {
489
+ set dir [lindex $auto_path $i]
490
+ set f ""
491
+ if {$issafe} {
492
+ catch {source [file join $dir tclIndex]}
493
+ } elseif {[catch {set f [open [file join $dir tclIndex]]}]} {
494
+ continue
495
+ } else {
496
+ set error [catch {
497
+ fconfigure $f -eofchar "\x1A {}"
498
+ set id [gets $f]
499
+ if {$id eq "# Tcl autoload index file, version 2.0"} {
500
+ eval [read $f]
501
+ } elseif {$id eq "# Tcl autoload index file: each line identifies a Tcl"} {
502
+ while {[gets $f line] >= 0} {
503
+ if {([string index $line 0] eq "#") \
504
+ || ([llength $line] != 2)} {
505
+ continue
506
+ }
507
+ set name [lindex $line 0]
508
+ set auto_index($name) \
509
+ "source [file join $dir [lindex $line 1]]"
510
+ }
511
+ } else {
512
+ error "[file join $dir tclIndex] isn't a proper Tcl index file"
513
+ }
514
+ } msg opts]
515
+ if {$f ne ""} {
516
+ close $f
517
+ }
518
+ if {$error} {
519
+ return -options $opts $msg
520
+ }
521
+ }
522
+ }
523
+ return 1
524
+ }
525
+
526
+ # auto_qualify --
527
+ #
528
+ # Compute a fully qualified names list for use in the auto_index array.
529
+ # For historical reasons, commands in the global namespace do not have leading
530
+ # :: in the index key. The list has two elements when the command name is
531
+ # relative (no leading ::) and the namespace is not the global one. Otherwise
532
+ # only one name is returned (and searched in the auto_index).
533
+ #
534
+ # Arguments -
535
+ # cmd The command name. Can be any name accepted for command
536
+ # invocations (Like "foo::::bar").
537
+ # namespace The namespace where the command is being used - must be
538
+ # a canonical namespace as returned by [namespace current]
539
+ # for instance.
540
+
541
+ proc auto_qualify {cmd namespace} {
542
+
543
+ # count separators and clean them up
544
+ # (making sure that foo:::::bar will be treated as foo::bar)
545
+ set n [regsub -all {::+} $cmd :: cmd]
546
+
547
+ # Ignore namespace if the name starts with ::
548
+ # Handle special case of only leading ::
549
+
550
+ # Before each return case we give an example of which category it is
551
+ # with the following form :
552
+ # (inputCmd, inputNameSpace) -> output
553
+
554
+ if {[string match ::* $cmd]} {
555
+ if {$n > 1} {
556
+ # (::foo::bar , *) -> ::foo::bar
557
+ return [list $cmd]
558
+ } else {
559
+ # (::global , *) -> global
560
+ return [list [string range $cmd 2 end]]
561
+ }
562
+ }
563
+
564
+ # Potentially returning 2 elements to try :
565
+ # (if the current namespace is not the global one)
566
+
567
+ if {$n == 0} {
568
+ if {$namespace eq "::"} {
569
+ # (nocolons , ::) -> nocolons
570
+ return [list $cmd]
571
+ } else {
572
+ # (nocolons , ::sub) -> ::sub::nocolons nocolons
573
+ return [list ${namespace}::$cmd $cmd]
574
+ }
575
+ } elseif {$namespace eq "::"} {
576
+ # (foo::bar , ::) -> ::foo::bar
577
+ return [list ::$cmd]
578
+ } else {
579
+ # (foo::bar , ::sub) -> ::sub::foo::bar ::foo::bar
580
+ return [list ${namespace}::$cmd ::$cmd]
581
+ }
582
+ }
583
+
584
+ # auto_import --
585
+ #
586
+ # Invoked during "namespace import" to make see if the imported commands
587
+ # reside in an autoloaded library. If so, the commands are loaded so
588
+ # that they will be available for the import links. If not, then this
589
+ # procedure does nothing.
590
+ #
591
+ # Arguments -
592
+ # pattern The pattern of commands being imported (like "foo::*")
593
+ # a canonical namespace as returned by [namespace current]
594
+
595
+ proc auto_import {pattern} {
596
+ global auto_index
597
+
598
+ # If no namespace is specified, this will be an error case
599
+
600
+ if {![string match *::* $pattern]} {
601
+ return
602
+ }
603
+
604
+ set ns [uplevel 1 [list ::namespace current]]
605
+ set patternList [auto_qualify $pattern $ns]
606
+
607
+ auto_load_index
608
+
609
+ foreach pattern $patternList {
610
+ foreach name [array names auto_index $pattern] {
611
+ if {([namespace which -command $name] eq "")
612
+ && ([namespace qualifiers $pattern] eq [namespace qualifiers $name])} {
613
+ namespace eval :: $auto_index($name)
614
+ }
615
+ }
616
+ }
617
+ }
618
+
619
+ # auto_execok --
620
+ #
621
+ # Returns string that indicates name of program to execute if
622
+ # name corresponds to a shell builtin or an executable in the
623
+ # Windows search path, or "" otherwise. Builds an associative
624
+ # array auto_execs that caches information about previous checks,
625
+ # for speed.
626
+ #
627
+ # Arguments:
628
+ # name - Name of a command.
629
+
630
+ if {$tcl_platform(platform) eq "windows"} {
631
+ # Windows version.
632
+ #
633
+ # Note that file executable doesn't work under Windows, so we have to
634
+ # look for files with .exe, .com, or .bat extensions. Also, the path
635
+ # may be in the Path or PATH environment variables, and path
636
+ # components are separated with semicolons, not colons as under Unix.
637
+ #
638
+ proc auto_execok name {
639
+ global auto_execs env tcl_platform
640
+
641
+ if {[info exists auto_execs($name)]} {
642
+ return $auto_execs($name)
643
+ }
644
+ set auto_execs($name) ""
645
+
646
+ set shellBuiltins [list assoc cls copy date del dir echo erase exit ftype \
647
+ md mkdir mklink move rd ren rename rmdir start time type ver vol]
648
+ if {[info exists env(PATHEXT)]} {
649
+ # Add an initial ; to have the {} extension check first.
650
+ set execExtensions [split ";$env(PATHEXT)" ";"]
651
+ } else {
652
+ set execExtensions [list {} .com .exe .bat .cmd]
653
+ }
654
+
655
+ if {[string tolower $name] in $shellBuiltins} {
656
+ # When this is command.com for some reason on Win2K, Tcl won't
657
+ # exec it unless the case is right, which this corrects. COMSPEC
658
+ # may not point to a real file, so do the check.
659
+ set cmd $env(COMSPEC)
660
+ if {[file exists $cmd]} {
661
+ set cmd [file attributes $cmd -shortname]
662
+ }
663
+ return [set auto_execs($name) [list $cmd /c $name]]
664
+ }
665
+
666
+ if {[llength [file split $name]] != 1} {
667
+ foreach ext $execExtensions {
668
+ set file ${name}${ext}
669
+ if {[file exists $file] && ![file isdirectory $file]} {
670
+ return [set auto_execs($name) [list $file]]
671
+ }
672
+ }
673
+ return ""
674
+ }
675
+
676
+ set path "[file dirname [info nameof]];.;"
677
+ if {[info exists env(SystemRoot)]} {
678
+ set windir $env(SystemRoot)
679
+ } elseif {[info exists env(WINDIR)]} {
680
+ set windir $env(WINDIR)
681
+ }
682
+ if {[info exists windir]} {
683
+ if {$tcl_platform(os) eq "Windows NT"} {
684
+ append path "$windir/system32;"
685
+ }
686
+ append path "$windir/system;$windir;"
687
+ }
688
+
689
+ foreach var {PATH Path path} {
690
+ if {[info exists env($var)]} {
691
+ append path ";$env($var)"
692
+ }
693
+ }
694
+
695
+ foreach ext $execExtensions {
696
+ unset -nocomplain checked
697
+ foreach dir [split $path {;}] {
698
+ # Skip already checked directories
699
+ if {[info exists checked($dir)] || ($dir eq "")} {
700
+ continue
701
+ }
702
+ set checked($dir) {}
703
+ set file [file join $dir ${name}${ext}]
704
+ if {[file exists $file] && ![file isdirectory $file]} {
705
+ return [set auto_execs($name) [list $file]]
706
+ }
707
+ }
708
+ }
709
+ return ""
710
+ }
711
+
712
+ } else {
713
+ # Unix version.
714
+ #
715
+ proc auto_execok name {
716
+ global auto_execs env
717
+
718
+ if {[info exists auto_execs($name)]} {
719
+ return $auto_execs($name)
720
+ }
721
+ set auto_execs($name) ""
722
+ if {[llength [file split $name]] != 1} {
723
+ if {[file executable $name] && ![file isdirectory $name]} {
724
+ set auto_execs($name) [list $name]
725
+ }
726
+ return $auto_execs($name)
727
+ }
728
+ foreach dir [split $env(PATH) :] {
729
+ if {$dir eq ""} {
730
+ set dir .
731
+ }
732
+ set file [file join $dir $name]
733
+ if {[file executable $file] && ![file isdirectory $file]} {
734
+ set auto_execs($name) [list $file]
735
+ return $auto_execs($name)
736
+ }
737
+ }
738
+ return ""
739
+ }
740
+
741
+ }
742
+
743
+ # ::tcl::CopyDirectory --
744
+ #
745
+ # This procedure is called by Tcl's core when attempts to call the
746
+ # filesystem's copydirectory function fail. The semantics of the call
747
+ # are that 'dest' does not yet exist, i.e. dest should become the exact
748
+ # image of src. If dest does exist, we throw an error.
749
+ #
750
+ # Note that making changes to this procedure can change the results
751
+ # of running Tcl's tests.
752
+ #
753
+ # Arguments:
754
+ # action - "renaming" or "copying"
755
+ # src - source directory
756
+ # dest - destination directory
757
+ proc tcl::CopyDirectory {action src dest} {
758
+ set nsrc [file normalize $src]
759
+ set ndest [file normalize $dest]
760
+
761
+ if {$action eq "renaming"} {
762
+ # Can't rename volumes. We could give a more precise
763
+ # error message here, but that would break the test suite.
764
+ if {$nsrc in [file volumes]} {
765
+ return -code error "error $action \"$src\" to\
766
+ \"$dest\": trying to rename a volume or move a directory\
767
+ into itself"
768
+ }
769
+ }
770
+ if {[file exists $dest]} {
771
+ if {$nsrc eq $ndest} {
772
+ return -code error "error $action \"$src\" to\
773
+ \"$dest\": trying to rename a volume or move a directory\
774
+ into itself"
775
+ }
776
+ if {$action eq "copying"} {
777
+ # We used to throw an error here, but, looking more closely
778
+ # at the core copy code in tclFCmd.c, if the destination
779
+ # exists, then we should only call this function if -force
780
+ # is true, which means we just want to over-write. So,
781
+ # the following code is now commented out.
782
+ #
783
+ # return -code error "error $action \"$src\" to\
784
+ # \"$dest\": file already exists"
785
+ } else {
786
+ # Depending on the platform, and on the current
787
+ # working directory, the directories '.', '..'
788
+ # can be returned in various combinations. Anyway,
789
+ # if any other file is returned, we must signal an error.
790
+ set existing [glob -nocomplain -directory $dest * .*]
791
+ lappend existing {*}[glob -nocomplain -directory $dest \
792
+ -type hidden * .*]
793
+ foreach s $existing {
794
+ if {[file tail $s] ni {. ..}} {
795
+ return -code error "error $action \"$src\" to\
796
+ \"$dest\": file already exists"
797
+ }
798
+ }
799
+ }
800
+ } else {
801
+ if {[string first $nsrc $ndest] >= 0} {
802
+ set srclen [expr {[llength [file split $nsrc]] - 1}]
803
+ set ndest [lindex [file split $ndest] $srclen]
804
+ if {$ndest eq [file tail $nsrc]} {
805
+ return -code error "error $action \"$src\" to\
806
+ \"$dest\": trying to rename a volume or move a directory\
807
+ into itself"
808
+ }
809
+ }
810
+ file mkdir $dest
811
+ }
812
+ # Have to be careful to capture both visible and hidden files.
813
+ # We will also be more generous to the file system and not
814
+ # assume the hidden and non-hidden lists are non-overlapping.
815
+ #
816
+ # On Unix 'hidden' files begin with '.'. On other platforms
817
+ # or filesystems hidden files may have other interpretations.
818
+ set filelist [concat [glob -nocomplain -directory $src *] \
819
+ [glob -nocomplain -directory $src -types hidden *]]
820
+
821
+ foreach s [lsort -unique $filelist] {
822
+ if {[file tail $s] ni {. ..}} {
823
+ file copy -force -- $s [file join $dest [file tail $s]]
824
+ }
825
+ }
826
+ return
827
+ }
lib/tcl8.6/package.tcl ADDED
@@ -0,0 +1,751 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # package.tcl --
2
+ #
3
+ # utility procs formerly in init.tcl which can be loaded on demand
4
+ # for package management.
5
+ #
6
+ # Copyright (c) 1991-1993 The Regents of the University of California.
7
+ # Copyright (c) 1994-1998 Sun Microsystems, Inc.
8
+ #
9
+ # See the file "license.terms" for information on usage and redistribution
10
+ # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
+ #
12
+
13
+ namespace eval tcl::Pkg {}
14
+
15
+ # ::tcl::Pkg::CompareExtension --
16
+ #
17
+ # Used internally by pkg_mkIndex to compare the extension of a file to a given
18
+ # extension. On Windows, it uses a case-insensitive comparison because the
19
+ # file system can be file insensitive.
20
+ #
21
+ # Arguments:
22
+ # fileName name of a file whose extension is compared
23
+ # ext (optional) The extension to compare against; you must
24
+ # provide the starting dot.
25
+ # Defaults to [info sharedlibextension]
26
+ #
27
+ # Results:
28
+ # Returns 1 if the extension matches, 0 otherwise
29
+
30
+ proc tcl::Pkg::CompareExtension {fileName {ext {}}} {
31
+ global tcl_platform
32
+ if {$ext eq ""} {set ext [info sharedlibextension]}
33
+ if {$tcl_platform(platform) eq "windows"} {
34
+ return [string equal -nocase [file extension $fileName] $ext]
35
+ } else {
36
+ # Some unices add trailing numbers after the .so, so
37
+ # we could have something like '.so.1.2'.
38
+ set root $fileName
39
+ while {1} {
40
+ set currExt [file extension $root]
41
+ if {$currExt eq $ext} {
42
+ return 1
43
+ }
44
+
45
+ # The current extension does not match; if it is not a numeric
46
+ # value, quit, as we are only looking to ignore version number
47
+ # extensions. Otherwise we might return 1 in this case:
48
+ # tcl::Pkg::CompareExtension foo.so.bar .so
49
+ # which should not match.
50
+
51
+ if {![string is integer -strict [string range $currExt 1 end]]} {
52
+ return 0
53
+ }
54
+ set root [file rootname $root]
55
+ }
56
+ }
57
+ }
58
+
59
+ # pkg_mkIndex --
60
+ # This procedure creates a package index in a given directory. The package
61
+ # index consists of a "pkgIndex.tcl" file whose contents are a Tcl script that
62
+ # sets up package information with "package require" commands. The commands
63
+ # describe all of the packages defined by the files given as arguments.
64
+ #
65
+ # Arguments:
66
+ # -direct (optional) If this flag is present, the generated
67
+ # code in pkgMkIndex.tcl will cause the package to be
68
+ # loaded when "package require" is executed, rather
69
+ # than lazily when the first reference to an exported
70
+ # procedure in the package is made.
71
+ # -verbose (optional) Verbose output; the name of each file that
72
+ # was successfully processed is printed out. Additionally,
73
+ # if processing of a file failed a message is printed.
74
+ # -load pat (optional) Preload any packages whose names match
75
+ # the pattern. Used to handle DLLs that depend on
76
+ # other packages during their Init procedure.
77
+ # dir - Name of the directory in which to create the index.
78
+ # args - Any number of additional arguments, each giving
79
+ # a glob pattern that matches the names of one or
80
+ # more shared libraries or Tcl script files in
81
+ # dir.
82
+
83
+ proc pkg_mkIndex {args} {
84
+ set usage {"pkg_mkIndex ?-direct? ?-lazy? ?-load pattern? ?-verbose? ?--? dir ?pattern ...?"}
85
+
86
+ set argCount [llength $args]
87
+ if {$argCount < 1} {
88
+ return -code error "wrong # args: should be\n$usage"
89
+ }
90
+
91
+ set more ""
92
+ set direct 1
93
+ set doVerbose 0
94
+ set loadPat ""
95
+ for {set idx 0} {$idx < $argCount} {incr idx} {
96
+ set flag [lindex $args $idx]
97
+ switch -glob -- $flag {
98
+ -- {
99
+ # done with the flags
100
+ incr idx
101
+ break
102
+ }
103
+ -verbose {
104
+ set doVerbose 1
105
+ }
106
+ -lazy {
107
+ set direct 0
108
+ append more " -lazy"
109
+ }
110
+ -direct {
111
+ append more " -direct"
112
+ }
113
+ -load {
114
+ incr idx
115
+ set loadPat [lindex $args $idx]
116
+ append more " -load $loadPat"
117
+ }
118
+ -* {
119
+ return -code error "unknown flag $flag: should be\n$usage"
120
+ }
121
+ default {
122
+ # done with the flags
123
+ break
124
+ }
125
+ }
126
+ }
127
+
128
+ set dir [lindex $args $idx]
129
+ set patternList [lrange $args [expr {$idx + 1}] end]
130
+ if {![llength $patternList]} {
131
+ set patternList [list "*.tcl" "*[info sharedlibextension]"]
132
+ }
133
+
134
+ try {
135
+ set fileList [glob -directory $dir -tails -types {r f} -- \
136
+ {*}$patternList]
137
+ } on error {msg opt} {
138
+ return -options $opt $msg
139
+ }
140
+ foreach file $fileList {
141
+ # For each file, figure out what commands and packages it provides.
142
+ # To do this, create a child interpreter, load the file into the
143
+ # interpreter, and get a list of the new commands and packages that
144
+ # are defined.
145
+
146
+ if {$file eq "pkgIndex.tcl"} {
147
+ continue
148
+ }
149
+
150
+ set c [interp create]
151
+
152
+ # Load into the child any packages currently loaded in the parent
153
+ # interpreter that match the -load pattern.
154
+
155
+ if {$loadPat ne ""} {
156
+ if {$doVerbose} {
157
+ tclLog "currently loaded packages: '[info loaded]'"
158
+ tclLog "trying to load all packages matching $loadPat"
159
+ }
160
+ if {![llength [info loaded]]} {
161
+ tclLog "warning: no packages are currently loaded, nothing"
162
+ tclLog "can possibly match '$loadPat'"
163
+ }
164
+ }
165
+ foreach pkg [info loaded] {
166
+ if {![string match -nocase $loadPat [lindex $pkg 1]]} {
167
+ continue
168
+ }
169
+ if {$doVerbose} {
170
+ tclLog "package [lindex $pkg 1] matches '$loadPat'"
171
+ }
172
+ try {
173
+ load [lindex $pkg 0] [lindex $pkg 1] $c
174
+ } on error err {
175
+ if {$doVerbose} {
176
+ tclLog "warning: load [lindex $pkg 0]\
177
+ [lindex $pkg 1]\nfailed with: $err"
178
+ }
179
+ } on ok {} {
180
+ if {$doVerbose} {
181
+ tclLog "loaded [lindex $pkg 0] [lindex $pkg 1]"
182
+ }
183
+ }
184
+ if {[lindex $pkg 1] eq "Tk"} {
185
+ # Withdraw . if Tk was loaded, to avoid showing a window.
186
+ $c eval [list wm withdraw .]
187
+ }
188
+ }
189
+
190
+ $c eval {
191
+ # Stub out the package command so packages can require other
192
+ # packages.
193
+
194
+ rename package __package_orig
195
+ proc package {what args} {
196
+ switch -- $what {
197
+ require {
198
+ return; # Ignore transitive requires
199
+ }
200
+ default {
201
+ __package_orig $what {*}$args
202
+ }
203
+ }
204
+ }
205
+ proc tclPkgUnknown args {}
206
+ package unknown tclPkgUnknown
207
+
208
+ # Stub out the unknown command so package can call into each other
209
+ # during their initialization.
210
+
211
+ proc unknown {args} {}
212
+
213
+ # Stub out the auto_import mechanism
214
+
215
+ proc auto_import {args} {}
216
+
217
+ # reserve the ::tcl namespace for support procs and temporary
218
+ # variables. This might make it awkward to generate a
219
+ # pkgIndex.tcl file for the ::tcl namespace.
220
+
221
+ namespace eval ::tcl {
222
+ variable dir ;# Current directory being processed
223
+ variable file ;# Current file being processed
224
+ variable direct ;# -direct flag value
225
+ variable x ;# Loop variable
226
+ variable debug ;# For debugging
227
+ variable type ;# "load" or "source", for -direct
228
+ variable namespaces ;# Existing namespaces (e.g., ::tcl)
229
+ variable packages ;# Existing packages (e.g., Tcl)
230
+ variable origCmds ;# Existing commands
231
+ variable newCmds ;# Newly created commands
232
+ variable newPkgs {} ;# Newly created packages
233
+ }
234
+ }
235
+
236
+ $c eval [list set ::tcl::dir $dir]
237
+ $c eval [list set ::tcl::file $file]
238
+ $c eval [list set ::tcl::direct $direct]
239
+
240
+ # Download needed procedures into the child because we've just deleted
241
+ # the unknown procedure. This doesn't handle procedures with default
242
+ # arguments.
243
+
244
+ foreach p {::tcl::Pkg::CompareExtension} {
245
+ $c eval [list namespace eval [namespace qualifiers $p] {}]
246
+ $c eval [list proc $p [info args $p] [info body $p]]
247
+ }
248
+
249
+ try {
250
+ $c eval {
251
+ set ::tcl::debug "loading or sourcing"
252
+
253
+ # we need to track command defined by each package even in the
254
+ # -direct case, because they are needed internally by the
255
+ # "partial pkgIndex.tcl" step above.
256
+
257
+ proc ::tcl::GetAllNamespaces {{root ::}} {
258
+ set list $root
259
+ foreach ns [namespace children $root] {
260
+ lappend list {*}[::tcl::GetAllNamespaces $ns]
261
+ }
262
+ return $list
263
+ }
264
+
265
+ # init the list of existing namespaces, packages, commands
266
+
267
+ foreach ::tcl::x [::tcl::GetAllNamespaces] {
268
+ set ::tcl::namespaces($::tcl::x) 1
269
+ }
270
+ foreach ::tcl::x [package names] {
271
+ if {[package provide $::tcl::x] ne ""} {
272
+ set ::tcl::packages($::tcl::x) 1
273
+ }
274
+ }
275
+ set ::tcl::origCmds [info commands]
276
+
277
+ # Try to load the file if it has the shared library extension,
278
+ # otherwise source it. It's important not to try to load
279
+ # files that aren't shared libraries, because on some systems
280
+ # (like SunOS) the loader will abort the whole application
281
+ # when it gets an error.
282
+
283
+ if {[::tcl::Pkg::CompareExtension $::tcl::file [info sharedlibextension]]} {
284
+ # The "file join ." command below is necessary. Without
285
+ # it, if the file name has no \'s and we're on UNIX, the
286
+ # load command will invoke the LD_LIBRARY_PATH search
287
+ # mechanism, which could cause the wrong file to be used.
288
+
289
+ set ::tcl::debug loading
290
+ load [file join $::tcl::dir $::tcl::file]
291
+ set ::tcl::type load
292
+ } else {
293
+ set ::tcl::debug sourcing
294
+ source [file join $::tcl::dir $::tcl::file]
295
+ set ::tcl::type source
296
+ }
297
+
298
+ # As a performance optimization, if we are creating direct
299
+ # load packages, don't bother figuring out the set of commands
300
+ # created by the new packages. We only need that list for
301
+ # setting up the autoloading used in the non-direct case.
302
+ if {!$::tcl::direct} {
303
+ # See what new namespaces appeared, and import commands
304
+ # from them. Only exported commands go into the index.
305
+
306
+ foreach ::tcl::x [::tcl::GetAllNamespaces] {
307
+ if {![info exists ::tcl::namespaces($::tcl::x)]} {
308
+ namespace import -force ${::tcl::x}::*
309
+ }
310
+
311
+ # Figure out what commands appeared
312
+
313
+ foreach ::tcl::x [info commands] {
314
+ set ::tcl::newCmds($::tcl::x) 1
315
+ }
316
+ foreach ::tcl::x $::tcl::origCmds {
317
+ unset -nocomplain ::tcl::newCmds($::tcl::x)
318
+ }
319
+ foreach ::tcl::x [array names ::tcl::newCmds] {
320
+ # determine which namespace a command comes from
321
+
322
+ set ::tcl::abs [namespace origin $::tcl::x]
323
+
324
+ # special case so that global names have no
325
+ # leading ::, this is required by the unknown
326
+ # command
327
+
328
+ set ::tcl::abs \
329
+ [lindex [auto_qualify $::tcl::abs ::] 0]
330
+
331
+ if {$::tcl::x ne $::tcl::abs} {
332
+ # Name changed during qualification
333
+
334
+ set ::tcl::newCmds($::tcl::abs) 1
335
+ unset ::tcl::newCmds($::tcl::x)
336
+ }
337
+ }
338
+ }
339
+ }
340
+
341
+ # Look through the packages that appeared, and if there is a
342
+ # version provided, then record it
343
+
344
+ foreach ::tcl::x [package names] {
345
+ if {[package provide $::tcl::x] ne ""
346
+ && ![info exists ::tcl::packages($::tcl::x)]} {
347
+ lappend ::tcl::newPkgs \
348
+ [list $::tcl::x [package provide $::tcl::x]]
349
+ }
350
+ }
351
+ }
352
+ } on error msg {
353
+ set what [$c eval set ::tcl::debug]
354
+ if {$doVerbose} {
355
+ tclLog "warning: error while $what $file: $msg"
356
+ }
357
+ } on ok {} {
358
+ set what [$c eval set ::tcl::debug]
359
+ if {$doVerbose} {
360
+ tclLog "successful $what of $file"
361
+ }
362
+ set type [$c eval set ::tcl::type]
363
+ set cmds [lsort [$c eval array names ::tcl::newCmds]]
364
+ set pkgs [$c eval set ::tcl::newPkgs]
365
+ if {$doVerbose} {
366
+ if {!$direct} {
367
+ tclLog "commands provided were $cmds"
368
+ }
369
+ tclLog "packages provided were $pkgs"
370
+ }
371
+ if {[llength $pkgs] > 1} {
372
+ tclLog "warning: \"$file\" provides more than one package ($pkgs)"
373
+ }
374
+ foreach pkg $pkgs {
375
+ # cmds is empty/not used in the direct case
376
+ lappend files($pkg) [list $file $type $cmds]
377
+ }
378
+
379
+ if {$doVerbose} {
380
+ tclLog "processed $file"
381
+ }
382
+ }
383
+ interp delete $c
384
+ }
385
+
386
+ append index "# Tcl package index file, version 1.1\n"
387
+ append index "# This file is generated by the \"pkg_mkIndex$more\" command\n"
388
+ append index "# and sourced either when an application starts up or\n"
389
+ append index "# by a \"package unknown\" script. It invokes the\n"
390
+ append index "# \"package ifneeded\" command to set up package-related\n"
391
+ append index "# information so that packages will be loaded automatically\n"
392
+ append index "# in response to \"package require\" commands. When this\n"
393
+ append index "# script is sourced, the variable \$dir must contain the\n"
394
+ append index "# full path name of this file's directory.\n"
395
+
396
+ foreach pkg [lsort [array names files]] {
397
+ set cmd {}
398
+ lassign $pkg name version
399
+ lappend cmd ::tcl::Pkg::Create -name $name -version $version
400
+ foreach spec [lsort -index 0 $files($pkg)] {
401
+ foreach {file type procs} $spec {
402
+ if {$direct} {
403
+ set procs {}
404
+ }
405
+ lappend cmd "-$type" [list $file $procs]
406
+ }
407
+ }
408
+ append index "\n[eval $cmd]"
409
+ }
410
+
411
+ set f [open [file join $dir pkgIndex.tcl] w]
412
+ puts $f $index
413
+ close $f
414
+ }
415
+
416
+ # tclPkgSetup --
417
+ # This is a utility procedure use by pkgIndex.tcl files. It is invoked as
418
+ # part of a "package ifneeded" script. It calls "package provide" to indicate
419
+ # that a package is available, then sets entries in the auto_index array so
420
+ # that the package's files will be auto-loaded when the commands are used.
421
+ #
422
+ # Arguments:
423
+ # dir - Directory containing all the files for this package.
424
+ # pkg - Name of the package (no version number).
425
+ # version - Version number for the package, such as 2.1.3.
426
+ # files - List of files that constitute the package. Each
427
+ # element is a sub-list with three elements. The first
428
+ # is the name of a file relative to $dir, the second is
429
+ # "load" or "source", indicating whether the file is a
430
+ # loadable binary or a script to source, and the third
431
+ # is a list of commands defined by this file.
432
+
433
+ proc tclPkgSetup {dir pkg version files} {
434
+ global auto_index
435
+
436
+ package provide $pkg $version
437
+ foreach fileInfo $files {
438
+ set f [lindex $fileInfo 0]
439
+ set type [lindex $fileInfo 1]
440
+ foreach cmd [lindex $fileInfo 2] {
441
+ if {$type eq "load"} {
442
+ set auto_index($cmd) [list load [file join $dir $f] $pkg]
443
+ } else {
444
+ set auto_index($cmd) [list source [file join $dir $f]]
445
+ }
446
+ }
447
+ }
448
+ }
449
+
450
+ # tclPkgUnknown --
451
+ # This procedure provides the default for the "package unknown" function. It
452
+ # is invoked when a package that's needed can't be found. It scans the
453
+ # auto_path directories and their immediate children looking for pkgIndex.tcl
454
+ # files and sources any such files that are found to setup the package
455
+ # database. As it searches, it will recognize changes to the auto_path and
456
+ # scan any new directories.
457
+ #
458
+ # Arguments:
459
+ # name - Name of desired package. Not used.
460
+ # version - Version of desired package. Not used.
461
+ # exact - Either "-exact" or omitted. Not used.
462
+
463
+ proc tclPkgUnknown {name args} {
464
+ global auto_path env
465
+
466
+ if {![info exists auto_path]} {
467
+ return
468
+ }
469
+ # Cache the auto_path, because it may change while we run through the
470
+ # first set of pkgIndex.tcl files
471
+ set old_path [set use_path $auto_path]
472
+ while {[llength $use_path]} {
473
+ set dir [lindex $use_path end]
474
+
475
+ # Make sure we only scan each directory one time.
476
+ if {[info exists tclSeenPath($dir)]} {
477
+ set use_path [lrange $use_path 0 end-1]
478
+ continue
479
+ }
480
+ set tclSeenPath($dir) 1
481
+
482
+ # Get the pkgIndex.tcl files in subdirectories of auto_path directories.
483
+ # - Safe Base interpreters have a restricted "glob" command that
484
+ # works in this case.
485
+ # - The "catch" was essential when there was no safe glob and every
486
+ # call in a safe interp failed; it is retained only for corner
487
+ # cases in which the eventual call to glob returns an error.
488
+ catch {
489
+ foreach file [glob -directory $dir -join -nocomplain \
490
+ * pkgIndex.tcl] {
491
+ set dir [file dirname $file]
492
+ if {![info exists procdDirs($dir)]} {
493
+ try {
494
+ source $file
495
+ } trap {POSIX EACCES} {} {
496
+ # $file was not readable; silently ignore
497
+ continue
498
+ } on error msg {
499
+ tclLog "error reading package index file $file: $msg"
500
+ } on ok {} {
501
+ set procdDirs($dir) 1
502
+ }
503
+ }
504
+ }
505
+ }
506
+ set dir [lindex $use_path end]
507
+ if {![info exists procdDirs($dir)]} {
508
+ set file [file join $dir pkgIndex.tcl]
509
+ # safe interps usually don't have "file exists",
510
+ if {([interp issafe] || [file exists $file])} {
511
+ try {
512
+ source $file
513
+ } trap {POSIX EACCES} {} {
514
+ # $file was not readable; silently ignore
515
+ continue
516
+ } on error msg {
517
+ tclLog "error reading package index file $file: $msg"
518
+ } on ok {} {
519
+ set procdDirs($dir) 1
520
+ }
521
+ }
522
+ }
523
+
524
+ set use_path [lrange $use_path 0 end-1]
525
+
526
+ # Check whether any of the index scripts we [source]d above set a new
527
+ # value for $::auto_path. If so, then find any new directories on the
528
+ # $::auto_path, and lappend them to the $use_path we are working from.
529
+ # This gives index scripts the (arguably unwise) power to expand the
530
+ # index script search path while the search is in progress.
531
+ set index 0
532
+ if {[llength $old_path] == [llength $auto_path]} {
533
+ foreach dir $auto_path old $old_path {
534
+ if {$dir ne $old} {
535
+ # This entry in $::auto_path has changed.
536
+ break
537
+ }
538
+ incr index
539
+ }
540
+ }
541
+
542
+ # $index now points to the first element of $auto_path that has
543
+ # changed, or the beginning if $auto_path has changed length Scan the
544
+ # new elements of $auto_path for directories to add to $use_path.
545
+ # Don't add directories we've already seen, or ones already on the
546
+ # $use_path.
547
+ foreach dir [lrange $auto_path $index end] {
548
+ if {![info exists tclSeenPath($dir)] && ($dir ni $use_path)} {
549
+ lappend use_path $dir
550
+ }
551
+ }
552
+ set old_path $auto_path
553
+ }
554
+ }
555
+
556
+ # tcl::MacOSXPkgUnknown --
557
+ # This procedure extends the "package unknown" function for MacOSX. It scans
558
+ # the Resources/Scripts directories of the immediate children of the auto_path
559
+ # directories for pkgIndex files.
560
+ #
561
+ # Arguments:
562
+ # original - original [package unknown] procedure
563
+ # name - Name of desired package. Not used.
564
+ # version - Version of desired package. Not used.
565
+ # exact - Either "-exact" or omitted. Not used.
566
+
567
+ proc tcl::MacOSXPkgUnknown {original name args} {
568
+ # First do the cross-platform default search
569
+ uplevel 1 $original [linsert $args 0 $name]
570
+
571
+ # Now do MacOSX specific searching
572
+ global auto_path
573
+
574
+ if {![info exists auto_path]} {
575
+ return
576
+ }
577
+ # Cache the auto_path, because it may change while we run through the
578
+ # first set of pkgIndex.tcl files
579
+ set old_path [set use_path $auto_path]
580
+ while {[llength $use_path]} {
581
+ set dir [lindex $use_path end]
582
+
583
+ # Make sure we only scan each directory one time.
584
+ if {[info exists tclSeenPath($dir)]} {
585
+ set use_path [lrange $use_path 0 end-1]
586
+ continue
587
+ }
588
+ set tclSeenPath($dir) 1
589
+
590
+ # get the pkgIndex files out of the subdirectories
591
+ # Safe interpreters do not use tcl::MacOSXPkgUnknown - see init.tcl.
592
+ foreach file [glob -directory $dir -join -nocomplain \
593
+ * Resources Scripts pkgIndex.tcl] {
594
+ set dir [file dirname $file]
595
+ if {![info exists procdDirs($dir)]} {
596
+ try {
597
+ source $file
598
+ } trap {POSIX EACCES} {} {
599
+ # $file was not readable; silently ignore
600
+ continue
601
+ } on error msg {
602
+ tclLog "error reading package index file $file: $msg"
603
+ } on ok {} {
604
+ set procdDirs($dir) 1
605
+ }
606
+ }
607
+ }
608
+ set use_path [lrange $use_path 0 end-1]
609
+
610
+ # Check whether any of the index scripts we [source]d above set a new
611
+ # value for $::auto_path. If so, then find any new directories on the
612
+ # $::auto_path, and lappend them to the $use_path we are working from.
613
+ # This gives index scripts the (arguably unwise) power to expand the
614
+ # index script search path while the search is in progress.
615
+ set index 0
616
+ if {[llength $old_path] == [llength $auto_path]} {
617
+ foreach dir $auto_path old $old_path {
618
+ if {$dir ne $old} {
619
+ # This entry in $::auto_path has changed.
620
+ break
621
+ }
622
+ incr index
623
+ }
624
+ }
625
+
626
+ # $index now points to the first element of $auto_path that has
627
+ # changed, or the beginning if $auto_path has changed length Scan the
628
+ # new elements of $auto_path for directories to add to $use_path.
629
+ # Don't add directories we've already seen, or ones already on the
630
+ # $use_path.
631
+ foreach dir [lrange $auto_path $index end] {
632
+ if {![info exists tclSeenPath($dir)] && ($dir ni $use_path)} {
633
+ lappend use_path $dir
634
+ }
635
+ }
636
+ set old_path $auto_path
637
+ }
638
+ }
639
+
640
+ # ::tcl::Pkg::Create --
641
+ #
642
+ # Given a package specification generate a "package ifneeded" statement
643
+ # for the package, suitable for inclusion in a pkgIndex.tcl file.
644
+ #
645
+ # Arguments:
646
+ # args arguments used by the Create function:
647
+ # -name packageName
648
+ # -version packageVersion
649
+ # -load {filename ?{procs}?}
650
+ # ...
651
+ # -source {filename ?{procs}?}
652
+ # ...
653
+ #
654
+ # Any number of -load and -source parameters may be
655
+ # specified, so long as there is at least one -load or
656
+ # -source parameter. If the procs component of a module
657
+ # specifier is left off, that module will be set up for
658
+ # direct loading; otherwise, it will be set up for lazy
659
+ # loading. If both -source and -load are specified, the
660
+ # -load'ed files will be loaded first, followed by the
661
+ # -source'd files.
662
+ #
663
+ # Results:
664
+ # An appropriate "package ifneeded" statement for the package.
665
+
666
+ proc ::tcl::Pkg::Create {args} {
667
+ append err(usage) "[lindex [info level 0] 0] "
668
+ append err(usage) "-name packageName -version packageVersion"
669
+ append err(usage) "?-load {filename ?{procs}?}? ... "
670
+ append err(usage) "?-source {filename ?{procs}?}? ..."
671
+
672
+ set err(wrongNumArgs) "wrong # args: should be \"$err(usage)\""
673
+ set err(valueMissing) "value for \"%s\" missing: should be \"$err(usage)\""
674
+ set err(unknownOpt) "unknown option \"%s\": should be \"$err(usage)\""
675
+ set err(noLoadOrSource) "at least one of -load and -source must be given"
676
+
677
+ # process arguments
678
+ set len [llength $args]
679
+ if {$len < 6} {
680
+ error $err(wrongNumArgs)
681
+ }
682
+
683
+ # Initialize parameters
684
+ array set opts {-name {} -version {} -source {} -load {}}
685
+
686
+ # process parameters
687
+ for {set i 0} {$i < $len} {incr i} {
688
+ set flag [lindex $args $i]
689
+ incr i
690
+ switch -glob -- $flag {
691
+ "-name" -
692
+ "-version" {
693
+ if {$i >= $len} {
694
+ error [format $err(valueMissing) $flag]
695
+ }
696
+ set opts($flag) [lindex $args $i]
697
+ }
698
+ "-source" -
699
+ "-load" {
700
+ if {$i >= $len} {
701
+ error [format $err(valueMissing) $flag]
702
+ }
703
+ lappend opts($flag) [lindex $args $i]
704
+ }
705
+ default {
706
+ error [format $err(unknownOpt) [lindex $args $i]]
707
+ }
708
+ }
709
+ }
710
+
711
+ # Validate the parameters
712
+ if {![llength $opts(-name)]} {
713
+ error [format $err(valueMissing) "-name"]
714
+ }
715
+ if {![llength $opts(-version)]} {
716
+ error [format $err(valueMissing) "-version"]
717
+ }
718
+
719
+ if {!([llength $opts(-source)] || [llength $opts(-load)])} {
720
+ error $err(noLoadOrSource)
721
+ }
722
+
723
+ # OK, now everything is good. Generate the package ifneeded statement.
724
+ set cmdline "package ifneeded $opts(-name) $opts(-version) "
725
+
726
+ set cmdList {}
727
+ set lazyFileList {}
728
+
729
+ # Handle -load and -source specs
730
+ foreach key {load source} {
731
+ foreach filespec $opts(-$key) {
732
+ lassign $filespec filename proclist
733
+
734
+ if { [llength $proclist] == 0 } {
735
+ set cmd "\[list $key \[file join \$dir [list $filename]\]\]"
736
+ lappend cmdList $cmd
737
+ } else {
738
+ lappend lazyFileList [list $filename $key $proclist]
739
+ }
740
+ }
741
+ }
742
+
743
+ if {[llength $lazyFileList]} {
744
+ lappend cmdList "\[list tclPkgSetup \$dir $opts(-name)\
745
+ $opts(-version) [list $lazyFileList]\]"
746
+ }
747
+ append cmdline [join $cmdList "\\n"]
748
+ return $cmdline
749
+ }
750
+
751
+ interp alias {} ::pkg::create {} ::tcl::Pkg::Create
lib/tcl8.6/parray.tcl ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # parray:
2
+ # Print the contents of a global array on stdout.
3
+ #
4
+ # Copyright (c) 1991-1993 The Regents of the University of California.
5
+ # Copyright (c) 1994 Sun Microsystems, Inc.
6
+ #
7
+ # See the file "license.terms" for information on usage and redistribution
8
+ # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9
+ #
10
+
11
+ proc parray {a {pattern *}} {
12
+ upvar 1 $a array
13
+ if {![array exists array]} {
14
+ return -code error "\"$a\" isn't an array"
15
+ }
16
+ set maxl 0
17
+ set names [lsort [array names array $pattern]]
18
+ foreach name $names {
19
+ if {[string length $name] > $maxl} {
20
+ set maxl [string length $name]
21
+ }
22
+ }
23
+ set maxl [expr {$maxl + [string length $a] + 2}]
24
+ foreach name $names {
25
+ set nameString [format %s(%s) $a $name]
26
+ puts stdout [format "%-*s = %s" $maxl $nameString $array($name)]
27
+ }
28
+ }
lib/tcl8.6/safe.tcl ADDED
@@ -0,0 +1,1289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # safe.tcl --
2
+ #
3
+ # This file provide a safe loading/sourcing mechanism for safe interpreters.
4
+ # It implements a virtual path mechanism to hide the real pathnames from the
5
+ # child. It runs in a parent interpreter and sets up data structure and
6
+ # aliases that will be invoked when used from a child interpreter.
7
+ #
8
+ # See the safe.n man page for details.
9
+ #
10
+ # Copyright (c) 1996-1997 Sun Microsystems, Inc.
11
+ #
12
+ # See the file "license.terms" for information on usage and redistribution of
13
+ # this file, and for a DISCLAIMER OF ALL WARRANTIES.
14
+
15
+ #
16
+ # The implementation is based on namespaces. These naming conventions are
17
+ # followed:
18
+ # Private procs starts with uppercase.
19
+ # Public procs are exported and starts with lowercase
20
+ #
21
+
22
+ # Needed utilities package
23
+ package require opt 0.4.8
24
+
25
+ # Create the safe namespace
26
+ namespace eval ::safe {
27
+ # Exported API:
28
+ namespace export interpCreate interpInit interpConfigure interpDelete \
29
+ interpAddToAccessPath interpFindInAccessPath setLogCmd
30
+ }
31
+
32
+ # Helper function to resolve the dual way of specifying staticsok (either
33
+ # by -noStatics or -statics 0)
34
+ proc ::safe::InterpStatics {} {
35
+ foreach v {Args statics noStatics} {
36
+ upvar $v $v
37
+ }
38
+ set flag [::tcl::OptProcArgGiven -noStatics]
39
+ if {$flag && (!$noStatics == !$statics)
40
+ && ([::tcl::OptProcArgGiven -statics])} {
41
+ return -code error\
42
+ "conflicting values given for -statics and -noStatics"
43
+ }
44
+ if {$flag} {
45
+ return [expr {!$noStatics}]
46
+ } else {
47
+ return $statics
48
+ }
49
+ }
50
+
51
+ # Helper function to resolve the dual way of specifying nested loading
52
+ # (either by -nestedLoadOk or -nested 1)
53
+ proc ::safe::InterpNested {} {
54
+ foreach v {Args nested nestedLoadOk} {
55
+ upvar $v $v
56
+ }
57
+ set flag [::tcl::OptProcArgGiven -nestedLoadOk]
58
+ # note that the test here is the opposite of the "InterpStatics" one
59
+ # (it is not -noNested... because of the wanted default value)
60
+ if {$flag && (!$nestedLoadOk != !$nested)
61
+ && ([::tcl::OptProcArgGiven -nested])} {
62
+ return -code error\
63
+ "conflicting values given for -nested and -nestedLoadOk"
64
+ }
65
+ if {$flag} {
66
+ # another difference with "InterpStatics"
67
+ return $nestedLoadOk
68
+ } else {
69
+ return $nested
70
+ }
71
+ }
72
+
73
+ ####
74
+ #
75
+ # API entry points that needs argument parsing :
76
+ #
77
+ ####
78
+
79
+ # Interface/entry point function and front end for "Create"
80
+ proc ::safe::interpCreate {args} {
81
+ set Args [::tcl::OptKeyParse ::safe::interpCreate $args]
82
+ RejectExcessColons $slave
83
+ InterpCreate $slave $accessPath \
84
+ [InterpStatics] [InterpNested] $deleteHook
85
+ }
86
+
87
+ proc ::safe::interpInit {args} {
88
+ set Args [::tcl::OptKeyParse ::safe::interpIC $args]
89
+ if {![::interp exists $slave]} {
90
+ return -code error "\"$slave\" is not an interpreter"
91
+ }
92
+ RejectExcessColons $slave
93
+ InterpInit $slave $accessPath \
94
+ [InterpStatics] [InterpNested] $deleteHook
95
+ }
96
+
97
+ # Check that the given child is "one of us"
98
+ proc ::safe::CheckInterp {child} {
99
+ namespace upvar ::safe [VarName $child] state
100
+ if {![info exists state] || ![::interp exists $child]} {
101
+ return -code error \
102
+ "\"$child\" is not an interpreter managed by ::safe::"
103
+ }
104
+ }
105
+
106
+ # Interface/entry point function and front end for "Configure". This code
107
+ # is awfully pedestrian because it would need more coupling and support
108
+ # between the way we store the configuration values in safe::interp's and
109
+ # the Opt package. Obviously we would like an OptConfigure to avoid
110
+ # duplicating all this code everywhere.
111
+ # -> TODO (the app should share or access easily the program/value stored
112
+ # by opt)
113
+
114
+ # This is even more complicated by the boolean flags with no values that
115
+ # we had the bad idea to support for the sake of user simplicity in
116
+ # create/init but which makes life hard in configure...
117
+ # So this will be hopefully written and some integrated with opt1.0
118
+ # (hopefully for tcl8.1 ?)
119
+ proc ::safe::interpConfigure {args} {
120
+ switch [llength $args] {
121
+ 1 {
122
+ # If we have exactly 1 argument the semantic is to return all
123
+ # the current configuration. We still call OptKeyParse though
124
+ # we know that "child" is our given argument because it also
125
+ # checks for the "-help" option.
126
+ set Args [::tcl::OptKeyParse ::safe::interpIC $args]
127
+ CheckInterp $slave
128
+ namespace upvar ::safe [VarName $slave] state
129
+
130
+ return [join [list \
131
+ [list -accessPath $state(access_path)] \
132
+ [list -statics $state(staticsok)] \
133
+ [list -nested $state(nestedok)] \
134
+ [list -deleteHook $state(cleanupHook)]]]
135
+ }
136
+ 2 {
137
+ # If we have exactly 2 arguments the semantic is a "configure
138
+ # get"
139
+ lassign $args slave arg
140
+
141
+ # get the flag sub program (we 'know' about Opt's internal
142
+ # representation of data)
143
+ set desc [lindex [::tcl::OptKeyGetDesc ::safe::interpIC] 2]
144
+ set hits [::tcl::OptHits desc $arg]
145
+ if {$hits > 1} {
146
+ return -code error [::tcl::OptAmbigous $desc $arg]
147
+ } elseif {$hits == 0} {
148
+ return -code error [::tcl::OptFlagUsage $desc $arg]
149
+ }
150
+ CheckInterp $slave
151
+ namespace upvar ::safe [VarName $slave] state
152
+
153
+ set item [::tcl::OptCurDesc $desc]
154
+ set name [::tcl::OptName $item]
155
+ switch -exact -- $name {
156
+ -accessPath {
157
+ return [list -accessPath $state(access_path)]
158
+ }
159
+ -statics {
160
+ return [list -statics $state(staticsok)]
161
+ }
162
+ -nested {
163
+ return [list -nested $state(nestedok)]
164
+ }
165
+ -deleteHook {
166
+ return [list -deleteHook $state(cleanupHook)]
167
+ }
168
+ -noStatics {
169
+ # it is most probably a set in fact but we would need
170
+ # then to jump to the set part and it is not *sure*
171
+ # that it is a set action that the user want, so force
172
+ # it to use the unambiguous -statics ?value? instead:
173
+ return -code error\
174
+ "ambigous query (get or set -noStatics ?)\
175
+ use -statics instead"
176
+ }
177
+ -nestedLoadOk {
178
+ return -code error\
179
+ "ambigous query (get or set -nestedLoadOk ?)\
180
+ use -nested instead"
181
+ }
182
+ default {
183
+ return -code error "unknown flag $name (bug)"
184
+ }
185
+ }
186
+ }
187
+ default {
188
+ # Otherwise we want to parse the arguments like init and
189
+ # create did
190
+ set Args [::tcl::OptKeyParse ::safe::interpIC $args]
191
+ CheckInterp $slave
192
+ namespace upvar ::safe [VarName $slave] state
193
+
194
+ # Get the current (and not the default) values of whatever has
195
+ # not been given:
196
+ if {![::tcl::OptProcArgGiven -accessPath]} {
197
+ set doreset 0
198
+ set accessPath $state(access_path)
199
+ } else {
200
+ set doreset 1
201
+ }
202
+ if {
203
+ ![::tcl::OptProcArgGiven -statics]
204
+ && ![::tcl::OptProcArgGiven -noStatics]
205
+ } then {
206
+ set statics $state(staticsok)
207
+ } else {
208
+ set statics [InterpStatics]
209
+ }
210
+ if {
211
+ [::tcl::OptProcArgGiven -nested] ||
212
+ [::tcl::OptProcArgGiven -nestedLoadOk]
213
+ } then {
214
+ set nested [InterpNested]
215
+ } else {
216
+ set nested $state(nestedok)
217
+ }
218
+ if {![::tcl::OptProcArgGiven -deleteHook]} {
219
+ set deleteHook $state(cleanupHook)
220
+ }
221
+ # we can now reconfigure :
222
+ InterpSetConfig $slave $accessPath $statics $nested $deleteHook
223
+ # auto_reset the child (to completely synch the new access_path)
224
+ if {$doreset} {
225
+ if {[catch {::interp eval $slave {auto_reset}} msg]} {
226
+ Log $slave "auto_reset failed: $msg"
227
+ } else {
228
+ Log $slave "successful auto_reset" NOTICE
229
+ }
230
+
231
+ # Sync the paths used to search for Tcl modules.
232
+ ::interp eval $slave {tcl::tm::path remove {*}[tcl::tm::list]}
233
+ if {[llength $state(tm_path_slave)] > 0} {
234
+ ::interp eval $slave [list \
235
+ ::tcl::tm::add {*}[lreverse $state(tm_path_slave)]]
236
+ }
237
+
238
+ # Remove stale "package ifneeded" data for non-loaded packages.
239
+ # - Not for loaded packages, because "package forget" erases
240
+ # data from "package provide" as well as "package ifneeded".
241
+ # - This is OK because the script cannot reload any version of
242
+ # the package unless it first does "package forget".
243
+ foreach pkg [::interp eval $slave {package names}] {
244
+ if {[::interp eval $slave [list package provide $pkg]] eq ""} {
245
+ ::interp eval $slave [list package forget $pkg]
246
+ }
247
+ }
248
+ }
249
+ return
250
+ }
251
+ }
252
+ }
253
+
254
+ ####
255
+ #
256
+ # Functions that actually implements the exported APIs
257
+ #
258
+ ####
259
+
260
+ #
261
+ # safe::InterpCreate : doing the real job
262
+ #
263
+ # This procedure creates a safe interpreter and initializes it with the safe
264
+ # base aliases.
265
+ # NB: child name must be simple alphanumeric string, no spaces, no (), no
266
+ # {},... {because the state array is stored as part of the name}
267
+ #
268
+ # Returns the child name.
269
+ #
270
+ # Optional Arguments :
271
+ # + child name : if empty, generated name will be used
272
+ # + access_path: path list controlling where load/source can occur,
273
+ # if empty: the parent auto_path will be used.
274
+ # + staticsok : flag, if 0 :no static package can be loaded (load {} Xxx)
275
+ # if 1 :static packages are ok.
276
+ # + nestedok: flag, if 0 :no loading to sub-sub interps (load xx xx sub)
277
+ # if 1 : multiple levels are ok.
278
+
279
+ # use the full name and no indent so auto_mkIndex can find us
280
+ proc ::safe::InterpCreate {
281
+ child
282
+ access_path
283
+ staticsok
284
+ nestedok
285
+ deletehook
286
+ } {
287
+ # Create the child.
288
+ # If evaluated in ::safe, the interpreter command for foo is ::foo;
289
+ # but for foo::bar is safe::foo::bar. So evaluate in :: instead.
290
+ if {$child ne ""} {
291
+ namespace eval :: [list ::interp create -safe $child]
292
+ } else {
293
+ # empty argument: generate child name
294
+ set child [::interp create -safe]
295
+ }
296
+ Log $child "Created" NOTICE
297
+
298
+ # Initialize it. (returns child name)
299
+ InterpInit $child $access_path $staticsok $nestedok $deletehook
300
+ }
301
+
302
+ #
303
+ # InterpSetConfig (was setAccessPath) :
304
+ # Sets up child virtual auto_path and corresponding structure within
305
+ # the parent. Also sets the tcl_library in the child to be the first
306
+ # directory in the path.
307
+ # NB: If you change the path after the child has been initialized you
308
+ # probably need to call "auto_reset" in the child in order that it gets
309
+ # the right auto_index() array values.
310
+
311
+ proc ::safe::InterpSetConfig {child access_path staticsok nestedok deletehook} {
312
+ global auto_path
313
+
314
+ # determine and store the access path if empty
315
+ if {$access_path eq ""} {
316
+ set access_path $auto_path
317
+
318
+ # Make sure that tcl_library is in auto_path and at the first
319
+ # position (needed by setAccessPath)
320
+ set where [lsearch -exact $access_path [info library]]
321
+ if {$where < 0} {
322
+ # not found, add it.
323
+ set access_path [linsert $access_path 0 [info library]]
324
+ Log $child "tcl_library was not in auto_path,\
325
+ added it to slave's access_path" NOTICE
326
+ } elseif {$where != 0} {
327
+ # not first, move it first
328
+ set access_path [linsert \
329
+ [lreplace $access_path $where $where] \
330
+ 0 [info library]]
331
+ Log $child "tcl_libray was not in first in auto_path,\
332
+ moved it to front of slave's access_path" NOTICE
333
+ }
334
+
335
+ # Add 1st level subdirs (will searched by auto loading from tcl
336
+ # code in the child using glob and thus fail, so we add them here
337
+ # so by default it works the same).
338
+ set access_path [AddSubDirs $access_path]
339
+ }
340
+
341
+ Log $child "Setting accessPath=($access_path) staticsok=$staticsok\
342
+ nestedok=$nestedok deletehook=($deletehook)" NOTICE
343
+
344
+ namespace upvar ::safe [VarName $child] state
345
+
346
+ # clear old autopath if it existed
347
+ # build new one
348
+ # Extend the access list with the paths used to look for Tcl Modules.
349
+ # We save the virtual form separately as well, as syncing it with the
350
+ # child has to be deferred until the necessary commands are present for
351
+ # setup.
352
+
353
+ set norm_access_path {}
354
+ set slave_access_path {}
355
+ set map_access_path {}
356
+ set remap_access_path {}
357
+ set slave_tm_path {}
358
+
359
+ set i 0
360
+ foreach dir $access_path {
361
+ set token [PathToken $i]
362
+ lappend slave_access_path $token
363
+ lappend map_access_path $token $dir
364
+ lappend remap_access_path $dir $token
365
+ lappend norm_access_path [file normalize $dir]
366
+ incr i
367
+ }
368
+
369
+ set morepaths [::tcl::tm::list]
370
+ set firstpass 1
371
+ while {[llength $morepaths]} {
372
+ set addpaths $morepaths
373
+ set morepaths {}
374
+
375
+ foreach dir $addpaths {
376
+ # Prevent the addition of dirs on the tm list to the
377
+ # result if they are already known.
378
+ if {[dict exists $remap_access_path $dir]} {
379
+ if {$firstpass} {
380
+ # $dir is in [::tcl::tm::list] and belongs in the slave_tm_path.
381
+ # Later passes handle subdirectories, which belong in the
382
+ # access path but not in the module path.
383
+ lappend slave_tm_path [dict get $remap_access_path $dir]
384
+ }
385
+ continue
386
+ }
387
+
388
+ set token [PathToken $i]
389
+ lappend access_path $dir
390
+ lappend slave_access_path $token
391
+ lappend map_access_path $token $dir
392
+ lappend remap_access_path $dir $token
393
+ lappend norm_access_path [file normalize $dir]
394
+ if {$firstpass} {
395
+ # $dir is in [::tcl::tm::list] and belongs in the slave_tm_path.
396
+ # Later passes handle subdirectories, which belong in the
397
+ # access path but not in the module path.
398
+ lappend slave_tm_path $token
399
+ }
400
+ incr i
401
+
402
+ # [Bug 2854929]
403
+ # Recursively find deeper paths which may contain
404
+ # modules. Required to handle modules with names like
405
+ # 'platform::shell', which translate into
406
+ # 'platform/shell-X.tm', i.e arbitrarily deep
407
+ # subdirectories.
408
+ lappend morepaths {*}[glob -nocomplain -directory $dir -type d *]
409
+ }
410
+ set firstpass 0
411
+ }
412
+
413
+ set state(access_path) $access_path
414
+ set state(access_path,map) $map_access_path
415
+ set state(access_path,remap) $remap_access_path
416
+ set state(access_path,norm) $norm_access_path
417
+ set state(access_path,slave) $slave_access_path
418
+ set state(tm_path_slave) $slave_tm_path
419
+ set state(staticsok) $staticsok
420
+ set state(nestedok) $nestedok
421
+ set state(cleanupHook) $deletehook
422
+
423
+ SyncAccessPath $child
424
+ return
425
+ }
426
+
427
+ #
428
+ #
429
+ # FindInAccessPath:
430
+ # Search for a real directory and returns its virtual Id (including the
431
+ # "$")
432
+ proc ::safe::interpFindInAccessPath {child path} {
433
+ CheckInterp $child
434
+ namespace upvar ::safe [VarName $child] state
435
+
436
+ if {![dict exists $state(access_path,remap) $path]} {
437
+ return -code error "$path not found in access path"
438
+ }
439
+
440
+ return [dict get $state(access_path,remap) $path]
441
+ }
442
+
443
+ #
444
+ # addToAccessPath:
445
+ # add (if needed) a real directory to access path and return its
446
+ # virtual token (including the "$").
447
+ proc ::safe::interpAddToAccessPath {child path} {
448
+ # first check if the directory is already in there
449
+ # (inlined interpFindInAccessPath).
450
+ CheckInterp $child
451
+ namespace upvar ::safe [VarName $child] state
452
+
453
+ if {[dict exists $state(access_path,remap) $path]} {
454
+ return [dict get $state(access_path,remap) $path]
455
+ }
456
+
457
+ # new one, add it:
458
+ set token [PathToken [llength $state(access_path)]]
459
+
460
+ lappend state(access_path) $path
461
+ lappend state(access_path,slave) $token
462
+ lappend state(access_path,map) $token $path
463
+ lappend state(access_path,remap) $path $token
464
+ lappend state(access_path,norm) [file normalize $path]
465
+
466
+ SyncAccessPath $child
467
+ return $token
468
+ }
469
+
470
+ # This procedure applies the initializations to an already existing
471
+ # interpreter. It is useful when you want to install the safe base aliases
472
+ # into a preexisting safe interpreter.
473
+ proc ::safe::InterpInit {
474
+ child
475
+ access_path
476
+ staticsok
477
+ nestedok
478
+ deletehook
479
+ } {
480
+ # Configure will generate an access_path when access_path is empty.
481
+ InterpSetConfig $child $access_path $staticsok $nestedok $deletehook
482
+
483
+ # NB we need to add [namespace current], aliases are always absolute
484
+ # paths.
485
+
486
+ # These aliases let the child load files to define new commands
487
+ # This alias lets the child use the encoding names, convertfrom,
488
+ # convertto, and system, but not "encoding system <name>" to set the
489
+ # system encoding.
490
+ # Handling Tcl Modules, we need a restricted form of Glob.
491
+ # This alias interposes on the 'exit' command and cleanly terminates
492
+ # the child.
493
+
494
+ foreach {command alias} {
495
+ source AliasSource
496
+ load AliasLoad
497
+ encoding AliasEncoding
498
+ exit interpDelete
499
+ glob AliasGlob
500
+ } {
501
+ ::interp alias $child $command {} [namespace current]::$alias $child
502
+ }
503
+
504
+ # This alias lets the child have access to a subset of the 'file'
505
+ # command functionality.
506
+
507
+ ::interp expose $child file
508
+ foreach subcommand {dirname extension rootname tail} {
509
+ ::interp alias $child ::tcl::file::$subcommand {} \
510
+ ::safe::AliasFileSubcommand $child $subcommand
511
+ }
512
+ foreach subcommand {
513
+ atime attributes copy delete executable exists isdirectory isfile
514
+ link lstat mtime mkdir nativename normalize owned readable readlink
515
+ rename size stat tempfile type volumes writable
516
+ } {
517
+ ::interp alias $child ::tcl::file::$subcommand {} \
518
+ ::safe::BadSubcommand $child file $subcommand
519
+ }
520
+
521
+ # Subcommands of info
522
+ foreach {subcommand alias} {
523
+ nameofexecutable AliasExeName
524
+ } {
525
+ ::interp alias $child ::tcl::info::$subcommand \
526
+ {} [namespace current]::$alias $child
527
+ }
528
+
529
+ # The allowed child variables already have been set by Tcl_MakeSafe(3)
530
+
531
+ # Source init.tcl and tm.tcl into the child, to get auto_load and
532
+ # other procedures defined:
533
+
534
+ if {[catch {::interp eval $child {
535
+ source [file join $tcl_library init.tcl]
536
+ }} msg opt]} {
537
+ Log $child "can't source init.tcl ($msg)"
538
+ return -options $opt "can't source init.tcl into slave $child ($msg)"
539
+ }
540
+
541
+ if {[catch {::interp eval $child {
542
+ source [file join $tcl_library tm.tcl]
543
+ }} msg opt]} {
544
+ Log $child "can't source tm.tcl ($msg)"
545
+ return -options $opt "can't source tm.tcl into slave $child ($msg)"
546
+ }
547
+
548
+ # Sync the paths used to search for Tcl modules. This can be done only
549
+ # now, after tm.tcl was loaded.
550
+ namespace upvar ::safe [VarName $child] state
551
+ if {[llength $state(tm_path_slave)] > 0} {
552
+ ::interp eval $child [list \
553
+ ::tcl::tm::add {*}[lreverse $state(tm_path_slave)]]
554
+ }
555
+ return $child
556
+ }
557
+
558
+ # Add (only if needed, avoid duplicates) 1 level of sub directories to an
559
+ # existing path list. Also removes non directories from the returned
560
+ # list.
561
+ proc ::safe::AddSubDirs {pathList} {
562
+ set res {}
563
+ foreach dir $pathList {
564
+ if {[file isdirectory $dir]} {
565
+ # check that we don't have it yet as a children of a previous
566
+ # dir
567
+ if {$dir ni $res} {
568
+ lappend res $dir
569
+ }
570
+ foreach sub [glob -directory $dir -nocomplain *] {
571
+ if {[file isdirectory $sub] && ($sub ni $res)} {
572
+ # new sub dir, add it !
573
+ lappend res $sub
574
+ }
575
+ }
576
+ }
577
+ }
578
+ return $res
579
+ }
580
+
581
+ # This procedure deletes a safe interpreter managed by Safe Tcl and cleans up
582
+ # associated state.
583
+ # - The command will also delete non-Safe-Base interpreters.
584
+ # - This is regrettable, but to avoid breaking existing code this should be
585
+ # amended at the next major revision by uncommenting "CheckInterp".
586
+
587
+ proc ::safe::interpDelete {child} {
588
+ Log $child "About to delete" NOTICE
589
+
590
+ # CheckInterp $child
591
+ namespace upvar ::safe [VarName $child] state
592
+
593
+ # When an interpreter is deleted with [interp delete], any sub-interpreters
594
+ # are deleted automatically, but this leaves behind their data in the Safe
595
+ # Base. To clean up properly, we call safe::interpDelete recursively on each
596
+ # Safe Base sub-interpreter, so each one is deleted cleanly and not by
597
+ # the automatic mechanism built into [interp delete].
598
+ foreach sub [interp children $child] {
599
+ if {[info exists ::safe::[VarName [list $child $sub]]]} {
600
+ ::safe::interpDelete [list $child $sub]
601
+ }
602
+ }
603
+
604
+ # If the child has a cleanup hook registered, call it. Check the
605
+ # existence because we might be called to delete an interp which has
606
+ # not been registered with us at all
607
+
608
+ if {[info exists state(cleanupHook)]} {
609
+ set hook $state(cleanupHook)
610
+ if {[llength $hook]} {
611
+ # remove the hook now, otherwise if the hook calls us somehow,
612
+ # we'll loop
613
+ unset state(cleanupHook)
614
+ try {
615
+ {*}$hook $child
616
+ } on error err {
617
+ Log $child "Delete hook error ($err)"
618
+ }
619
+ }
620
+ }
621
+
622
+ # Discard the global array of state associated with the child, and
623
+ # delete the interpreter.
624
+
625
+ if {[info exists state]} {
626
+ unset state
627
+ }
628
+
629
+ # if we have been called twice, the interp might have been deleted
630
+ # already
631
+ if {[::interp exists $child]} {
632
+ ::interp delete $child
633
+ Log $child "Deleted" NOTICE
634
+ }
635
+
636
+ return
637
+ }
638
+
639
+ # Set (or get) the logging mechanism
640
+
641
+ proc ::safe::setLogCmd {args} {
642
+ variable Log
643
+ set la [llength $args]
644
+ if {$la == 0} {
645
+ return $Log
646
+ } elseif {$la == 1} {
647
+ set Log [lindex $args 0]
648
+ } else {
649
+ set Log $args
650
+ }
651
+
652
+ if {$Log eq ""} {
653
+ # Disable logging completely. Calls to it will be compiled out
654
+ # of all users.
655
+ proc ::safe::Log {args} {}
656
+ } else {
657
+ # Activate logging, define proper command.
658
+
659
+ proc ::safe::Log {child msg {type ERROR}} {
660
+ variable Log
661
+ {*}$Log "$type for slave $child : $msg"
662
+ return
663
+ }
664
+ }
665
+ }
666
+
667
+ # ------------------- END OF PUBLIC METHODS ------------
668
+
669
+ #
670
+ # Sets the child auto_path to the parent recorded value. Also sets
671
+ # tcl_library to the first token of the virtual path.
672
+ #
673
+ proc ::safe::SyncAccessPath {child} {
674
+ namespace upvar ::safe [VarName $child] state
675
+
676
+ set slave_access_path $state(access_path,slave)
677
+ ::interp eval $child [list set auto_path $slave_access_path]
678
+
679
+ Log $child "auto_path in $child has been set to $slave_access_path"\
680
+ NOTICE
681
+
682
+ # This code assumes that info library is the first element in the
683
+ # list of auto_path's. See -> InterpSetConfig for the code which
684
+ # ensures this condition.
685
+
686
+ ::interp eval $child [list \
687
+ set tcl_library [lindex $slave_access_path 0]]
688
+ }
689
+
690
+ # Returns the virtual token for directory number N.
691
+ proc ::safe::PathToken {n} {
692
+ # We need to have a ":" in the token string so [file join] on the
693
+ # mac won't turn it into a relative path.
694
+ return "\$p(:$n:)" ;# Form tested by case 7.2
695
+ }
696
+
697
+ #
698
+ # translate virtual path into real path
699
+ #
700
+ proc ::safe::TranslatePath {child path} {
701
+ namespace upvar ::safe [VarName $child] state
702
+
703
+ # somehow strip the namespaces 'functionality' out (the danger is that
704
+ # we would strip valid macintosh "../" queries... :
705
+ if {[string match "*::*" $path] || [string match "*..*" $path]} {
706
+ return -code error "invalid characters in path $path"
707
+ }
708
+
709
+ # Use a cached map instead of computed local vars and subst.
710
+
711
+ return [string map $state(access_path,map) $path]
712
+ }
713
+
714
+ # file name control (limit access to files/resources that should be a
715
+ # valid tcl source file)
716
+ proc ::safe::CheckFileName {child file} {
717
+ # This used to limit what can be sourced to ".tcl" and forbid files
718
+ # with more than 1 dot and longer than 14 chars, but I changed that
719
+ # for 8.4 as a safe interp has enough internal protection already to
720
+ # allow sourcing anything. - hobbs
721
+
722
+ if {![file exists $file]} {
723
+ # don't tell the file path
724
+ return -code error "no such file or directory"
725
+ }
726
+
727
+ if {![file readable $file]} {
728
+ # don't tell the file path
729
+ return -code error "not readable"
730
+ }
731
+ }
732
+
733
+ # AliasFileSubcommand handles selected subcommands of [file] in safe
734
+ # interpreters that are *almost* safe. In particular, it just acts to
735
+ # prevent discovery of what home directories exist.
736
+
737
+ proc ::safe::AliasFileSubcommand {child subcommand name} {
738
+ if {[string match ~* $name]} {
739
+ set name ./$name
740
+ }
741
+ tailcall ::interp invokehidden $child tcl:file:$subcommand $name
742
+ }
743
+
744
+ # AliasGlob is the target of the "glob" alias in safe interpreters.
745
+
746
+ proc ::safe::AliasGlob {child args} {
747
+ Log $child "GLOB ! $args" NOTICE
748
+ set cmd {}
749
+ set at 0
750
+ array set got {
751
+ -directory 0
752
+ -nocomplain 0
753
+ -join 0
754
+ -tails 0
755
+ -- 0
756
+ }
757
+
758
+ if {$::tcl_platform(platform) eq "windows"} {
759
+ set dirPartRE {^(.*)[\\/]([^\\/]*)$}
760
+ } else {
761
+ set dirPartRE {^(.*)/([^/]*)$}
762
+ }
763
+
764
+ set dir {}
765
+ set virtualdir {}
766
+
767
+ while {$at < [llength $args]} {
768
+ switch -glob -- [set opt [lindex $args $at]] {
769
+ -nocomplain - -- - -tails {
770
+ lappend cmd $opt
771
+ set got($opt) 1
772
+ incr at
773
+ }
774
+ -join {
775
+ set got($opt) 1
776
+ incr at
777
+ }
778
+ -types - -type {
779
+ lappend cmd -types [lindex $args [incr at]]
780
+ incr at
781
+ }
782
+ -directory {
783
+ if {$got($opt)} {
784
+ return -code error \
785
+ {"-directory" cannot be used with "-path"}
786
+ }
787
+ set got($opt) 1
788
+ set virtualdir [lindex $args [incr at]]
789
+ incr at
790
+ }
791
+ -* {
792
+ Log $child "Safe base rejecting glob option '$opt'"
793
+ return -code error "Safe base rejecting glob option '$opt'"
794
+ }
795
+ default {
796
+ break
797
+ }
798
+ }
799
+ if {$got(--)} break
800
+ }
801
+
802
+ # Get the real path from the virtual one and check that the path is in the
803
+ # access path of that child. Done after basic argument processing so that
804
+ # we know if -nocomplain is set.
805
+ if {$got(-directory)} {
806
+ try {
807
+ set dir [TranslatePath $child $virtualdir]
808
+ DirInAccessPath $child $dir
809
+ } on error msg {
810
+ Log $child $msg
811
+ if {$got(-nocomplain)} return
812
+ return -code error "permission denied"
813
+ }
814
+ if {$got(--)} {
815
+ set cmd [linsert $cmd end-1 -directory $dir]
816
+ } else {
817
+ lappend cmd -directory $dir
818
+ }
819
+ } else {
820
+ # The code after this "if ... else" block would conspire to return with
821
+ # no results in this case, if it were allowed to proceed. Instead,
822
+ # return now and reduce the number of cases to be considered later.
823
+ Log $child {option -directory must be supplied}
824
+ if {$got(-nocomplain)} return
825
+ return -code error "permission denied"
826
+ }
827
+
828
+ # Apply the -join semantics ourselves.
829
+ if {$got(-join)} {
830
+ set args [lreplace $args $at end [join [lrange $args $at end] "/"]]
831
+ }
832
+
833
+ # Process the pattern arguments. If we've done a join there is only one
834
+ # pattern argument.
835
+
836
+ set firstPattern [llength $cmd]
837
+ foreach opt [lrange $args $at end] {
838
+ if {![regexp $dirPartRE $opt -> thedir thefile]} {
839
+ set thedir .
840
+ # The *.tm search comes here.
841
+ }
842
+ # "Special" treatment for (joined) argument {*/pkgIndex.tcl}.
843
+ # Do the expansion of "*" here, and filter out any directories that are
844
+ # not in the access path. The outcome is to lappend to cmd a path of
845
+ # the form $virtualdir/subdir/pkgIndex.tcl for each subdirectory subdir,
846
+ # after removing any subdir that are not in the access path.
847
+ if {($thedir eq "*") && ($thefile eq "pkgIndex.tcl")} {
848
+ set mapped 0
849
+ foreach d [glob -directory [TranslatePath $child $virtualdir] \
850
+ -types d -tails *] {
851
+ catch {
852
+ DirInAccessPath $child \
853
+ [TranslatePath $child [file join $virtualdir $d]]
854
+ lappend cmd [file join $d $thefile]
855
+ set mapped 1
856
+ }
857
+ }
858
+ if {$mapped} continue
859
+ # Don't [continue] if */pkgIndex.tcl has no matches in the access
860
+ # path. The pattern will now receive the same treatment as a
861
+ # "non-special" pattern (and will fail because it includes a "*" in
862
+ # the directory name).
863
+ }
864
+ # Any directory pattern that is not an exact (i.e. non-glob) match to a
865
+ # directory in the access path will be rejected here.
866
+ # - Rejections include any directory pattern that has glob matching
867
+ # patterns "*", "?", backslashes, braces or square brackets, (UNLESS
868
+ # it corresponds to a genuine directory name AND that directory is in
869
+ # the access path).
870
+ # - The only "special matching characters" that remain in patterns for
871
+ # processing by glob are in the filename tail.
872
+ # - [file join $anything ~${foo}] is ~${foo}, which is not an exact
873
+ # match to any directory in the access path. Hence directory patterns
874
+ # that begin with "~" are rejected here. Tests safe-16.[5-8] check
875
+ # that "file join" remains as required and does not expand ~${foo}.
876
+ # - Bug [3529949] relates to unwanted expansion of ~${foo} and this is
877
+ # how the present code avoids the bug. All tests safe-16.* relate.
878
+ try {
879
+ DirInAccessPath $child [TranslatePath $child \
880
+ [file join $virtualdir $thedir]]
881
+ } on error msg {
882
+ Log $child $msg
883
+ if {$got(-nocomplain)} continue
884
+ return -code error "permission denied"
885
+ }
886
+ lappend cmd $opt
887
+ }
888
+
889
+ Log $child "GLOB = $cmd" NOTICE
890
+
891
+ if {$got(-nocomplain) && [llength $cmd] eq $firstPattern} {
892
+ return
893
+ }
894
+ try {
895
+ # >>>>>>>>>> HERE'S THE CALL TO SAFE INTERP GLOB <<<<<<<<<<
896
+ # - Pattern arguments added to cmd have NOT been translated from tokens.
897
+ # Only the virtualdir is translated (to dir).
898
+ # - In the pkgIndex.tcl case, there is no "*" in the pattern arguments,
899
+ # which are a list of names each with tail pkgIndex.tcl. The purpose
900
+ # of the call to glob is to remove the names for which the file does
901
+ # not exist.
902
+ set entries [::interp invokehidden $child glob {*}$cmd]
903
+ } on error msg {
904
+ # This is the only place that a call with -nocomplain and no invalid
905
+ # "dash-options" can return an error.
906
+ Log $child $msg
907
+ return -code error "script error"
908
+ }
909
+
910
+ Log $child "GLOB < $entries" NOTICE
911
+
912
+ # Translate path back to what the child should see.
913
+ set res {}
914
+ set l [string length $dir]
915
+ foreach p $entries {
916
+ if {[string equal -length $l $dir $p]} {
917
+ set p [string replace $p 0 [expr {$l-1}] $virtualdir]
918
+ }
919
+ lappend res $p
920
+ }
921
+
922
+ Log $child "GLOB > $res" NOTICE
923
+ return $res
924
+ }
925
+
926
+ # AliasSource is the target of the "source" alias in safe interpreters.
927
+
928
+ proc ::safe::AliasSource {child args} {
929
+ set argc [llength $args]
930
+ # Extended for handling of Tcl Modules to allow not only "source
931
+ # filename", but "source -encoding E filename" as well.
932
+ if {[lindex $args 0] eq "-encoding"} {
933
+ incr argc -2
934
+ set encoding [lindex $args 1]
935
+ set at 2
936
+ if {$encoding eq "identity"} {
937
+ Log $child "attempt to use the identity encoding"
938
+ return -code error "permission denied"
939
+ }
940
+ } else {
941
+ set at 0
942
+ set encoding {}
943
+ }
944
+ if {$argc != 1} {
945
+ set msg "wrong # args: should be \"source ?-encoding E? fileName\""
946
+ Log $child "$msg ($args)"
947
+ return -code error $msg
948
+ }
949
+ set file [lindex $args $at]
950
+
951
+ # get the real path from the virtual one.
952
+ if {[catch {
953
+ set realfile [TranslatePath $child $file]
954
+ } msg]} {
955
+ Log $child $msg
956
+ return -code error "permission denied"
957
+ }
958
+
959
+ # check that the path is in the access path of that child
960
+ if {[catch {
961
+ FileInAccessPath $child $realfile
962
+ } msg]} {
963
+ Log $child $msg
964
+ return -code error "permission denied"
965
+ }
966
+
967
+ # Check that the filename exists and is readable. If it is not, deliver
968
+ # this -errorcode so that caller in tclPkgUnknown does not write a message
969
+ # to tclLog. Has no effect on other callers of ::source, which are in
970
+ # "package ifneeded" scripts.
971
+ if {[catch {
972
+ CheckFileName $child $realfile
973
+ } msg]} {
974
+ Log $child "$realfile:$msg"
975
+ return -code error -errorcode {POSIX EACCES} $msg
976
+ }
977
+
978
+ # Passed all the tests, lets source it. Note that we do this all manually
979
+ # because we want to control [info script] in the child so information
980
+ # doesn't leak so much. [Bug 2913625]
981
+ set old [::interp eval $child {info script}]
982
+ set replacementMsg "script error"
983
+ set code [catch {
984
+ set f [open $realfile]
985
+ fconfigure $f -eofchar "\x1A {}"
986
+ if {$encoding ne ""} {
987
+ fconfigure $f -encoding $encoding
988
+ }
989
+ set contents [read $f]
990
+ close $f
991
+ ::interp eval $child [list info script $file]
992
+ } msg opt]
993
+ if {$code == 0} {
994
+ set code [catch {::interp eval $child $contents} msg opt]
995
+ set replacementMsg $msg
996
+ }
997
+ catch {interp eval $child [list info script $old]}
998
+ # Note that all non-errors are fine result codes from [source], so we must
999
+ # take a little care to do it properly. [Bug 2923613]
1000
+ if {$code == 1} {
1001
+ Log $child $msg
1002
+ return -code error $replacementMsg
1003
+ }
1004
+ return -code $code -options $opt $msg
1005
+ }
1006
+
1007
+ # AliasLoad is the target of the "load" alias in safe interpreters.
1008
+
1009
+ proc ::safe::AliasLoad {child file args} {
1010
+ set argc [llength $args]
1011
+ if {$argc > 2} {
1012
+ set msg "load error: too many arguments"
1013
+ Log $child "$msg ($argc) {$file $args}"
1014
+ return -code error $msg
1015
+ }
1016
+
1017
+ # package name (can be empty if file is not).
1018
+ set package [lindex $args 0]
1019
+
1020
+ namespace upvar ::safe [VarName $child] state
1021
+
1022
+ # Determine where to load. load use a relative interp path and {}
1023
+ # means self, so we can directly and safely use passed arg.
1024
+ set target [lindex $args 1]
1025
+ if {$target ne ""} {
1026
+ # we will try to load into a sub sub interp; check that we want to
1027
+ # authorize that.
1028
+ if {!$state(nestedok)} {
1029
+ Log $child "loading to a sub interp (nestedok)\
1030
+ disabled (trying to load $package to $target)"
1031
+ return -code error "permission denied (nested load)"
1032
+ }
1033
+ }
1034
+
1035
+ # Determine what kind of load is requested
1036
+ if {$file eq ""} {
1037
+ # static package loading
1038
+ if {$package eq ""} {
1039
+ set msg "load error: empty filename and no package name"
1040
+ Log $child $msg
1041
+ return -code error $msg
1042
+ }
1043
+ if {!$state(staticsok)} {
1044
+ Log $child "static packages loading disabled\
1045
+ (trying to load $package to $target)"
1046
+ return -code error "permission denied (static package)"
1047
+ }
1048
+ } else {
1049
+ # file loading
1050
+
1051
+ # get the real path from the virtual one.
1052
+ try {
1053
+ set file [TranslatePath $child $file]
1054
+ } on error msg {
1055
+ Log $child $msg
1056
+ return -code error "permission denied"
1057
+ }
1058
+
1059
+ # check the translated path
1060
+ try {
1061
+ FileInAccessPath $child $file
1062
+ } on error msg {
1063
+ Log $child $msg
1064
+ return -code error "permission denied (path)"
1065
+ }
1066
+ }
1067
+
1068
+ try {
1069
+ return [::interp invokehidden $child load $file $package $target]
1070
+ } on error msg {
1071
+ # Some packages return no error message.
1072
+ set msg0 "load of binary library for package $package failed"
1073
+ if {$msg eq {}} {
1074
+ set msg $msg0
1075
+ } else {
1076
+ set msg "$msg0: $msg"
1077
+ }
1078
+ Log $child $msg
1079
+ return -code error $msg
1080
+ }
1081
+ }
1082
+
1083
+ # FileInAccessPath raises an error if the file is not found in the list of
1084
+ # directories contained in the (parent side recorded) child's access path.
1085
+
1086
+ # the security here relies on "file dirname" answering the proper
1087
+ # result... needs checking ?
1088
+ proc ::safe::FileInAccessPath {child file} {
1089
+ namespace upvar ::safe [VarName $child] state
1090
+ set access_path $state(access_path)
1091
+
1092
+ if {[file isdirectory $file]} {
1093
+ return -code error "\"$file\": is a directory"
1094
+ }
1095
+ set parent [file dirname $file]
1096
+
1097
+ # Normalize paths for comparison since lsearch knows nothing of
1098
+ # potential pathname anomalies.
1099
+ set norm_parent [file normalize $parent]
1100
+
1101
+ namespace upvar ::safe [VarName $child] state
1102
+ if {$norm_parent ni $state(access_path,norm)} {
1103
+ return -code error "\"$file\": not in access_path"
1104
+ }
1105
+ }
1106
+
1107
+ proc ::safe::DirInAccessPath {child dir} {
1108
+ namespace upvar ::safe [VarName $child] state
1109
+ set access_path $state(access_path)
1110
+
1111
+ if {[file isfile $dir]} {
1112
+ return -code error "\"$dir\": is a file"
1113
+ }
1114
+
1115
+ # Normalize paths for comparison since lsearch knows nothing of
1116
+ # potential pathname anomalies.
1117
+ set norm_dir [file normalize $dir]
1118
+
1119
+ namespace upvar ::safe [VarName $child] state
1120
+ if {$norm_dir ni $state(access_path,norm)} {
1121
+ return -code error "\"$dir\": not in access_path"
1122
+ }
1123
+ }
1124
+
1125
+ # This procedure is used to report an attempt to use an unsafe member of an
1126
+ # ensemble command.
1127
+
1128
+ proc ::safe::BadSubcommand {child command subcommand args} {
1129
+ set msg "not allowed to invoke subcommand $subcommand of $command"
1130
+ Log $child $msg
1131
+ return -code error -errorcode {TCL SAFE SUBCOMMAND} $msg
1132
+ }
1133
+
1134
+ # AliasEncoding is the target of the "encoding" alias in safe interpreters.
1135
+
1136
+ proc ::safe::AliasEncoding {child option args} {
1137
+ # Note that [encoding dirs] is not supported in safe children at all
1138
+ set subcommands {convertfrom convertto names system}
1139
+ try {
1140
+ set option [tcl::prefix match -error [list -level 1 -errorcode \
1141
+ [list TCL LOOKUP INDEX option $option]] $subcommands $option]
1142
+ # Special case: [encoding system] ok, but [encoding system foo] not
1143
+ if {$option eq "system" && [llength $args]} {
1144
+ return -code error -errorcode {TCL WRONGARGS} \
1145
+ "wrong # args: should be \"encoding system\""
1146
+ }
1147
+ } on error {msg options} {
1148
+ Log $child $msg
1149
+ return -options $options $msg
1150
+ }
1151
+ tailcall ::interp invokehidden $child encoding $option {*}$args
1152
+ }
1153
+
1154
+ # Various minor hiding of platform features. [Bug 2913625]
1155
+
1156
+ proc ::safe::AliasExeName {child} {
1157
+ return ""
1158
+ }
1159
+
1160
+ # ------------------------------------------------------------------------------
1161
+ # Using Interpreter Names with Namespace Qualifiers
1162
+ # ------------------------------------------------------------------------------
1163
+ # (1) We wish to preserve compatibility with existing code, in which Safe Base
1164
+ # interpreter names have no namespace qualifiers.
1165
+ # (2) safe::interpCreate and the rest of the Safe Base previously could not
1166
+ # accept namespace qualifiers in an interpreter name.
1167
+ # (3) The interp command will accept namespace qualifiers in an interpreter
1168
+ # name, but accepts distinct interpreters that will have the same command
1169
+ # name (e.g. foo, ::foo, and :::foo) (bug 66c2e8c974).
1170
+ # (4) To satisfy these constraints, Safe Base interpreter names will be fully
1171
+ # qualified namespace names with no excess colons and with the leading "::"
1172
+ # omitted.
1173
+ # (5) Trailing "::" implies a namespace tail {}, which interp reads as {{}}.
1174
+ # Reject such names.
1175
+ # (6) We could:
1176
+ # (a) EITHER reject usable but non-compliant names (e.g. excess colons) in
1177
+ # interpCreate, interpInit;
1178
+ # (b) OR accept such names and then translate to a compliant name in every
1179
+ # command.
1180
+ # The problem with (b) is that the user will expect to use the name with the
1181
+ # interp command and will find that it is not recognised.
1182
+ # E.g "interpCreate ::foo" creates interpreter "foo", and the user's name
1183
+ # "::foo" works with all the Safe Base commands, but "interp eval ::foo"
1184
+ # fails.
1185
+ # So we choose (a).
1186
+ # (7) The command
1187
+ # namespace upvar ::safe S$child state
1188
+ # becomes
1189
+ # namespace upvar ::safe [VarName $child] state
1190
+ # ------------------------------------------------------------------------------
1191
+
1192
+ proc ::safe::RejectExcessColons {child} {
1193
+ set stripped [regsub -all -- {:::*} $child ::]
1194
+ if {[string range $stripped end-1 end] eq {::}} {
1195
+ return -code error {interpreter name must not end in "::"}
1196
+ }
1197
+ if {$stripped ne $child} {
1198
+ set msg {interpreter name has excess colons in namespace separators}
1199
+ return -code error $msg
1200
+ }
1201
+ if {[string range $stripped 0 1] eq {::}} {
1202
+ return -code error {interpreter name must not begin "::"}
1203
+ }
1204
+ return
1205
+ }
1206
+
1207
+ proc ::safe::VarName {child} {
1208
+ # return S$child
1209
+ return S[string map {:: @N @ @A} $child]
1210
+ }
1211
+
1212
+ proc ::safe::Setup {} {
1213
+ ####
1214
+ #
1215
+ # Setup the arguments parsing
1216
+ #
1217
+ ####
1218
+
1219
+ # Share the descriptions
1220
+ set temp [::tcl::OptKeyRegister {
1221
+ {-accessPath -list {} "access path for the slave"}
1222
+ {-noStatics "prevent loading of statically linked pkgs"}
1223
+ {-statics true "loading of statically linked pkgs"}
1224
+ {-nestedLoadOk "allow nested loading"}
1225
+ {-nested false "nested loading"}
1226
+ {-deleteHook -script {} "delete hook"}
1227
+ }]
1228
+
1229
+ # create case (slave is optional)
1230
+ ::tcl::OptKeyRegister {
1231
+ {?slave? -name {} "name of the slave (optional)"}
1232
+ } ::safe::interpCreate
1233
+
1234
+ # adding the flags sub programs to the command program (relying on Opt's
1235
+ # internal implementation details)
1236
+ lappend ::tcl::OptDesc(::safe::interpCreate) $::tcl::OptDesc($temp)
1237
+
1238
+ # init and configure (slave is needed)
1239
+ ::tcl::OptKeyRegister {
1240
+ {slave -name {} "name of the slave"}
1241
+ } ::safe::interpIC
1242
+
1243
+ # adding the flags sub programs to the command program (relying on Opt's
1244
+ # internal implementation details)
1245
+ lappend ::tcl::OptDesc(::safe::interpIC) $::tcl::OptDesc($temp)
1246
+
1247
+ # temp not needed anymore
1248
+ ::tcl::OptKeyDelete $temp
1249
+
1250
+ ####
1251
+ #
1252
+ # Default: No logging.
1253
+ #
1254
+ ####
1255
+
1256
+ setLogCmd {}
1257
+
1258
+ # Log eventually.
1259
+ # To enable error logging, set Log to {puts stderr} for instance,
1260
+ # via setLogCmd.
1261
+ return
1262
+ }
1263
+
1264
+ namespace eval ::safe {
1265
+ # internal variables
1266
+
1267
+ # Log command, set via 'setLogCmd'. Logging is disabled when empty.
1268
+ variable Log {}
1269
+
1270
+ # The package maintains a state array per child interp under its
1271
+ # control. The name of this array is S<interp-name>. This array is
1272
+ # brought into scope where needed, using 'namespace upvar'. The S
1273
+ # prefix is used to avoid that a child interp called "Log" smashes
1274
+ # the "Log" variable.
1275
+ #
1276
+ # The array's elements are:
1277
+ #
1278
+ # access_path : List of paths accessible to the child.
1279
+ # access_path,norm : Ditto, in normalized form.
1280
+ # access_path,slave : Ditto, as the path tokens as seen by the child.
1281
+ # access_path,map : dict ( token -> path )
1282
+ # access_path,remap : dict ( path -> token )
1283
+ # tm_path_slave : List of TM root directories, as tokens seen by the child.
1284
+ # staticsok : Value of option -statics
1285
+ # nestedok : Value of option -nested
1286
+ # cleanupHook : Value of option -deleteHook
1287
+ }
1288
+
1289
+ ::safe::Setup
lib/tcl8.6/tclAppInit.c ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * tclAppInit.c --
3
+ *
4
+ * Provides a default version of the main program and Tcl_AppInit
5
+ * procedure for tclsh and other Tcl-based applications (without Tk).
6
+ *
7
+ * Copyright (c) 1993 The Regents of the University of California.
8
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
9
+ * Copyright (c) 1998-1999 Scriptics Corporation.
10
+ *
11
+ * See the file "license.terms" for information on usage and redistribution of
12
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
+ */
14
+
15
+ #undef BUILD_tcl
16
+ #undef STATIC_BUILD
17
+ #include "tcl.h"
18
+ #if TCL_MAJOR_VERSION < 9 && TCL_MINOR_VERSION < 7
19
+ # define Tcl_LibraryInitProc Tcl_PackageInitProc
20
+ # define Tcl_StaticLibrary Tcl_StaticPackage
21
+ #endif
22
+
23
+ #ifdef TCL_TEST
24
+ extern Tcl_LibraryInitProc Tcltest_Init;
25
+ extern Tcl_LibraryInitProc Tcltest_SafeInit;
26
+ #endif /* TCL_TEST */
27
+
28
+ #ifdef TCL_XT_TEST
29
+ extern void XtToolkitInitialize(void);
30
+ extern Tcl_LibraryInitProc Tclxttest_Init;
31
+ #endif /* TCL_XT_TEST */
32
+
33
+ /*
34
+ * The following #if block allows you to change the AppInit function by using
35
+ * a #define of TCL_LOCAL_APPINIT instead of rewriting this entire file. The
36
+ * #if checks for that #define and uses Tcl_AppInit if it does not exist.
37
+ */
38
+
39
+ #ifndef TCL_LOCAL_APPINIT
40
+ #define TCL_LOCAL_APPINIT Tcl_AppInit
41
+ #endif
42
+ #ifndef MODULE_SCOPE
43
+ # define MODULE_SCOPE extern
44
+ #endif
45
+ MODULE_SCOPE int TCL_LOCAL_APPINIT(Tcl_Interp *);
46
+ MODULE_SCOPE int main(int, char **);
47
+
48
+ /*
49
+ * The following #if block allows you to change how Tcl finds the startup
50
+ * script, prime the library or encoding paths, fiddle with the argv, etc.,
51
+ * without needing to rewrite Tcl_Main()
52
+ */
53
+
54
+ #ifdef TCL_LOCAL_MAIN_HOOK
55
+ MODULE_SCOPE int TCL_LOCAL_MAIN_HOOK(int *argc, char ***argv);
56
+ #endif
57
+
58
+ /*
59
+ *----------------------------------------------------------------------
60
+ *
61
+ * main --
62
+ *
63
+ * This is the main program for the application.
64
+ *
65
+ * Results:
66
+ * None: Tcl_Main never returns here, so this procedure never returns
67
+ * either.
68
+ *
69
+ * Side effects:
70
+ * Just about anything, since from here we call arbitrary Tcl code.
71
+ *
72
+ *----------------------------------------------------------------------
73
+ */
74
+
75
+ int
76
+ main(
77
+ int argc, /* Number of command-line arguments. */
78
+ char *argv[]) /* Values of command-line arguments. */
79
+ {
80
+ #ifdef TCL_XT_TEST
81
+ XtToolkitInitialize();
82
+ #endif
83
+
84
+ #ifdef TCL_LOCAL_MAIN_HOOK
85
+ TCL_LOCAL_MAIN_HOOK(&argc, &argv);
86
+ #elif (TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6) && (!defined(_WIN32) || defined(UNICODE))
87
+ /* New in Tcl 8.7. This doesn't work on Windows without UNICODE */
88
+ TclZipfs_AppHook(&argc, &argv);
89
+ #endif
90
+
91
+ Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
92
+ return 0; /* Needed only to prevent compiler warning. */
93
+ }
94
+
95
+ /*
96
+ *----------------------------------------------------------------------
97
+ *
98
+ * Tcl_AppInit --
99
+ *
100
+ * This procedure performs application-specific initialization. Most
101
+ * applications, especially those that incorporate additional packages,
102
+ * will have their own version of this procedure.
103
+ *
104
+ * Results:
105
+ * Returns a standard Tcl completion code, and leaves an error message in
106
+ * the interp's result if an error occurs.
107
+ *
108
+ * Side effects:
109
+ * Depends on the startup script.
110
+ *
111
+ *----------------------------------------------------------------------
112
+ */
113
+
114
+ int
115
+ Tcl_AppInit(
116
+ Tcl_Interp *interp) /* Interpreter for application. */
117
+ {
118
+ if ((Tcl_Init)(interp) == TCL_ERROR) {
119
+ return TCL_ERROR;
120
+ }
121
+
122
+ #ifdef TCL_XT_TEST
123
+ if (Tclxttest_Init(interp) == TCL_ERROR) {
124
+ return TCL_ERROR;
125
+ }
126
+ #endif
127
+
128
+ #ifdef TCL_TEST
129
+ if (Tcltest_Init(interp) == TCL_ERROR) {
130
+ return TCL_ERROR;
131
+ }
132
+ Tcl_StaticLibrary(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit);
133
+ #endif /* TCL_TEST */
134
+
135
+ /*
136
+ * Call the init procedures for included packages. Each call should look
137
+ * like this:
138
+ *
139
+ * if (Mod_Init(interp) == TCL_ERROR) {
140
+ * return TCL_ERROR;
141
+ * }
142
+ *
143
+ * where "Mod" is the name of the module. (Dynamically-loadable packages
144
+ * should have the same entry-point name.)
145
+ */
146
+
147
+ /*
148
+ * Call Tcl_CreateCommand for application-specific commands, if they
149
+ * weren't already created by the init procedures called above.
150
+ */
151
+
152
+ /*
153
+ * Specify a user-specific startup file to invoke if the application is
154
+ * run interactively. Typically the startup file is "~/.apprc" where "app"
155
+ * is the name of the application. If this line is deleted then no
156
+ * user-specific startup file will be run under any conditions.
157
+ */
158
+
159
+ #ifdef DJGPP
160
+ (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,
161
+ Tcl_NewStringObj("~/tclsh.rc", -1), TCL_GLOBAL_ONLY);
162
+ #else
163
+ (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,
164
+ Tcl_NewStringObj("~/.tclshrc", -1), TCL_GLOBAL_ONLY);
165
+ #endif
166
+
167
+ return TCL_OK;
168
+ }
169
+
170
+ /*
171
+ * Local Variables:
172
+ * mode: c
173
+ * c-basic-offset: 4
174
+ * fill-column: 78
175
+ * End:
176
+ */
lib/tcl8.6/tclIndex ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Tcl autoload index file, version 2.0
2
+ # -*- tcl -*-
3
+ # This file is generated by the "auto_mkindex" command
4
+ # and sourced to set up indexing information for one or
5
+ # more commands. Typically each line is a command that
6
+ # sets an element in the auto_index array, where the
7
+ # element name is the name of a command and the value is
8
+ # a script that loads the command.
9
+
10
+ set auto_index(auto_reset) [list source [file join $dir auto.tcl]]
11
+ set auto_index(tcl_findLibrary) [list source [file join $dir auto.tcl]]
12
+ set auto_index(auto_mkindex) [list source [file join $dir auto.tcl]]
13
+ set auto_index(auto_mkindex_old) [list source [file join $dir auto.tcl]]
14
+ set auto_index(::auto_mkindex_parser::init) [list source [file join $dir auto.tcl]]
15
+ set auto_index(::auto_mkindex_parser::cleanup) [list source [file join $dir auto.tcl]]
16
+ set auto_index(::auto_mkindex_parser::mkindex) [list source [file join $dir auto.tcl]]
17
+ set auto_index(::auto_mkindex_parser::hook) [list source [file join $dir auto.tcl]]
18
+ set auto_index(::auto_mkindex_parser::slavehook) [list source [file join $dir auto.tcl]]
19
+ set auto_index(::auto_mkindex_parser::command) [list source [file join $dir auto.tcl]]
20
+ set auto_index(::auto_mkindex_parser::commandInit) [list source [file join $dir auto.tcl]]
21
+ set auto_index(::auto_mkindex_parser::fullname) [list source [file join $dir auto.tcl]]
22
+ set auto_index(history) [list source [file join $dir history.tcl]]
23
+ set auto_index(::tcl::history) [list source [file join $dir history.tcl]]
24
+ set auto_index(::tcl::HistAdd) [list source [file join $dir history.tcl]]
25
+ set auto_index(::tcl::HistKeep) [list source [file join $dir history.tcl]]
26
+ set auto_index(::tcl::HistClear) [list source [file join $dir history.tcl]]
27
+ set auto_index(::tcl::HistInfo) [list source [file join $dir history.tcl]]
28
+ set auto_index(::tcl::HistRedo) [list source [file join $dir history.tcl]]
29
+ set auto_index(::tcl::HistIndex) [list source [file join $dir history.tcl]]
30
+ set auto_index(::tcl::HistEvent) [list source [file join $dir history.tcl]]
31
+ set auto_index(::tcl::HistChange) [list source [file join $dir history.tcl]]
32
+ set auto_index(pkg_mkIndex) [list source [file join $dir package.tcl]]
33
+ set auto_index(tclPkgSetup) [list source [file join $dir package.tcl]]
34
+ set auto_index(tclPkgUnknown) [list source [file join $dir package.tcl]]
35
+ set auto_index(::tcl::MacOSXPkgUnknown) [list source [file join $dir package.tcl]]
36
+ set auto_index(::pkg::create) [list source [file join $dir package.tcl]]
37
+ set auto_index(parray) [list source [file join $dir parray.tcl]]
38
+ set auto_index(::safe::InterpStatics) [list source [file join $dir safe.tcl]]
39
+ set auto_index(::safe::InterpNested) [list source [file join $dir safe.tcl]]
40
+ set auto_index(::safe::interpCreate) [list source [file join $dir safe.tcl]]
41
+ set auto_index(::safe::interpInit) [list source [file join $dir safe.tcl]]
42
+ set auto_index(::safe::CheckInterp) [list source [file join $dir safe.tcl]]
43
+ set auto_index(::safe::interpConfigure) [list source [file join $dir safe.tcl]]
44
+ set auto_index(::safe::InterpCreate) [list source [file join $dir safe.tcl]]
45
+ set auto_index(::safe::InterpSetConfig) [list source [file join $dir safe.tcl]]
46
+ set auto_index(::safe::interpFindInAccessPath) [list source [file join $dir safe.tcl]]
47
+ set auto_index(::safe::interpAddToAccessPath) [list source [file join $dir safe.tcl]]
48
+ set auto_index(::safe::InterpInit) [list source [file join $dir safe.tcl]]
49
+ set auto_index(::safe::AddSubDirs) [list source [file join $dir safe.tcl]]
50
+ set auto_index(::safe::interpDelete) [list source [file join $dir safe.tcl]]
51
+ set auto_index(::safe::setLogCmd) [list source [file join $dir safe.tcl]]
52
+ set auto_index(::safe::SyncAccessPath) [list source [file join $dir safe.tcl]]
53
+ set auto_index(::safe::PathToken) [list source [file join $dir safe.tcl]]
54
+ set auto_index(::safe::TranslatePath) [list source [file join $dir safe.tcl]]
55
+ set auto_index(::safe::Log) [list source [file join $dir safe.tcl]]
56
+ set auto_index(::safe::CheckFileName) [list source [file join $dir safe.tcl]]
57
+ set auto_index(::safe::AliasGlob) [list source [file join $dir safe.tcl]]
58
+ set auto_index(::safe::AliasSource) [list source [file join $dir safe.tcl]]
59
+ set auto_index(::safe::AliasLoad) [list source [file join $dir safe.tcl]]
60
+ set auto_index(::safe::FileInAccessPath) [list source [file join $dir safe.tcl]]
61
+ set auto_index(::safe::DirInAccessPath) [list source [file join $dir safe.tcl]]
62
+ set auto_index(::safe::Subset) [list source [file join $dir safe.tcl]]
63
+ set auto_index(::safe::AliasSubset) [list source [file join $dir safe.tcl]]
64
+ set auto_index(::safe::AliasEncoding) [list source [file join $dir safe.tcl]]
65
+ set auto_index(tcl_wordBreakAfter) [list source [file join $dir word.tcl]]
66
+ set auto_index(tcl_wordBreakBefore) [list source [file join $dir word.tcl]]
67
+ set auto_index(tcl_endOfWord) [list source [file join $dir word.tcl]]
68
+ set auto_index(tcl_startOfNextWord) [list source [file join $dir word.tcl]]
69
+ set auto_index(tcl_startOfPreviousWord) [list source [file join $dir word.tcl]]
70
+ set auto_index(::tcl::tm::add) [list source [file join $dir tm.tcl]]
71
+ set auto_index(::tcl::tm::remove) [list source [file join $dir tm.tcl]]
72
+ set auto_index(::tcl::tm::list) [list source [file join $dir tm.tcl]]
73
+ set auto_index(::tcl::tm::Defaults) [list source [file join $dir tm.tcl]]
74
+ set auto_index(::tcl::tm::UnknownHandler) [list source [file join $dir tm.tcl]]
75
+ set auto_index(::tcl::tm::roots) [list source [file join $dir tm.tcl]]
76
+ set auto_index(::tcl::tm::path) [list source [file join $dir tm.tcl]]
77
+ if {[namespace exists ::tcl::unsupported]} {
78
+ set auto_index(timerate) {namespace import ::tcl::unsupported::timerate}
79
+ }
lib/tcl8.6/tm.tcl ADDED
@@ -0,0 +1,380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- tcl -*-
2
+ #
3
+ # Searching for Tcl Modules. Defines a procedure, declares it as the primary
4
+ # command for finding packages, however also uses the former 'package unknown'
5
+ # command as a fallback.
6
+ #
7
+ # Locates all possible packages in a directory via a less restricted glob. The
8
+ # targeted directory is derived from the name of the requested package, i.e.
9
+ # the TM scan will look only at directories which can contain the requested
10
+ # package. It will register all packages it found in the directory so that
11
+ # future requests have a higher chance of being fulfilled by the ifneeded
12
+ # database without having to come to us again.
13
+ #
14
+ # We do not remember where we have been and simply rescan targeted directories
15
+ # when invoked again. The reasoning is this:
16
+ #
17
+ # - The only way we get back to the same directory is if someone is trying to
18
+ # [package require] something that wasn't there on the first scan.
19
+ #
20
+ # Either
21
+ # 1) It is there now: If we rescan, you get it; if not you don't.
22
+ #
23
+ # This covers the possibility that the application asked for a package
24
+ # late, and the package was actually added to the installation after the
25
+ # application was started. It should still be able to find it.
26
+ #
27
+ # 2) It still is not there: Either way, you don't get it, but the rescan
28
+ # takes time. This is however an error case and we don't care that much
29
+ # about it
30
+ #
31
+ # 3) It was there the first time; but for some reason a "package forget" has
32
+ # been run, and "package" doesn't know about it anymore.
33
+ #
34
+ # This can be an indication that the application wishes to reload some
35
+ # functionality. And should work as well.
36
+ #
37
+ # Note that this also strikes a balance between doing a glob targeting a
38
+ # single package, and thus most likely requiring multiple globs of the same
39
+ # directory when the application is asking for many packages, and trying to
40
+ # glob for _everything_ in all subdirectories when looking for a package,
41
+ # which comes with a heavy startup cost.
42
+ #
43
+ # We scan for regular packages only if no satisfying module was found.
44
+
45
+ namespace eval ::tcl::tm {
46
+ # Default paths. None yet.
47
+
48
+ variable paths {}
49
+
50
+ # The regex pattern a file name has to match to make it a Tcl Module.
51
+
52
+ set pkgpattern {^([_[:alpha:]][:_[:alnum:]]*)-([[:digit:]].*)[.]tm$}
53
+
54
+ # Export the public API
55
+
56
+ namespace export path
57
+ namespace ensemble create -command path -subcommands {add remove list}
58
+ }
59
+
60
+ # ::tcl::tm::path implementations --
61
+ #
62
+ # Public API to the module path. See specification.
63
+ #
64
+ # Arguments
65
+ # cmd - The subcommand to execute
66
+ # args - The paths to add/remove. Must not appear querying the
67
+ # path with 'list'.
68
+ #
69
+ # Results
70
+ # No result for subcommands 'add' and 'remove'. A list of paths for
71
+ # 'list'.
72
+ #
73
+ # Side effects
74
+ # The subcommands 'add' and 'remove' manipulate the list of paths to
75
+ # search for Tcl Modules. The subcommand 'list' has no side effects.
76
+
77
+ proc ::tcl::tm::add {args} {
78
+ # PART OF THE ::tcl::tm::path ENSEMBLE
79
+ #
80
+ # The path is added at the head to the list of module paths.
81
+ #
82
+ # The command enforces the restriction that no path may be an ancestor
83
+ # directory of any other path on the list. If the new path violates this
84
+ # restriction an error will be raised.
85
+ #
86
+ # If the path is already present as is no error will be raised and no
87
+ # action will be taken.
88
+
89
+ variable paths
90
+
91
+ # We use a copy of the path as source during validation, and extend it as
92
+ # well. Because we not only have to detect if the new paths are bogus with
93
+ # respect to the existing paths, but also between themselves. Otherwise we
94
+ # can still add bogus paths, by specifying them in a single call. This
95
+ # makes the use of the new paths simpler as well, a trivial assignment of
96
+ # the collected paths to the official state var.
97
+
98
+ set newpaths $paths
99
+ foreach p $args {
100
+ if {$p in $newpaths} {
101
+ # Ignore a path already on the list.
102
+ continue
103
+ }
104
+
105
+ # Search for paths which are subdirectories of the new one. If there
106
+ # are any then the new path violates the restriction about ancestors.
107
+
108
+ set pos [lsearch -glob $newpaths ${p}/*]
109
+ # Cannot use "in", we need the position for the message.
110
+ if {$pos >= 0} {
111
+ return -code error \
112
+ "$p is ancestor of existing module path [lindex $newpaths $pos]."
113
+ }
114
+
115
+ # Now look for existing paths which are ancestors of the new one. This
116
+ # reverse question forces us to loop over the existing paths, as each
117
+ # element is the pattern, not the new path :(
118
+
119
+ foreach ep $newpaths {
120
+ if {[string match ${ep}/* $p]} {
121
+ return -code error \
122
+ "$p is subdirectory of existing module path $ep."
123
+ }
124
+ }
125
+
126
+ set newpaths [linsert $newpaths 0 $p]
127
+ }
128
+
129
+ # The validation of the input is complete and successful, and everything
130
+ # in newpaths is either an old path, or added. We can now extend the
131
+ # official list of paths, a simple assignment is sufficient.
132
+
133
+ set paths $newpaths
134
+ return
135
+ }
136
+
137
+ proc ::tcl::tm::remove {args} {
138
+ # PART OF THE ::tcl::tm::path ENSEMBLE
139
+ #
140
+ # Removes the path from the list of module paths. The command is silently
141
+ # ignored if the path is not on the list.
142
+
143
+ variable paths
144
+
145
+ foreach p $args {
146
+ set pos [lsearch -exact $paths $p]
147
+ if {$pos >= 0} {
148
+ set paths [lreplace $paths $pos $pos]
149
+ }
150
+ }
151
+ }
152
+
153
+ proc ::tcl::tm::list {} {
154
+ # PART OF THE ::tcl::tm::path ENSEMBLE
155
+
156
+ variable paths
157
+ return $paths
158
+ }
159
+
160
+ # ::tcl::tm::UnknownHandler --
161
+ #
162
+ # Unknown handler for Tcl Modules, i.e. packages in module form.
163
+ #
164
+ # Arguments
165
+ # original - Original [package unknown] procedure.
166
+ # name - Name of desired package.
167
+ # version - Version of desired package. Can be the
168
+ # empty string.
169
+ # exact - Either -exact or omitted.
170
+ #
171
+ # Name, version, and exact are used to determine satisfaction. The
172
+ # original is called iff no satisfaction was achieved. The name is also
173
+ # used to compute the directory to target in the search.
174
+ #
175
+ # Results
176
+ # None.
177
+ #
178
+ # Side effects
179
+ # May populate the package ifneeded database with additional provide
180
+ # scripts.
181
+
182
+ proc ::tcl::tm::UnknownHandler {original name args} {
183
+ # Import the list of paths to search for packages in module form.
184
+ # Import the pattern used to check package names in detail.
185
+
186
+ variable paths
187
+ variable pkgpattern
188
+
189
+ # Without paths to search we can do nothing. (Except falling back to the
190
+ # regular search).
191
+
192
+ if {[llength $paths]} {
193
+ set pkgpath [string map {:: /} $name]
194
+ set pkgroot [file dirname $pkgpath]
195
+ if {$pkgroot eq "."} {
196
+ set pkgroot ""
197
+ }
198
+
199
+ # We don't remember a copy of the paths while looping. Tcl Modules are
200
+ # unable to change the list while we are searching for them. This also
201
+ # simplifies the loop, as we cannot get additional directories while
202
+ # iterating over the list. A simple foreach is sufficient.
203
+
204
+ set satisfied 0
205
+ foreach path $paths {
206
+ if {![interp issafe] && ![file exists $path]} {
207
+ continue
208
+ }
209
+ set currentsearchpath [file join $path $pkgroot]
210
+ if {![interp issafe] && ![file exists $currentsearchpath]} {
211
+ continue
212
+ }
213
+ set strip [llength [file split $path]]
214
+
215
+ # Get the module files out of the subdirectories.
216
+ # - Safe Base interpreters have a restricted "glob" command that
217
+ # works in this case.
218
+ # - The "catch" was essential when there was no safe glob and every
219
+ # call in a safe interp failed; it is retained only for corner
220
+ # cases in which the eventual call to glob returns an error.
221
+
222
+ catch {
223
+ # We always look for _all_ possible modules in the current
224
+ # path, to get the max result out of the glob.
225
+
226
+ foreach file [glob -nocomplain -directory $currentsearchpath *.tm] {
227
+ set pkgfilename [join [lrange [file split $file] $strip end] ::]
228
+
229
+ if {![regexp -- $pkgpattern $pkgfilename --> pkgname pkgversion]} {
230
+ # Ignore everything not matching our pattern for
231
+ # package names.
232
+ continue
233
+ }
234
+ try {
235
+ package vcompare $pkgversion 0
236
+ } on error {} {
237
+ # Ignore everything where the version part is not
238
+ # acceptable to "package vcompare".
239
+ continue
240
+ }
241
+
242
+ if {([package ifneeded $pkgname $pkgversion] ne {})
243
+ && (![interp issafe])
244
+ } {
245
+ # There's already a provide script registered for
246
+ # this version of this package. Since all units of
247
+ # code claiming to be the same version of the same
248
+ # package ought to be identical, just stick with
249
+ # the one we already have.
250
+ # This does not apply to Safe Base interpreters because
251
+ # the token-to-directory mapping may have changed.
252
+ continue
253
+ }
254
+
255
+ # We have found a candidate, generate a "provide script"
256
+ # for it, and remember it. Note that we are using ::list
257
+ # to do this; locally [list] means something else without
258
+ # the namespace specifier.
259
+
260
+ # NOTE. When making changes to the format of the provide
261
+ # command generated below CHECK that the 'LOCATE'
262
+ # procedure in core file 'platform/shell.tcl' still
263
+ # understands it, or, if not, update its implementation
264
+ # appropriately.
265
+ #
266
+ # Right now LOCATE's implementation assumes that the path
267
+ # of the package file is the last element in the list.
268
+
269
+ package ifneeded $pkgname $pkgversion \
270
+ "[::list package provide $pkgname $pkgversion];[::list source -encoding utf-8 $file]"
271
+
272
+ # We abort in this unknown handler only if we got a
273
+ # satisfying candidate for the requested package.
274
+ # Otherwise we still have to fallback to the regular
275
+ # package search to complete the processing.
276
+
277
+ if {($pkgname eq $name)
278
+ && [package vsatisfies $pkgversion {*}$args]} {
279
+ set satisfied 1
280
+
281
+ # We do not abort the loop, and keep adding provide
282
+ # scripts for every candidate in the directory, just
283
+ # remember to not fall back to the regular search
284
+ # anymore.
285
+ }
286
+ }
287
+ }
288
+ }
289
+
290
+ if {$satisfied} {
291
+ return
292
+ }
293
+ }
294
+
295
+ # Fallback to previous command, if existing. See comment above about
296
+ # ::list...
297
+
298
+ if {[llength $original]} {
299
+ uplevel 1 $original [::linsert $args 0 $name]
300
+ }
301
+ }
302
+
303
+ # ::tcl::tm::Defaults --
304
+ #
305
+ # Determines the default search paths.
306
+ #
307
+ # Arguments
308
+ # None
309
+ #
310
+ # Results
311
+ # None.
312
+ #
313
+ # Side effects
314
+ # May add paths to the list of defaults.
315
+
316
+ proc ::tcl::tm::Defaults {} {
317
+ global env tcl_platform
318
+
319
+ regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
320
+ set exe [file normalize [info nameofexecutable]]
321
+
322
+ # Note that we're using [::list], not [list] because [list] means
323
+ # something other than [::list] in this namespace.
324
+ roots [::list \
325
+ [file dirname [info library]] \
326
+ [file join [file dirname [file dirname $exe]] lib] \
327
+ ]
328
+
329
+ if {$tcl_platform(platform) eq "windows"} {
330
+ set sep ";"
331
+ } else {
332
+ set sep ":"
333
+ }
334
+ for {set n $minor} {$n >= 0} {incr n -1} {
335
+ foreach ev [::list \
336
+ TCL${major}.${n}_TM_PATH \
337
+ TCL${major}_${n}_TM_PATH \
338
+ ] {
339
+ if {![info exists env($ev)]} continue
340
+ foreach p [split $env($ev) $sep] {
341
+ path add $p
342
+ }
343
+ }
344
+ }
345
+ return
346
+ }
347
+
348
+ # ::tcl::tm::roots --
349
+ #
350
+ # Public API to the module path. See specification.
351
+ #
352
+ # Arguments
353
+ # paths - List of 'root' paths to derive search paths from.
354
+ #
355
+ # Results
356
+ # No result.
357
+ #
358
+ # Side effects
359
+ # Calls 'path add' to paths to the list of module search paths.
360
+
361
+ proc ::tcl::tm::roots {paths} {
362
+ regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
363
+ foreach pa $paths {
364
+ set p [file join $pa tcl$major]
365
+ for {set n $minor} {$n >= 0} {incr n -1} {
366
+ set px [file join $p ${major}.${n}]
367
+ if {![interp issafe]} {set px [file normalize $px]}
368
+ path add $px
369
+ }
370
+ set px [file join $p site-tcl]
371
+ if {![interp issafe]} {set px [file normalize $px]}
372
+ path add $px
373
+ }
374
+ return
375
+ }
376
+
377
+ # Initialization. Set up the default paths, then insert the new handler into
378
+ # the chain.
379
+
380
+ if {![interp issafe]} {::tcl::tm::Defaults}
lib/tcl8.6/word.tcl ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # word.tcl --
2
+ #
3
+ # This file defines various procedures for computing word boundaries in
4
+ # strings. This file is primarily needed so Tk text and entry widgets behave
5
+ # properly for different platforms.
6
+ #
7
+ # Copyright (c) 1996 Sun Microsystems, Inc.
8
+ # Copyright (c) 1998 Scriptics Corporation.
9
+ #
10
+ # See the file "license.terms" for information on usage and redistribution
11
+ # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
+
13
+ # The following variables are used to determine which characters are
14
+ # interpreted as white space.
15
+
16
+ if {$::tcl_platform(platform) eq "windows"} {
17
+ # Windows style - any but a Unicode space char
18
+ if {![info exists ::tcl_wordchars]} {
19
+ set ::tcl_wordchars {\S}
20
+ }
21
+ if {![info exists ::tcl_nonwordchars]} {
22
+ set ::tcl_nonwordchars {\s}
23
+ }
24
+ } else {
25
+ # Motif style - any Unicode word char (number, letter, or underscore)
26
+ if {![info exists ::tcl_wordchars]} {
27
+ set ::tcl_wordchars {\w}
28
+ }
29
+ if {![info exists ::tcl_nonwordchars]} {
30
+ set ::tcl_nonwordchars {\W}
31
+ }
32
+ }
33
+
34
+ # Arrange for caches of the real matcher REs to be kept, which enables the REs
35
+ # themselves to be cached for greater performance (and somewhat greater
36
+ # clarity too).
37
+
38
+ namespace eval ::tcl {
39
+ variable WordBreakRE
40
+ array set WordBreakRE {}
41
+
42
+ proc UpdateWordBreakREs args {
43
+ # Ignores the arguments
44
+ global tcl_wordchars tcl_nonwordchars
45
+ variable WordBreakRE
46
+
47
+ # To keep the RE strings short...
48
+ set letter $tcl_wordchars
49
+ set space $tcl_nonwordchars
50
+
51
+ set WordBreakRE(after) "$letter$space|$space$letter"
52
+ set WordBreakRE(before) "^.*($letter$space|$space$letter)"
53
+ set WordBreakRE(end) "$space*$letter+$space"
54
+ set WordBreakRE(next) "$letter*$space+$letter"
55
+ set WordBreakRE(previous) "$space*($letter+)$space*\$"
56
+ }
57
+
58
+ # Initialize the cache
59
+ UpdateWordBreakREs
60
+ trace add variable ::tcl_wordchars write ::tcl::UpdateWordBreakREs
61
+ trace add variable ::tcl_nonwordchars write ::tcl::UpdateWordBreakREs
62
+ }
63
+
64
+ # tcl_wordBreakAfter --
65
+ #
66
+ # This procedure returns the index of the first word boundary after the
67
+ # starting point in the given string, or -1 if there are no more boundaries in
68
+ # the given string. The index returned refers to the first character of the
69
+ # pair that comprises a boundary.
70
+ #
71
+ # Arguments:
72
+ # str - String to search.
73
+ # start - Index into string specifying starting point.
74
+
75
+ proc tcl_wordBreakAfter {str start} {
76
+ variable ::tcl::WordBreakRE
77
+ set result {-1 -1}
78
+ regexp -indices -start $start -- $WordBreakRE(after) $str result
79
+ return [lindex $result 1]
80
+ }
81
+
82
+ # tcl_wordBreakBefore --
83
+ #
84
+ # This procedure returns the index of the first word boundary before the
85
+ # starting point in the given string, or -1 if there are no more boundaries in
86
+ # the given string. The index returned refers to the second character of the
87
+ # pair that comprises a boundary.
88
+ #
89
+ # Arguments:
90
+ # str - String to search.
91
+ # start - Index into string specifying starting point.
92
+
93
+ proc tcl_wordBreakBefore {str start} {
94
+ variable ::tcl::WordBreakRE
95
+ set result {-1 -1}
96
+ regexp -indices -- $WordBreakRE(before) [string range $str 0 $start] result
97
+ return [lindex $result 1]
98
+ }
99
+
100
+ # tcl_endOfWord --
101
+ #
102
+ # This procedure returns the index of the first end-of-word location after a
103
+ # starting index in the given string. An end-of-word location is defined to be
104
+ # the first whitespace character following the first non-whitespace character
105
+ # after the starting point. Returns -1 if there are no more words after the
106
+ # starting point.
107
+ #
108
+ # Arguments:
109
+ # str - String to search.
110
+ # start - Index into string specifying starting point.
111
+
112
+ proc tcl_endOfWord {str start} {
113
+ variable ::tcl::WordBreakRE
114
+ set result {-1 -1}
115
+ regexp -indices -start $start -- $WordBreakRE(end) $str result
116
+ return [lindex $result 1]
117
+ }
118
+
119
+ # tcl_startOfNextWord --
120
+ #
121
+ # This procedure returns the index of the first start-of-word location after a
122
+ # starting index in the given string. A start-of-word location is defined to
123
+ # be a non-whitespace character following a whitespace character. Returns -1
124
+ # if there are no more start-of-word locations after the starting point.
125
+ #
126
+ # Arguments:
127
+ # str - String to search.
128
+ # start - Index into string specifying starting point.
129
+
130
+ proc tcl_startOfNextWord {str start} {
131
+ variable ::tcl::WordBreakRE
132
+ set result {-1 -1}
133
+ regexp -indices -start $start -- $WordBreakRE(next) $str result
134
+ return [lindex $result 1]
135
+ }
136
+
137
+ # tcl_startOfPreviousWord --
138
+ #
139
+ # This procedure returns the index of the first start-of-word location before
140
+ # a starting index in the given string.
141
+ #
142
+ # Arguments:
143
+ # str - String to search.
144
+ # start - Index into string specifying starting point.
145
+
146
+ proc tcl_startOfPreviousWord {str start} {
147
+ variable ::tcl::WordBreakRE
148
+ set word {-1 -1}
149
+ if {$start > 0} {
150
+ regexp -indices -- $WordBreakRE(previous) [string range [string range $str 0 $start] 0 end-1] \
151
+ result word
152
+ }
153
+ return [lindex $word 0]
154
+ }
lib/tdbc1.1.7/libtdbc1.1.7.so ADDED
Binary file (24.3 kB). View file
 
lib/tdbc1.1.7/libtdbcstub1.1.7.a ADDED
Binary file (3.04 kB). View file
 
lib/tdbc1.1.7/pkgIndex.tcl ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- tcl -*-
2
+ # Tcl package index file, version 1.1
3
+ #
4
+ # Make sure that TDBC is running in a compatible version of Tcl, and
5
+ # that TclOO is available.
6
+
7
+ if {![package vsatisfies [package provide Tcl] 8.6-]} {
8
+ return
9
+ }
10
+ apply {{dir} {
11
+ set libraryfile [file join $dir tdbc.tcl]
12
+ if {![file exists $libraryfile] && [info exists ::env(TDBC_LIBRARY)]} {
13
+ set libraryfile [file join $::env(TDBC_LIBRARY) tdbc.tcl]
14
+ }
15
+ if {[package vsatisfies [package provide Tcl] 9.0-]} {
16
+ package ifneeded tdbc 1.1.7 \
17
+ "package require TclOO;\
18
+ [list load [file join $dir libtcl9tdbc1.1.7.so] [string totitle tdbc]]\;\
19
+ [list source $libraryfile]"
20
+ } else {
21
+ package ifneeded tdbc 1.1.7 \
22
+ "package require TclOO;\
23
+ [list load [file join $dir libtdbc1.1.7.so] [string totitle tdbc]]\;\
24
+ [list source $libraryfile]"
25
+ }
26
+ }} $dir