]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/yapf/yapflib/file_resources.py
1 # Copyright 2015 Google Inc. All Rights Reserved.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """Interface to file resources.
16 This module provides functions for interfacing with files: opening, writing, and
25 from configparser
import ConfigParser
26 from tokenize
import detect_encoding
28 from yapf
.yapflib
import errors
29 from yapf
.yapflib
import style
36 def _GetExcludePatternsFromYapfIgnore(filename
):
37 """Get a list of file patterns to ignore from .yapfignore."""
39 if os
.path
.isfile(filename
) and os
.access(filename
, os
.R_OK
):
40 with
open(filename
, 'r') as fd
:
42 if line
.strip() and not line
.startswith('#'):
43 ignore_patterns
.append(line
.strip())
45 if any(e
.startswith('./') for e
in ignore_patterns
):
46 raise errors
.YapfError('path in .yapfignore should not start with ./')
48 return ignore_patterns
51 def _GetExcludePatternsFromPyprojectToml(filename
):
52 """Get a list of file patterns to ignore from pyproject.toml."""
55 import tomli
as tomllib
57 raise errors
.YapfError(
58 'tomli package is needed for using pyproject.toml as a '
61 if os
.path
.isfile(filename
) and os
.access(filename
, os
.R_OK
):
62 with
open(filename
, 'rb') as fd
:
63 pyproject_toml
= tomllib
.load(fd
)
64 ignore_patterns
= pyproject_toml
.get('tool',
66 {}).get('ignore_patterns', [])
67 if any(e
.startswith('./') for e
in ignore_patterns
):
68 raise errors
.YapfError('path in pyproject.toml should not start with ./')
70 return ignore_patterns
73 def GetExcludePatternsForDir(dirname
):
74 """Return patterns of files to exclude from ignorefile in a given directory.
76 Looks for .yapfignore in the directory dirname.
79 dirname: (unicode) The name of the directory.
82 A List of file patterns to exclude if ignore file is found, otherwise empty
87 yapfignore_file
= os
.path
.join(dirname
, '.yapfignore')
88 if os
.path
.exists(yapfignore_file
):
89 ignore_patterns
+= _GetExcludePatternsFromYapfIgnore(yapfignore_file
)
91 pyproject_toml_file
= os
.path
.join(dirname
, 'pyproject.toml')
92 if os
.path
.exists(pyproject_toml_file
):
93 ignore_patterns
+= _GetExcludePatternsFromPyprojectToml(pyproject_toml_file
)
94 return ignore_patterns
97 def GetDefaultStyleForDir(dirname
, default_style
=style
.DEFAULT_STYLE
):
98 """Return default style name for a given directory.
100 Looks for .style.yapf or setup.cfg or pyproject.toml in the parent
104 dirname: (unicode) The name of the directory.
105 default_style: The style to return if nothing is found. Defaults to the
106 global default style ('pep8') unless otherwise specified.
109 The filename if found, otherwise return the default style.
111 dirname
= os
.path
.abspath(dirname
)
113 # See if we have a .style.yapf file.
114 style_file
= os
.path
.join(dirname
, style
.LOCAL_STYLE
)
115 if os
.path
.exists(style_file
):
118 # See if we have a setup.cfg file with a '[yapf]' section.
119 config_file
= os
.path
.join(dirname
, style
.SETUP_CONFIG
)
121 fd
= open(config_file
)
123 pass # It's okay if it's not there.
126 config
= ConfigParser()
128 if config
.has_section('yapf'):
131 # See if we have a pyproject.toml file with a '[tool.yapf]' section.
132 config_file
= os
.path
.join(dirname
, style
.PYPROJECT_TOML
)
134 fd
= open(config_file
, 'rb')
136 pass # It's okay if it's not there.
140 import tomli
as tomllib
142 raise errors
.YapfError(
143 'tomli package is needed for using pyproject.toml as a '
144 'configuration file')
146 pyproject_toml
= tomllib
.load(fd
)
147 style_dict
= pyproject_toml
.get('tool', {}).get('yapf', None)
148 if style_dict
is not None:
151 if (not dirname
or not os
.path
.basename(dirname
) or
152 dirname
== os
.path
.abspath(os
.path
.sep
)):
154 dirname
= os
.path
.dirname(dirname
)
156 global_file
= os
.path
.expanduser(style
.GLOBAL_STYLE
)
157 if os
.path
.exists(global_file
):
163 def GetCommandLineFiles(command_line_file_list
, recursive
, exclude
):
164 """Return the list of files specified on the command line."""
165 return _FindPythonFiles(command_line_file_list
, recursive
, exclude
)
168 def WriteReformattedCode(filename
,
172 """Emit the reformatted code.
174 Write the reformatted code into the file, if in_place is True. Otherwise,
178 filename: (unicode) The name of the unformatted file.
179 reformatted_code: (unicode) The reformatted code.
180 encoding: (unicode) The encoding of the file.
181 in_place: (bool) If True, then write the reformatted code to the file.
184 with codecs
.open(filename
, mode
='w', encoding
=encoding
) as fd
:
185 fd
.write(reformatted_code
)
187 sys
.stdout
.buffer.write(reformatted_code
.encode('utf-8'))
190 def LineEnding(lines
):
191 """Retrieve the line ending of the original source."""
192 endings
= {CRLF
: 0, CR
: 0, LF
: 0}
194 if line
.endswith(CRLF
):
196 elif line
.endswith(CR
):
198 elif line
.endswith(LF
):
200 return sorted((LF
, CRLF
, CR
), key
=endings
.get
, reverse
=True)[0]
203 def _FindPythonFiles(filenames
, recursive
, exclude
):
204 """Find all Python files."""
205 if exclude
and any(e
.startswith('./') for e
in exclude
):
206 raise errors
.YapfError("path in '--exclude' should not start with ./")
207 exclude
= exclude
and [e
.rstrip('/' + os
.path
.sep
) for e
in exclude
]
210 for filename
in filenames
:
211 if filename
!= '.' and exclude
and IsIgnored(filename
, exclude
):
213 if os
.path
.isdir(filename
):
215 raise errors
.YapfError(
216 "directory specified without '--recursive' flag: %s" % filename
)
218 # TODO(morbo): Look into a version of os.walk that can handle recursion.
220 for dirpath
, dirnames
, filelist
in os
.walk(filename
):
221 if dirpath
!= '.' and exclude
and IsIgnored(dirpath
, exclude
):
222 excluded_dirs
.append(dirpath
)
224 elif any(dirpath
.startswith(e
) for e
in excluded_dirs
):
227 filepath
= os
.path
.join(dirpath
, f
)
228 if exclude
and IsIgnored(filepath
, exclude
):
230 if IsPythonFile(filepath
):
231 python_files
.append(filepath
)
232 # To prevent it from scanning the contents excluded folders, os.walk()
233 # lets you amend its list of child dirs `dirnames`. These edits must be
234 # made in-place instead of creating a modified copy of `dirnames`.
235 # list.remove() is slow and list.pop() is a headache. Instead clear
236 # `dirnames` then repopulate it.
237 dirnames_
= [dirnames
.pop(0) for i
in range(len(dirnames
))]
238 for dirname
in dirnames_
:
239 dir_
= os
.path
.join(dirpath
, dirname
)
240 if IsIgnored(dir_
, exclude
):
241 excluded_dirs
.append(dir_
)
243 dirnames
.append(dirname
)
245 elif os
.path
.isfile(filename
):
246 python_files
.append(filename
)
251 def IsIgnored(path
, exclude
):
252 """Return True if filename matches any patterns in exclude."""
255 path
= path
.lstrip(os
.path
.sep
)
256 while path
.startswith('.' + os
.path
.sep
):
258 return any(fnmatch
.fnmatch(path
, e
.rstrip(os
.path
.sep
)) for e
in exclude
)
261 def IsPythonFile(filename
):
262 """Return True if filename is a Python file."""
263 if os
.path
.splitext(filename
)[1] == '.py':
267 with
open(filename
, 'rb') as fd
:
268 encoding
= detect_encoding(fd
.readline
)[0]
270 # Check for correctness of encoding.
271 with codecs
.open(filename
, mode
='r', encoding
=encoding
) as fd
:
273 except UnicodeDecodeError:
275 except (IOError, SyntaxError):
276 # If we fail to detect encoding (or the encoding cookie is incorrect - which
277 # will make detect_encoding raise SyntaxError), assume it's not a Python
282 with codecs
.open(filename
, mode
='r', encoding
=encoding
) as fd
:
283 first_line
= fd
.readline(256)
287 return re
.match(r
'^#!.*\bpython[23]?\b', first_line
)
290 def FileEncoding(filename
):
291 """Return the file's encoding."""
292 with
open(filename
, 'rb') as fd
:
293 return detect_encoding(fd
.readline
)[0]