py2docfx 0.1.20rc2196756__py3-none-any.whl → 0.1.21__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- py2docfx/convert_prepare/get_source.py +1 -1
- py2docfx/convert_prepare/package_info.py +37 -27
- py2docfx/convert_prepare/tests/test_get_source.py +3 -1
- py2docfx/convert_prepare/tests/test_package_info.py +159 -1
- py2docfx/docfx_yaml/build_finished.py +1 -1
- py2docfx/docfx_yaml/logger.py +42 -28
- py2docfx/venv/basevenv/Lib/site-packages/charset_normalizer/api.py +3 -2
- py2docfx/venv/basevenv/Lib/site-packages/charset_normalizer/legacy.py +17 -1
- py2docfx/venv/basevenv/Lib/site-packages/charset_normalizer/version.py +1 -1
- py2docfx/venv/basevenv/Lib/site-packages/requests/__version__.py +2 -2
- py2docfx/venv/basevenv/Lib/site-packages/requests/adapters.py +17 -40
- py2docfx/venv/basevenv/Lib/site-packages/requests/sessions.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/core/_version.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/core/pipeline/policies/_authentication.py +21 -9
- py2docfx/venv/venv1/Lib/site-packages/azure/core/pipeline/policies/_authentication_async.py +21 -9
- py2docfx/venv/venv1/Lib/site-packages/azure/core/pipeline/policies/_retry.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_bearer_token_provider.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/authorization_code.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azd_cli.py +82 -17
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azure_cli.py +28 -5
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azure_powershell.py +28 -4
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/broker.py +79 -0
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/chained.py +9 -3
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/default.py +153 -53
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/imds.py +25 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/shared_cache.py +12 -5
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/vscode.py +163 -144
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/workload_identity.py +23 -12
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/__init__.py +4 -0
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/interactive.py +14 -2
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/pipeline.py +4 -2
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/utils.py +96 -0
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_version.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_bearer_token_provider.py +3 -3
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/authorization_code.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azd_cli.py +32 -13
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azure_cli.py +26 -5
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azure_powershell.py +13 -2
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/chained.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/default.py +120 -55
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/imds.py +27 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/on_behalf_of.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/shared_cache.py +12 -5
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/vscode.py +15 -67
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/workload_identity.py +17 -13
- py2docfx/venv/venv1/Lib/site-packages/cffi/__init__.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/cffi/cparser.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/cffi/recompiler.py +5 -5
- py2docfx/venv/venv1/Lib/site-packages/cffi/setuptools_ext.py +13 -0
- py2docfx/venv/venv1/Lib/site-packages/cffi/vengine_cpy.py +3 -0
- py2docfx/venv/venv1/Lib/site-packages/charset_normalizer/api.py +3 -2
- py2docfx/venv/venv1/Lib/site-packages/charset_normalizer/legacy.py +17 -1
- py2docfx/venv/venv1/Lib/site-packages/charset_normalizer/version.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/cryptography/__about__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/cryptography/__init__.py +0 -13
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/_oid.py +8 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/asn1/__init__.py +10 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/asn1/asn1.py +116 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py +3 -9
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/_rust/declarative_asn1.pyi +32 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi +23 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi +1 -13
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py +16 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py +16 -1
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py +0 -2
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py +8 -0
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py +0 -47
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py +6 -91
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py +1 -3
- py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/cryptography/utils.py +0 -2
- py2docfx/venv/venv1/Lib/site-packages/cryptography/x509/name.py +2 -3
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/__init__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/any_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/api_pb2.py +12 -8
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/compiler/plugin_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor.py +398 -246
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor_pb2.py +74 -72
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor_pool.py +5 -4
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/duration_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/empty_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/field_mask_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/api_implementation.py +0 -6
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/extension_dict.py +3 -3
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/field_mask.py +3 -3
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/python_edition_defaults.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/python_message.py +10 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/type_checkers.py +47 -5
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/json_format.py +55 -32
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/runtime_version.py +6 -26
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/source_context_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/struct_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/text_format.py +30 -19
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/timestamp_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/type_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/google/protobuf/wrappers_pb2.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/psutil/__init__.py +39 -19
- py2docfx/venv/venv1/Lib/site-packages/psutil/_common.py +3 -5
- py2docfx/venv/venv1/Lib/site-packages/psutil/_psaix.py +1 -2
- py2docfx/venv/venv1/Lib/site-packages/psutil/_psbsd.py +53 -78
- py2docfx/venv/venv1/Lib/site-packages/psutil/_pslinux.py +55 -38
- py2docfx/venv/venv1/Lib/site-packages/psutil/_psosx.py +40 -12
- py2docfx/venv/venv1/Lib/site-packages/psutil/_psposix.py +0 -1
- py2docfx/venv/venv1/Lib/site-packages/psutil/_pssunos.py +1 -2
- py2docfx/venv/venv1/Lib/site-packages/psutil/_pswindows.py +33 -13
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/__init__.py +185 -122
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/__main__.py +2 -3
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_bsd.py +5 -10
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_connections.py +3 -4
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_contracts.py +41 -45
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_linux.py +35 -38
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_memleaks.py +4 -8
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_misc.py +6 -12
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_osx.py +17 -8
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_posix.py +29 -17
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_process.py +74 -75
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_process_all.py +11 -13
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_scripts.py +2 -3
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_sudo.py +117 -0
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_system.py +21 -31
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_testutils.py +23 -23
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_unicode.py +15 -8
- py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_windows.py +65 -33
- py2docfx/venv/venv1/Lib/site-packages/pycparser/__init__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/pycparser/c_generator.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/pycparser/c_lexer.py +14 -0
- py2docfx/venv/venv1/Lib/site-packages/pycparser/c_parser.py +30 -7
- py2docfx/venv/venv1/Lib/site-packages/pycparser/lextab.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/pycparser/yacctab.py +132 -127
- py2docfx/venv/venv1/Lib/site-packages/requests/__version__.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/requests/adapters.py +17 -40
- py2docfx/venv/venv1/Lib/site-packages/requests/sessions.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/typing_extensions.py +91 -18
- {py2docfx-0.1.20rc2196756.dist-info → py2docfx-0.1.21.dist-info}/METADATA +1 -1
- {py2docfx-0.1.20rc2196756.dist-info → py2docfx-0.1.21.dist-info}/RECORD +137 -135
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/linux_vscode_adapter.py +0 -100
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/macos_vscode_adapter.py +0 -34
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/win_vscode_adapter.py +0 -77
- {py2docfx-0.1.20rc2196756.dist-info → py2docfx-0.1.21.dist-info}/WHEEL +0 -0
- {py2docfx-0.1.20rc2196756.dist-info → py2docfx-0.1.21.dist-info}/top_level.txt +0 -0
@@ -54,7 +54,7 @@ def update_package_info(executable: str, pkg: PackageInfo, source_folder: str):
|
|
54
54
|
for meta_info in metadata:
|
55
55
|
meta_info_array = meta_info.split(":")
|
56
56
|
meta_field = meta_info_array[0].strip().lower()
|
57
|
-
if meta_field in attrs:
|
57
|
+
if meta_field in attrs and not hasattr(pkg, meta_field):
|
58
58
|
setattr(
|
59
59
|
pkg,
|
60
60
|
meta_field,
|
@@ -13,7 +13,7 @@ class PackageInfo:
|
|
13
13
|
path: Source
|
14
14
|
def __init__(self) -> None:
|
15
15
|
pass
|
16
|
-
|
16
|
+
|
17
17
|
@classmethod
|
18
18
|
def report_error(cls, name, value, condition=None):
|
19
19
|
py2docfx_logger = get_logger(__name__)
|
@@ -53,6 +53,7 @@ class PackageInfo:
|
|
53
53
|
|
54
54
|
package_info.version = package_info_dict.get("version", None)
|
55
55
|
package_info.extra_index_url = package_info_dict.get("extra_index_url", None)
|
56
|
+
package_info.extras = package_info_dict.get("extras", [])
|
56
57
|
|
57
58
|
if package_info.install_type == cls.InstallType.SOURCE_CODE:
|
58
59
|
package_info.url = package_info_dict.get("url", None)
|
@@ -93,56 +94,65 @@ class PackageInfo:
|
|
93
94
|
return package_info
|
94
95
|
|
95
96
|
def get_combined_name_version(self):
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
return f"{self.name.strip()}=={self.version.strip()}"
|
97
|
+
base_name = (
|
98
|
+
f"{self.name}[{','.join(extras)}]"
|
99
|
+
if (extras := getattr(self, "extras", []))
|
100
|
+
else self.name
|
101
|
+
)
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
103
|
+
version = getattr(self, "version", None)
|
104
|
+
if not version:
|
105
|
+
return base_name
|
106
|
+
elif re.match("^(<|>|<=|>=|==).+$", version.strip()):
|
107
|
+
return base_name.strip() + version.strip()
|
108
|
+
else:
|
109
|
+
return f"{base_name.strip()}=={version.strip()}"
|
106
110
|
|
111
|
+
def get_install_command(self) -> tuple[str, list]:
|
107
112
|
if self.install_type == self.InstallType.DIST_FILE:
|
108
|
-
if hasattr(self, "location")
|
109
|
-
packageInstallName = self.location
|
110
|
-
else:
|
113
|
+
if not hasattr(self, "location") or not self.location:
|
111
114
|
self.__class__.report_error(
|
112
115
|
"location", "None", condition="When install_type is dist_file"
|
113
116
|
)
|
117
|
+
return (
|
118
|
+
f"{self.location}[{','.join(extras)}]"
|
119
|
+
if (extras := getattr(self, "extras", None))
|
120
|
+
else self.location,
|
121
|
+
[],
|
122
|
+
)
|
114
123
|
|
115
|
-
|
124
|
+
if self.install_type == self.InstallType.PYPI:
|
116
125
|
if not hasattr(self, "name") or not self.name:
|
117
126
|
self.__class__.report_error(
|
118
127
|
"name", "None", condition="When install_type is pypi"
|
119
128
|
)
|
120
|
-
|
121
|
-
|
122
|
-
else:
|
123
|
-
packageInstallName = self.name
|
129
|
+
pipInstallExtraOptions = []
|
130
|
+
if not hasattr(self, "version") or self.version is None:
|
124
131
|
pipInstallExtraOptions.append("--upgrade")
|
125
|
-
|
126
132
|
if hasattr(self, "extra_index_url") and self.extra_index_url:
|
127
133
|
pipInstallExtraOptions.extend(
|
128
134
|
["--extra-index-url", self.extra_index_url]
|
129
135
|
)
|
136
|
+
return (self.get_combined_name_version(), pipInstallExtraOptions)
|
130
137
|
|
131
|
-
|
132
|
-
if hasattr(self, "path")
|
133
|
-
packageInstallName = self.path.source_folder
|
134
|
-
else:
|
138
|
+
if self.install_type == self.InstallType.SOURCE_CODE:
|
139
|
+
if not hasattr(self, "path") or not self.path.source_folder:
|
135
140
|
self.__class__.report_error(
|
136
141
|
"path.source_folder",
|
137
142
|
"None",
|
138
143
|
condition="When install_type is source_code",
|
139
144
|
)
|
140
|
-
|
141
|
-
|
145
|
+
return (
|
146
|
+
f"{self.path.source_folder}[{','.join(extras)}]"
|
147
|
+
if (extras := getattr(self, "extras", None))
|
148
|
+
else self.path.source_folder,
|
149
|
+
[],
|
150
|
+
)
|
151
|
+
|
152
|
+
self.__class__.report_error("install_type", self.install_type)
|
142
153
|
|
143
|
-
return (packageInstallName, pipInstallExtraOptions)
|
144
154
|
|
145
|
-
def get_exluded_command(self) ->
|
155
|
+
def get_exluded_command(self) -> list:
|
146
156
|
py2docfx_logger = get_logger(__name__)
|
147
157
|
if hasattr(self, "path"):
|
148
158
|
code_location = self.path.source_folder
|
@@ -50,8 +50,10 @@ def test_update_package_info(init_package_info):
|
|
50
50
|
assert package.name == "dummy_package"
|
51
51
|
assert package.version == "3.1.0"
|
52
52
|
|
53
|
-
# case of metadata
|
53
|
+
# case of metadata, unly use metadata file as a fallback
|
54
54
|
package = init_package_info
|
55
|
+
del package.name
|
56
|
+
del package.version
|
55
57
|
get_source.update_package_info(sys.executable, package, os.path.join(base_path, "mock-2"))
|
56
58
|
assert package.name == "mock_package"
|
57
59
|
assert package.version == "2.2.0"
|
@@ -80,4 +80,162 @@ def test_get_exclude_command_check_extra_exclude(tmp_path):
|
|
80
80
|
]
|
81
81
|
def form_exclude_path(raletive_path):
|
82
82
|
return os.path.join(source_folder, raletive_path)
|
83
|
-
assert exclude_path == [form_exclude_path(path) for path in expected_exclude_path]
|
83
|
+
assert exclude_path == [form_exclude_path(path) for path in expected_exclude_path]
|
84
|
+
|
85
|
+
|
86
|
+
def test_get_combined_name_version_with_extras():
|
87
|
+
"""Test get_combined_name_version with extras"""
|
88
|
+
# Test package with extras but no version
|
89
|
+
test_data = {
|
90
|
+
"package_info": {
|
91
|
+
"install_type": "pypi",
|
92
|
+
"name": "test-package",
|
93
|
+
"extras": ["dev", "test"],
|
94
|
+
},
|
95
|
+
}
|
96
|
+
pkg = PackageInfo.parse_from(test_data)
|
97
|
+
assert pkg.get_combined_name_version() == "test-package[dev,test]"
|
98
|
+
|
99
|
+
# Test package with extras and version
|
100
|
+
test_data_with_version = {
|
101
|
+
"package_info": {
|
102
|
+
"install_type": "pypi",
|
103
|
+
"name": "test-package",
|
104
|
+
"version": "1.0.0",
|
105
|
+
"extras": ["dev", "test"],
|
106
|
+
},
|
107
|
+
}
|
108
|
+
pkg_with_version = PackageInfo.parse_from(test_data_with_version)
|
109
|
+
assert (
|
110
|
+
pkg_with_version.get_combined_name_version() == "test-package[dev,test]==1.0.0"
|
111
|
+
)
|
112
|
+
|
113
|
+
# Test package with extras and version operator
|
114
|
+
test_data_with_operator = {
|
115
|
+
"package_info": {
|
116
|
+
"install_type": "pypi",
|
117
|
+
"name": "test-package",
|
118
|
+
"version": ">=1.0.0",
|
119
|
+
"extras": ["dev"],
|
120
|
+
},
|
121
|
+
}
|
122
|
+
pkg_with_operator = PackageInfo.parse_from(test_data_with_operator)
|
123
|
+
assert pkg_with_operator.get_combined_name_version() == "test-package[dev]>=1.0.0"
|
124
|
+
|
125
|
+
|
126
|
+
def test_install_command_pypi_with_extras():
|
127
|
+
"""Test get_install_command for PYPI packages with extras"""
|
128
|
+
# Test PYPI package with extras and version
|
129
|
+
test_data = {
|
130
|
+
"package_info": {
|
131
|
+
"install_type": "pypi",
|
132
|
+
"name": "test-package",
|
133
|
+
"version": "1.0.0",
|
134
|
+
"extras": ["dev", "test"],
|
135
|
+
},
|
136
|
+
}
|
137
|
+
pkg = PackageInfo.parse_from(test_data)
|
138
|
+
install_command = pkg.get_install_command()
|
139
|
+
assert install_command[0] == "test-package[dev,test]==1.0.0"
|
140
|
+
assert install_command[1] == []
|
141
|
+
|
142
|
+
# Test PYPI package with extras but no version (should get --upgrade)
|
143
|
+
test_data_no_version = {
|
144
|
+
"package_info": {
|
145
|
+
"install_type": "pypi",
|
146
|
+
"name": "test-package",
|
147
|
+
"extras": ["dev"],
|
148
|
+
},
|
149
|
+
}
|
150
|
+
pkg_no_version = PackageInfo.parse_from(test_data_no_version)
|
151
|
+
install_command = pkg_no_version.get_install_command()
|
152
|
+
assert install_command[0] == "test-package[dev]"
|
153
|
+
assert install_command[1] == ["--upgrade"]
|
154
|
+
|
155
|
+
|
156
|
+
def test_install_command_source_code_with_extras(tmp_path):
|
157
|
+
"""Test get_install_command for SOURCE_CODE packages with extras"""
|
158
|
+
source_folder = os.path.join(tmp_path, "source_folder")
|
159
|
+
yaml_output_folder = os.path.join(tmp_path, "yaml_output_folder")
|
160
|
+
|
161
|
+
test_data = {
|
162
|
+
"package_info": {
|
163
|
+
"install_type": "source_code",
|
164
|
+
"name": "test-package",
|
165
|
+
"url": "https://github.com/test/test-package.git",
|
166
|
+
"extras": ["dev", "test"],
|
167
|
+
},
|
168
|
+
}
|
169
|
+
pkg = PackageInfo.parse_from(test_data)
|
170
|
+
pkg.path = Source(
|
171
|
+
source_folder=source_folder,
|
172
|
+
yaml_output_folder=yaml_output_folder,
|
173
|
+
package_name="test-package",
|
174
|
+
)
|
175
|
+
|
176
|
+
install_command = pkg.get_install_command()
|
177
|
+
assert install_command[0] == f"{source_folder}[dev,test]"
|
178
|
+
assert install_command[1] == []
|
179
|
+
|
180
|
+
|
181
|
+
def test_install_command_dist_file_with_extras():
|
182
|
+
"""Test get_install_command for DIST_FILE packages with extras"""
|
183
|
+
test_data = {
|
184
|
+
"package_info": {
|
185
|
+
"install_type": "dist_file",
|
186
|
+
"location": "/path/to/package.whl",
|
187
|
+
"extras": ["dev"],
|
188
|
+
},
|
189
|
+
}
|
190
|
+
pkg = PackageInfo.parse_from(test_data)
|
191
|
+
install_command = pkg.get_install_command()
|
192
|
+
assert install_command[0] == "/path/to/package.whl[dev]"
|
193
|
+
assert install_command[1] == []
|
194
|
+
|
195
|
+
|
196
|
+
def test_install_command_without_extras():
|
197
|
+
"""Test that packages without extras work as before"""
|
198
|
+
# Test PYPI package without extras
|
199
|
+
test_data = {
|
200
|
+
"package_info": {
|
201
|
+
"install_type": "pypi",
|
202
|
+
"name": "test-package",
|
203
|
+
"version": "1.0.0",
|
204
|
+
}
|
205
|
+
}
|
206
|
+
pkg = PackageInfo.parse_from(test_data)
|
207
|
+
install_command = pkg.get_install_command()
|
208
|
+
assert install_command[0] == "test-package==1.0.0"
|
209
|
+
assert install_command[1] == []
|
210
|
+
|
211
|
+
|
212
|
+
def test_install_command_empty_extras():
|
213
|
+
"""Test that packages with empty extras list work correctly"""
|
214
|
+
test_data = {
|
215
|
+
"package_info": {
|
216
|
+
"install_type": "pypi",
|
217
|
+
"name": "test-package",
|
218
|
+
"version": "1.0.0",
|
219
|
+
"extras": [],
|
220
|
+
},
|
221
|
+
}
|
222
|
+
pkg = PackageInfo.parse_from(test_data)
|
223
|
+
install_command = pkg.get_install_command()
|
224
|
+
assert install_command[0] == "test-package==1.0.0"
|
225
|
+
assert install_command[1] == []
|
226
|
+
|
227
|
+
|
228
|
+
def test_install_command_single_extra():
|
229
|
+
"""Test package with single extra"""
|
230
|
+
test_data = {
|
231
|
+
"package_info": {
|
232
|
+
"install_type": "pypi",
|
233
|
+
"name": "test-package",
|
234
|
+
"version": "1.0.0",
|
235
|
+
"extras": ["dev"],
|
236
|
+
},
|
237
|
+
}
|
238
|
+
pkg = PackageInfo.parse_from(test_data)
|
239
|
+
install_command = pkg.get_install_command()
|
240
|
+
assert install_command[0] == "test-package[dev]==1.0.0"
|
241
|
+
assert install_command[1] == []
|
@@ -277,7 +277,7 @@ def build_finished(app, exception):
|
|
277
277
|
obj['kind'] = 'import'
|
278
278
|
package_obj = obj
|
279
279
|
|
280
|
-
if (obj['type'] == 'class' and
|
280
|
+
if (obj['type'] == 'class' and 'inheritance' in obj):
|
281
281
|
convert_class_to_enum_if_needed(obj)
|
282
282
|
|
283
283
|
is_root = insert_node_to_toc_tree_return_is_root_package(toc_yaml, uid, project_name, toc_node_map)
|
py2docfx/docfx_yaml/logger.py
CHANGED
@@ -77,18 +77,18 @@ def counts_errors_warnings(log_file_path):
|
|
77
77
|
warning_count += 1
|
78
78
|
return warning_count, error_count
|
79
79
|
|
80
|
-
def get_warning_error_count():
|
81
|
-
main_log_file_path = os.path.join("logs", "log.txt")
|
82
|
-
warning_count, error_count = counts_errors_warnings(main_log_file_path)
|
83
|
-
|
84
|
-
log_folder_path = os.path.join("logs", "package_logs")
|
85
|
-
# Check if the directory exists before trying to list its contents
|
86
|
-
if os.path.exists(log_folder_path) and os.path.isdir(log_folder_path):
|
87
|
-
for log_file in os.listdir(log_folder_path):
|
88
|
-
log_file_path = os.path.join(log_folder_path, log_file)
|
89
|
-
warnings, errors = counts_errors_warnings(log_file_path)
|
90
|
-
warning_count += warnings
|
91
|
-
error_count += errors
|
80
|
+
def get_warning_error_count():
|
81
|
+
main_log_file_path = os.path.join("logs", "log.txt")
|
82
|
+
warning_count, error_count = counts_errors_warnings(main_log_file_path)
|
83
|
+
|
84
|
+
log_folder_path = os.path.join("logs", "package_logs")
|
85
|
+
# Check if the directory exists before trying to list its contents
|
86
|
+
if os.path.exists(log_folder_path) and os.path.isdir(log_folder_path):
|
87
|
+
for log_file in os.listdir(log_folder_path):
|
88
|
+
log_file_path = os.path.join(log_folder_path, log_file)
|
89
|
+
warnings, errors = counts_errors_warnings(log_file_path)
|
90
|
+
warning_count += warnings
|
91
|
+
error_count += errors
|
92
92
|
|
93
93
|
return warning_count, error_count
|
94
94
|
|
@@ -120,16 +120,16 @@ def print_out_log_by_log_level(log_list, log_level):
|
|
120
120
|
if log['level'] >= log_level and log['message'] not in ['', '\n', '\r\n']:
|
121
121
|
print(log['message'])
|
122
122
|
|
123
|
-
def output_log_by_log_level():
|
124
|
-
log_level = get_log_level()
|
125
|
-
main_log_file_path = os.path.join("logs", "log.txt")
|
126
|
-
print_out_log_by_log_level(parse_log(main_log_file_path), log_level)
|
127
|
-
|
128
|
-
package_logs_folder = os.path.join("logs", "package_logs")
|
129
|
-
# Check if the directory exists before trying to list its contents
|
130
|
-
if os.path.exists(package_logs_folder) and os.path.isdir(package_logs_folder):
|
131
|
-
for log_file in os.listdir(package_logs_folder):
|
132
|
-
log_file_path = os.path.join(package_logs_folder, log_file)
|
123
|
+
def output_log_by_log_level():
|
124
|
+
log_level = get_log_level()
|
125
|
+
main_log_file_path = os.path.join("logs", "log.txt")
|
126
|
+
print_out_log_by_log_level(parse_log(main_log_file_path), log_level)
|
127
|
+
|
128
|
+
package_logs_folder = os.path.join("logs", "package_logs")
|
129
|
+
# Check if the directory exists before trying to list its contents
|
130
|
+
if os.path.exists(package_logs_folder) and os.path.isdir(package_logs_folder):
|
131
|
+
for log_file in os.listdir(package_logs_folder):
|
132
|
+
log_file_path = os.path.join(package_logs_folder, log_file)
|
133
133
|
print_out_log_by_log_level(parse_log(log_file_path), log_level)
|
134
134
|
|
135
135
|
async def run_async_subprocess(exe_path, cmd, logger, cwd=None):
|
@@ -148,9 +148,16 @@ async def run_async_subprocess(exe_path, cmd, logger, cwd=None):
|
|
148
148
|
)
|
149
149
|
stdout, stderr = await process.communicate()
|
150
150
|
if process.returncode != 0:
|
151
|
-
|
152
|
-
|
153
|
-
|
151
|
+
# Log both stdout and stderr on failure - pip often outputs detailed
|
152
|
+
# dependency resolution errors to stdout even when it fails
|
153
|
+
stdout_msg = stdout.decode('utf-8')
|
154
|
+
stderr_msg = stderr.decode('utf-8')
|
155
|
+
|
156
|
+
if stdout_msg and stdout_msg.strip():
|
157
|
+
logger.error(f"STDOUT: {stdout_msg}")
|
158
|
+
if stderr_msg and stderr_msg.strip():
|
159
|
+
logger.error(f"STDERR: {stderr_msg}")
|
160
|
+
|
154
161
|
raise subprocess.CalledProcessError(process.returncode, cmd, stdout, stderr)
|
155
162
|
else:
|
156
163
|
msg = stdout.decode('utf-8')
|
@@ -174,9 +181,16 @@ async def run_async_subprocess_without_executable(cmd, logger, cwd=None):
|
|
174
181
|
|
175
182
|
stdout, stderr = await process.communicate()
|
176
183
|
if process.returncode != 0:
|
177
|
-
|
178
|
-
|
179
|
-
|
184
|
+
# Log both stdout and stderr on failure - pip often outputs detailed
|
185
|
+
# dependency resolution errors to stdout even when it fails
|
186
|
+
stdout_msg = stdout.decode('utf-8')
|
187
|
+
stderr_msg = stderr.decode('utf-8')
|
188
|
+
|
189
|
+
if stdout_msg and stdout_msg.strip():
|
190
|
+
logger.error(f"STDOUT: {stdout_msg}")
|
191
|
+
if stderr_msg and stderr_msg.strip():
|
192
|
+
logger.error(f"STDERR: {stderr_msg}")
|
193
|
+
|
180
194
|
raise subprocess.CalledProcessError(process.returncode, cmd, stdout, stderr)
|
181
195
|
else:
|
182
196
|
msg = stdout.decode('utf-8')
|
@@ -369,14 +369,15 @@ def from_bytes(
|
|
369
369
|
# Preparing those fallbacks in case we got nothing.
|
370
370
|
if (
|
371
371
|
enable_fallback
|
372
|
-
and encoding_iana
|
372
|
+
and encoding_iana
|
373
|
+
in ["ascii", "utf_8", specified_encoding, "utf_16", "utf_32"]
|
373
374
|
and not lazy_str_hard_failure
|
374
375
|
):
|
375
376
|
fallback_entry = CharsetMatch(
|
376
377
|
sequences,
|
377
378
|
encoding_iana,
|
378
379
|
threshold,
|
379
|
-
|
380
|
+
bom_or_sig_available,
|
380
381
|
[],
|
381
382
|
decoded_payload,
|
382
383
|
preemptive_declaration=specified_encoding,
|
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any
|
|
4
4
|
from warnings import warn
|
5
5
|
|
6
6
|
from .api import from_bytes
|
7
|
-
from .constant import CHARDET_CORRESPONDENCE
|
7
|
+
from .constant import CHARDET_CORRESPONDENCE, TOO_SMALL_SEQUENCE
|
8
8
|
|
9
9
|
# TODO: remove this check when dropping Python 3.7 support
|
10
10
|
if TYPE_CHECKING:
|
@@ -49,6 +49,22 @@ def detect(
|
|
49
49
|
language = r.language if r is not None and r.language != "Unknown" else ""
|
50
50
|
confidence = 1.0 - r.chaos if r is not None else None
|
51
51
|
|
52
|
+
# automatically lower confidence
|
53
|
+
# on small bytes samples.
|
54
|
+
# https://github.com/jawah/charset_normalizer/issues/391
|
55
|
+
if (
|
56
|
+
confidence is not None
|
57
|
+
and confidence >= 0.9
|
58
|
+
and encoding
|
59
|
+
not in {
|
60
|
+
"utf_8",
|
61
|
+
"ascii",
|
62
|
+
}
|
63
|
+
and r.bom is False # type: ignore[union-attr]
|
64
|
+
and len(byte_str) < TOO_SMALL_SEQUENCE
|
65
|
+
):
|
66
|
+
confidence -= 0.2
|
67
|
+
|
52
68
|
# Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process
|
53
69
|
# but chardet does return 'utf-8-sig' and it is a valid codec name.
|
54
70
|
if r is not None and encoding == "utf_8" and r.bom:
|
@@ -5,8 +5,8 @@
|
|
5
5
|
__title__ = "requests"
|
6
6
|
__description__ = "Python HTTP for Humans."
|
7
7
|
__url__ = "https://requests.readthedocs.io"
|
8
|
-
__version__ = "2.32.
|
9
|
-
__build__ =
|
8
|
+
__version__ = "2.32.5"
|
9
|
+
__build__ = 0x023205
|
10
10
|
__author__ = "Kenneth Reitz"
|
11
11
|
__author_email__ = "me@kennethreitz.org"
|
12
12
|
__license__ = "Apache-2.0"
|
@@ -27,7 +27,6 @@ from urllib3.poolmanager import PoolManager, proxy_from_url
|
|
27
27
|
from urllib3.util import Timeout as TimeoutSauce
|
28
28
|
from urllib3.util import parse_url
|
29
29
|
from urllib3.util.retry import Retry
|
30
|
-
from urllib3.util.ssl_ import create_urllib3_context
|
31
30
|
|
32
31
|
from .auth import _basic_auth_str
|
33
32
|
from .compat import basestring, urlparse
|
@@ -74,19 +73,6 @@ DEFAULT_RETRIES = 0
|
|
74
73
|
DEFAULT_POOL_TIMEOUT = None
|
75
74
|
|
76
75
|
|
77
|
-
try:
|
78
|
-
import ssl # noqa: F401
|
79
|
-
|
80
|
-
_preloaded_ssl_context = create_urllib3_context()
|
81
|
-
_preloaded_ssl_context.load_verify_locations(
|
82
|
-
extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH)
|
83
|
-
)
|
84
|
-
except ImportError:
|
85
|
-
# Bypass default SSLContext creation when Python
|
86
|
-
# interpreter isn't built with the ssl module.
|
87
|
-
_preloaded_ssl_context = None
|
88
|
-
|
89
|
-
|
90
76
|
def _urllib3_request_context(
|
91
77
|
request: "PreparedRequest",
|
92
78
|
verify: "bool | str | None",
|
@@ -99,19 +85,9 @@ def _urllib3_request_context(
|
|
99
85
|
scheme = parsed_request_url.scheme.lower()
|
100
86
|
port = parsed_request_url.port
|
101
87
|
|
102
|
-
# Determine if we have and should use our default SSLContext
|
103
|
-
# to optimize performance on standard requests.
|
104
|
-
poolmanager_kwargs = getattr(poolmanager, "connection_pool_kw", {})
|
105
|
-
has_poolmanager_ssl_context = poolmanager_kwargs.get("ssl_context")
|
106
|
-
should_use_default_ssl_context = (
|
107
|
-
_preloaded_ssl_context is not None and not has_poolmanager_ssl_context
|
108
|
-
)
|
109
|
-
|
110
88
|
cert_reqs = "CERT_REQUIRED"
|
111
89
|
if verify is False:
|
112
90
|
cert_reqs = "CERT_NONE"
|
113
|
-
elif verify is True and should_use_default_ssl_context:
|
114
|
-
pool_kwargs["ssl_context"] = _preloaded_ssl_context
|
115
91
|
elif isinstance(verify, str):
|
116
92
|
if not os.path.isdir(verify):
|
117
93
|
pool_kwargs["ca_certs"] = verify
|
@@ -314,26 +290,27 @@ class HTTPAdapter(BaseAdapter):
|
|
314
290
|
:param cert: The SSL certificate to verify.
|
315
291
|
"""
|
316
292
|
if url.lower().startswith("https") and verify:
|
317
|
-
|
293
|
+
cert_loc = None
|
318
294
|
|
319
|
-
#
|
320
|
-
# Otherwise, if verify is a boolean, we don't load anything since
|
321
|
-
# the connection will be using a context with the default certificates already loaded,
|
322
|
-
# and this avoids a call to the slow load_verify_locations()
|
295
|
+
# Allow self-specified cert location.
|
323
296
|
if verify is not True:
|
324
|
-
# `verify` must be a str with a path then
|
325
297
|
cert_loc = verify
|
326
298
|
|
327
|
-
|
328
|
-
|
329
|
-
f"Could not find a suitable TLS CA certificate bundle, "
|
330
|
-
f"invalid path: {cert_loc}"
|
331
|
-
)
|
299
|
+
if not cert_loc:
|
300
|
+
cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH)
|
332
301
|
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
302
|
+
if not cert_loc or not os.path.exists(cert_loc):
|
303
|
+
raise OSError(
|
304
|
+
f"Could not find a suitable TLS CA certificate bundle, "
|
305
|
+
f"invalid path: {cert_loc}"
|
306
|
+
)
|
307
|
+
|
308
|
+
conn.cert_reqs = "CERT_REQUIRED"
|
309
|
+
|
310
|
+
if not os.path.isdir(cert_loc):
|
311
|
+
conn.ca_certs = cert_loc
|
312
|
+
else:
|
313
|
+
conn.ca_cert_dir = cert_loc
|
337
314
|
else:
|
338
315
|
conn.cert_reqs = "CERT_NONE"
|
339
316
|
conn.ca_certs = None
|
@@ -410,7 +387,7 @@ class HTTPAdapter(BaseAdapter):
|
|
410
387
|
``"cert_reqs"`` will be set
|
411
388
|
* If ``verify`` is a string, (i.e., it is a user-specified trust bundle)
|
412
389
|
``"ca_certs"`` will be set if the string is not a directory recognized
|
413
|
-
by :py:func:`os.path.isdir`, otherwise ``"
|
390
|
+
by :py:func:`os.path.isdir`, otherwise ``"ca_cert_dir"`` will be
|
414
391
|
set.
|
415
392
|
* If ``"cert"`` is specified, ``"cert_file"`` will always be set. If
|
416
393
|
``"cert"`` is a tuple with a second item, ``"key_file"`` will also
|
@@ -535,7 +535,7 @@ class Session(SessionRedirectMixin):
|
|
535
535
|
for multipart encoding upload.
|
536
536
|
:param auth: (optional) Auth tuple or callable to enable
|
537
537
|
Basic/Digest/Custom HTTP Auth.
|
538
|
-
:param timeout: (optional) How
|
538
|
+
:param timeout: (optional) How many seconds to wait for the server to send
|
539
539
|
data before giving up, as a float, or a :ref:`(connect timeout,
|
540
540
|
read timeout) <timeouts>` tuple.
|
541
541
|
:type timeout: float or tuple
|
@@ -6,12 +6,14 @@
|
|
6
6
|
import time
|
7
7
|
import base64
|
8
8
|
from typing import TYPE_CHECKING, Optional, TypeVar, MutableMapping, Any, Union, cast
|
9
|
+
|
9
10
|
from azure.core.credentials import (
|
10
11
|
TokenCredential,
|
11
12
|
SupportsTokenInfo,
|
12
13
|
TokenRequestOptions,
|
13
14
|
TokenProvider,
|
14
15
|
)
|
16
|
+
from azure.core.exceptions import HttpResponseError
|
15
17
|
from azure.core.pipeline import PipelineRequest, PipelineResponse
|
16
18
|
from azure.core.pipeline.transport import (
|
17
19
|
HttpResponse as LegacyHttpResponse,
|
@@ -165,7 +167,20 @@ class BearerTokenCredentialPolicy(_BearerTokenCredentialPolicyBase, HTTPPolicy[H
|
|
165
167
|
if response.http_response.status_code == 401:
|
166
168
|
self._token = None # any cached token is invalid
|
167
169
|
if "WWW-Authenticate" in response.http_response.headers:
|
168
|
-
|
170
|
+
try:
|
171
|
+
request_authorized = self.on_challenge(request, response)
|
172
|
+
except Exception as ex:
|
173
|
+
# If the response is streamed, read it so the error message is immediately available to the user.
|
174
|
+
# Otherwise, a generic error message will be given and the user will have to read the response
|
175
|
+
# body to see the actual error.
|
176
|
+
if response.context.options.get("stream"):
|
177
|
+
try:
|
178
|
+
response.http_response.read() # type: ignore
|
179
|
+
except Exception: # pylint:disable=broad-except
|
180
|
+
pass
|
181
|
+
# Raise the exception from the token request with the original 401 response
|
182
|
+
raise ex from HttpResponseError(response=response.http_response)
|
183
|
+
|
169
184
|
if request_authorized:
|
170
185
|
# if we receive a challenge response, we retrieve a new token
|
171
186
|
# which matches the new target. In this case, we don't want to remove
|
@@ -200,14 +215,11 @@ class BearerTokenCredentialPolicy(_BearerTokenCredentialPolicyBase, HTTPPolicy[H
|
|
200
215
|
encoded_claims = get_challenge_parameter(headers, "Bearer", "claims")
|
201
216
|
if not encoded_claims:
|
202
217
|
return False
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
return True
|
209
|
-
except Exception: # pylint:disable=broad-except
|
210
|
-
return False
|
218
|
+
padding_needed = -len(encoded_claims) % 4
|
219
|
+
claims = base64.urlsafe_b64decode(encoded_claims + "=" * padding_needed).decode("utf-8")
|
220
|
+
if claims:
|
221
|
+
self.authorize_request(request, *self._scopes, claims=claims)
|
222
|
+
return True
|
211
223
|
return False
|
212
224
|
|
213
225
|
def on_response(
|