| 158 | |
| 159 | |
| 160 | def super_len(o: Any) -> int: |
| 161 | total_length = None |
| 162 | current_position = 0 |
| 163 | |
| 164 | if not is_urllib3_1 and isinstance(o, str): |
| 165 | # urllib3 2.x+ treats all strings as utf-8 instead |
| 166 | # of latin-1 (iso-8859-1) like http.client. |
| 167 | o = o.encode("utf-8") |
| 168 | |
| 169 | if hasattr(o, "__len__"): |
| 170 | total_length = len(o) |
| 171 | |
| 172 | elif hasattr(o, "len"): |
| 173 | total_length = o.len |
| 174 | |
| 175 | elif hasattr(o, "fileno"): |
| 176 | try: |
| 177 | fileno = o.fileno() |
| 178 | except (io.UnsupportedOperation, AttributeError): |
| 179 | # AttributeError is a surprising exception, seeing as how we've just checked |
| 180 | # that `hasattr(o, 'fileno')`. It happens for objects obtained via |
| 181 | # `Tarfile.extractfile()`, per issue 5229. |
| 182 | pass |
| 183 | else: |
| 184 | total_length = os.fstat(fileno).st_size |
| 185 | |
| 186 | # Having used fstat to determine the file length, we need to |
| 187 | # confirm that this file was opened up in binary mode. |
| 188 | if "b" not in o.mode: |
| 189 | warnings.warn( |
| 190 | ( |
| 191 | "Requests has determined the content-length for this " |
| 192 | "request using the binary size of the file: however, the " |
| 193 | "file has been opened in text mode (i.e. without the 'b' " |
| 194 | "flag in the mode). This may lead to an incorrect " |
| 195 | "content-length. In Requests 3.0, support will be removed " |
| 196 | "for files in text mode." |
| 197 | ), |
| 198 | FileModeWarning, |
| 199 | ) |
| 200 | |
| 201 | if hasattr(o, "tell"): |
| 202 | try: |
| 203 | current_position = o.tell() |
| 204 | except OSError: |
| 205 | # This can happen in some weird situations, such as when the file |
| 206 | # is actually a special file descriptor like stdin. In this |
| 207 | # instance, we don't know what the length is, so set it to zero and |
| 208 | # let requests chunk it instead. |
| 209 | if total_length is not None: |
| 210 | current_position = total_length |
| 211 | else: |
| 212 | if hasattr(o, "seek") and total_length is None: |
| 213 | # StringIO and BytesIO have seek but no usable fileno |
| 214 | try: |
| 215 | # seek to end of file |
| 216 | o.seek(0, 2) |
| 217 | total_length = o.tell() |