You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/unify.py

239 lines
7.5 KiB

#!/usr/bin/env python
# Copyright (C) 2013-2018 Steven Myint
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Modifies strings to all use the same quote where possible."""
from __future__ import print_function
from __future__ import unicode_literals
import io
import os
import signal
import sys
import tokenize
import untokenize
__version__ = '0.5'
try:
unicode
except NameError:
unicode = str
def format_code(source, preferred_quote="'"):
"""Return source code with quotes unified."""
try:
return _format_code(source, preferred_quote)
except (tokenize.TokenError, IndentationError):
return source
def _format_code(source, preferred_quote):
"""Return source code with quotes unified."""
if not source:
return source
modified_tokens = []
sio = io.StringIO(source)
for (token_type,
token_string,
start,
end,
line) in tokenize.generate_tokens(sio.readline):
if token_type == tokenize.STRING:
token_string = unify_quotes(token_string,
preferred_quote=preferred_quote)
modified_tokens.append(
(token_type, token_string, start, end, line))
return untokenize.untokenize(modified_tokens)
def unify_quotes(token_string, preferred_quote):
"""Return string with quotes changed to preferred_quote if possible."""
bad_quote = {'"': "'",
"'": '"'}[preferred_quote]
allowed_starts = {
'': bad_quote,
'f': 'f' + bad_quote,
'r': 'r' + bad_quote,
'u': 'u' + bad_quote,
'b': 'b' + bad_quote
}
if not any(token_string.startswith(start)
for start in allowed_starts.values()):
return token_string
if token_string.count(bad_quote) != 2:
return token_string
if preferred_quote in token_string:
return token_string
assert token_string.endswith(bad_quote)
assert len(token_string) >= 2
for prefix, start in allowed_starts.items():
if token_string.startswith(start):
chars_to_strip_from_front = len(start)
return '{prefix}{preferred_quote}{token}{preferred_quote}'.format(
prefix=prefix,
preferred_quote=preferred_quote,
token=token_string[chars_to_strip_from_front:-1]
)
def open_with_encoding(filename, encoding, mode='r'):
"""Return opened file with a specific encoding."""
return io.open(filename, mode=mode, encoding=encoding,
newline='') # Preserve line endings
def detect_encoding(filename):
"""Return file encoding."""
try:
with open(filename, 'rb') as input_file:
from lib2to3.pgen2 import tokenize as lib2to3_tokenize
encoding = lib2to3_tokenize.detect_encoding(input_file.readline)[0]
# Check for correctness of encoding.
with open_with_encoding(filename, encoding) as input_file:
input_file.read()
return encoding
except (SyntaxError, LookupError, UnicodeDecodeError):
return 'latin-1'
def format_file(filename, args, standard_out):
"""Run format_code() on a file.
Returns `True` if any changes are needed and they are not being done
in-place.
"""
encoding = detect_encoding(filename)
with open_with_encoding(filename, encoding=encoding) as input_file:
source = input_file.read()
formatted_source = format_code(
source,
preferred_quote=args.quote)
if source != formatted_source:
if args.in_place:
with open_with_encoding(filename, mode='w',
encoding=encoding) as output_file:
output_file.write(formatted_source)
else:
import difflib
diff = difflib.unified_diff(
source.splitlines(),
formatted_source.splitlines(),
'before/' + filename,
'after/' + filename,
lineterm='')
standard_out.write('\n'.join(list(diff) + ['']))
return True
return False
def _main(argv, standard_out, standard_error):
"""Run quotes unifying on files.
Returns `1` if any quoting changes are still needed, otherwise
`None`.
"""
import argparse
parser = argparse.ArgumentParser(description=__doc__, prog='unify')
parser.add_argument('-i', '--in-place', action='store_true',
help='make changes to files instead of printing diffs')
parser.add_argument('-c', '--check-only', action='store_true',
help='exit with a status code of 1 if any changes are'
' still needed')
parser.add_argument('-r', '--recursive', action='store_true',
help='drill down directories recursively')
parser.add_argument('--quote', help='preferred quote', choices=["'", '"'],
default="'")
parser.add_argument('--version', action='version',
version='%(prog)s ' + __version__)
parser.add_argument('files', nargs='+',
help='files to format')
args = parser.parse_args(argv[1:])
filenames = list(set(args.files))
changes_needed = False
failure = False
while filenames:
name = filenames.pop(0)
if args.recursive and os.path.isdir(name):
for root, directories, children in os.walk(unicode(name)):
filenames += [os.path.join(root, f) for f in children
if f.endswith('.py') and
not f.startswith('.')]
directories[:] = [d for d in directories
if not d.startswith('.')]
else:
try:
if format_file(name, args=args, standard_out=standard_out):
changes_needed = True
except IOError as exception:
print(unicode(exception), file=standard_error)
failure = True
if failure or (args.check_only and changes_needed):
return 1
def main(): # pragma: no cover
"""Return exit status."""
try:
# Exit on broken pipe.
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
except AttributeError:
# SIGPIPE is not available on Windows.
pass
try:
return _main(sys.argv,
standard_out=sys.stdout,
standard_error=sys.stderr)
except KeyboardInterrupt:
return 2
if __name__ == '__main__':
sys.exit(main()) # pragma: no cover