YAPF هو منسق لغة Python يعتمد على clang-format
(تم تطويره بواسطة Daniel Jasper). في الأساس، تأخذ الخوارزمية الكود وتحسب أفضل تنسيق يتوافق مع النمط الذي تم تكوينه. إنه يأخذ الكثير من العمل الشاق للحفاظ على التعليمات البرمجية الخاصة بك.
الهدف النهائي هو أن يكون الكود الذي تنتجه YAPF بنفس جودة الكود الذي سيكتبه المبرمج إذا كان يتبع دليل الأسلوب.
ملاحظة: YAPF ليس منتجًا رسميًا من منتجات Google (تجريبيًا أو غير ذلك)، فهو مجرد رمز مملوك لشركة Google.
لتثبيت YAPF من PyPI:
$ pip install yapf
لا يزال YAPF في مرحلة "التجريبية"، وقد يتغير الإصدار الذي تم إصداره كثيرًا؛ ولذلك، فإن أفضل طريقة لمواكبة آخر التطورات هي استنساخ هذا المستودع أو التثبيت مباشرة من github:
$ pip install git+https://github.com/google/yapf.git
لاحظ أنه إذا كنت تنوي استخدام YAPF كأداة لسطر الأوامر وليس كمكتبة، فإن التثبيت ليس ضروريًا. يدعم YAPF تشغيله كدليل بواسطة مترجم Python. إذا قمت باستنساخ/فك ضغط YAPF في DIR
، فمن الممكن تشغيل:
$ PYTHONPATH=DIR python DIR/yapf [options] ...
يتم دعم YAPF بواسطة محررين متعددين عبر ملحقات المجتمع أو المكونات الإضافية. راجع دعم المحرر لمزيد من المعلومات.
YAPF يدعم بايثون 3.7+.
usage: yapf [-h] [-v] [-d | -i | -q] [-r | -l START-END] [-e PATTERN]
[--style STYLE] [--style-help] [--no-local-style] [-p] [-m] [-vv]
[files ...]
Formatter for Python code.
positional arguments:
files reads from stdin when no files are specified.
optional arguments:
-h, --help show this help message and exit
-v, --version show program's version number and exit
-d, --diff print the diff for the fixed source
-i, --in-place make changes to files in place
-q, --quiet output nothing and set return value
-r, --recursive run recursively over directories
-l START-END, --lines START-END
range of lines to reformat, one-based
-e PATTERN, --exclude PATTERN
patterns for files to exclude from formatting
--style STYLE specify formatting style: either a style name (for
example "pep8" or "google"), or the name of a file
with style settings. The default is pep8 unless a
.style.yapf or setup.cfg or pyproject.toml file
located in the same directory as the source or one of
its parent directories (for stdin, the current
directory is used).
--style-help show style settings and exit; this output can be saved
to .style.yapf to make your settings permanent
--no-local-style don't search for local style definition
-p, --parallel run YAPF in parallel when formatting multiple files.
-m, --print-modified print out file names of modified files
-vv, --verbose print out file names while processing
عادةً ما تُرجع YAPF الصفر عند إنهاء البرنامج بنجاح وغير الصفر بخلاف ذلك.
إذا تم توفير --diff
، فإن YAPF تُرجع صفرًا عندما لا تكون هناك تغييرات ضرورية، وغير صفر بخلاف ذلك (بما في ذلك خطأ البرنامج). يمكنك استخدام هذا في سير عمل CI لاختبار أن الرمز قد تم تنسيقه بـ YAPF.
بالإضافة إلى استبعاد الأنماط المتوفرة في سطر الأوامر، يبحث YAPF عن أنماط إضافية محددة في ملف يسمى .yapfignore
أو pyproject.toml
الموجود في دليل العمل الذي يتم استدعاء YAPF منه.
بناء جملة .yapfignore
يشبه مطابقة نمط اسم ملف UNIX:
* matches everything
? matches any single character
[seq] matches any character in seq
[!seq] matches any character not in seq
لاحظ أنه لا يجب أن يبدأ أي إدخال بـ ./
.
إذا كنت تستخدم pyproject.toml
، فسيتم تحديد أنماط الاستبعاد بواسطة مفتاح ignore_patterns
في القسم [tool.yapfignore]
. على سبيل المثال:
[tool.yapfignore]
ignore_patterns = [
" temp/**/*.py " ,
" temp2/*.py "
]
نمط التنسيق الذي تستخدمه YAPF قابل للتكوين وهناك العديد من "المقابض" التي يمكن استخدامها لضبط كيفية قيام YAPF بالتنسيق. راجع الوحدة style.py
للحصول على القائمة الكاملة.
للتحكم في النمط، قم بتشغيل YAPF باستخدام وسيطة --style
. فهو يقبل أحد الأنماط المحددة مسبقًا (على سبيل المثال، pep8
أو google
)، أو المسار إلى ملف التكوين الذي يحدد النمط المطلوب، أو قاموس أزواج المفاتيح/القيمة.
ملف التكوين عبارة عن قائمة بسيطة key = value
مع عنوان [style]
. على سبيل المثال:
[style]
based_on_style = pep8
spaces_before_comment = 4
split_before_logical_operator = true
يحدد الإعداد based_on_style
أي من الأنماط المحددة مسبقًا يعتمد عليها هذا النمط المخصص (فكر في الأمر مثل الفئات الفرعية). تم تحديد أربعة أنماط مسبقًا:
pep8
(افتراضي)google
(استنادًا إلى دليل Google Python Style Guide)yapf
(للاستخدام مع مشاريع Google مفتوحة المصدر)facebook
راجع _STYLE_NAME_TO_FACTORY
في style.py
للحصول على التفاصيل.
من الممكن أيضًا أن تفعل الشيء نفسه في سطر الأوامر باستخدام القاموس. على سبيل المثال:
--style= ' {based_on_style: pep8, indent_width: 2} '
سيأخذ هذا النمط الأساسي pep8
ويعدله ليحتوي على مسافة بادئة.
سوف تقوم YAPF بالبحث عن نمط التنسيق بالطريقة التالية:
[style]
من ملف .style.yapf
إما في الدليل الحالي أو في أحد الأدلة الأصلية الخاصة به.[yapf]
من ملف setup.cfg
إما في الدليل الحالي أو في أحد الأدلة الأصلية الخاصة به.[tool.yapf]
من ملف pyproject.toml
إما في الدليل الحالي أو في أحد الأدلة الأصلية الخاصة به.[style]
من ملف ~/.config/yapf/style
في دليلك الرئيسي.إذا لم يتم العثور على أي من هذه الملفات، فسيتم استخدام النمط الافتراضي PEP8.
مثال على نوع التنسيق الذي يمكن أن تقوم به YAPF، سيأخذ هذا الكود القبيح:
x = { 'a' : 37 , 'b' : 42 ,
'c' : 927 }
y = 'hello ' 'world'
z = 'hello ' + 'world'
a = 'hello {}' . format ( 'world' )
class foo ( object ):
def f ( self ):
return 37 * - + 2
def g ( self , x , y = 42 ):
return y
def f ( a ) :
return 37 + - + a [ 42 - x : y ** 3 ]
وأعد تنسيقه إلى:
x = { 'a' : 37 , 'b' : 42 , 'c' : 927 }
y = 'hello ' 'world'
z = 'hello ' + 'world'
a = 'hello {}' . format ( 'world' )
class foo ( object ):
def f ( self ):
return 37 * - + 2
def g ( self , x , y = 42 ):
return y
def f ( a ):
return 37 + - + a [ 42 - x : y ** 3 ]
واجهتا برمجة التطبيقات الرئيسيتان للاتصال بـ YAPF هما FormatCode
و FormatFile
، ويشتركان في العديد من الوسائط الموضحة أدناه:
> >> from yapf . yapflib . yapf_api import FormatCode # reformat a string of code
> >> formatted_code , changed = FormatCode ( "f ( a = 1, b = 2 )" )
> >> formatted_code
'f(a=1, b=2) n '
> >> changed
True
وسيطة style_config
: إما اسم نمط أو مسار إلى ملف يحتوي على إعدادات نمط التنسيق. إذا لم يتم تحديد أي شيء، فاستخدم النمط الافتراضي كما هو محدد في style.DEFAULT_STYLE_FACTORY
.
> >> FormatCode ( "def g(): n return True" , style_config = 'pep8' )[ 0 ]
'def g(): n return True n '
وسيطة lines
: قائمة بصفوف الخطوط (ints)، [البداية، النهاية]، التي نريد تنسيقها. الأسطر مفهرسة على أساس 1. يمكن استخدامه بواسطة تعليمات برمجية خارجية (مثل IDEs) عند إعادة تنسيق مقتطف من التعليمات البرمجية بدلاً من الملف بأكمله.
> >> FormatCode ( "def g( ): n a=1 n b = 2 n return a==b" , lines = [( 1 , 1 ), ( 2 , 3 )])[ 0 ]
'def g(): n a = 1 n b = 2 n return a==b n '
print_diff
(bool): بدلاً من إرجاع المصدر الذي تمت إعادة تنسيقه، قم بإرجاع diff الذي يحول المصدر المنسق إلى مصدر تمت إعادة تنسيقه.
>>> print(FormatCode("a==b", filename="foo.py", print_diff=True)[0])
--- foo.py (original)
+++ foo.py (reformatted)
@@ -1 +1 @@
- a==b
+ a == b
ملاحظة: وسيطة filename
لـ FormatCode
هي ما يتم إدراجه في diff، والقيمة الافتراضية هي <unknown>
.
يقوم FormatFile
بإرجاع التعليمات البرمجية المعاد تنسيقها من الملف الذي تم تمريره مع ترميزه:
> >> from yapf . yapflib . yapf_api import FormatFile # reformat a file
> >> print ( open ( "foo.py" ). read ()) # contents of file
a == b
> >> reformatted_code , encoding , changed = FormatFile ( "foo.py" )
> >> formatted_code
'a == b n '
> >> encoding
'utf-8'
> >> changed
True
تقوم الوسيطة in_place
بحفظ الكود المعاد تنسيقه مرة أخرى في الملف:
> >> FormatFile ( "foo.py" , in_place = True )[: 2 ]
( None , 'utf-8' )
> >> print ( open ( "foo.py" ). read ()) # contents of file (now fixed)
a == b
خيارات:
usage: yapf-diff [-h] [-i] [-p NUM] [--regex PATTERN] [--iregex PATTERN][-v]
[--style STYLE] [--binary BINARY]
This script reads input from a unified diff and reformats all the changed
lines. This is useful to reformat all the lines touched by a specific patch.
Example usage for git/svn users:
git diff -U0 --no-color --relative HEAD^ | yapf-diff -i
svn diff --diff-cmd=diff -x-U0 | yapf-diff -p0 -i
It should be noted that the filename contained in the diff is used
unmodified to determine the source file to update. Users calling this script
directly should be careful to ensure that the path in the diff is correct
relative to the current working directory.
optional arguments:
-h, --help show this help message and exit
-i, --in-place apply edits to files instead of displaying a diff
-p NUM, --prefix NUM strip the smallest prefix containing P slashes
--regex PATTERN custom pattern selecting file paths to reformat
(case sensitive, overrides -iregex)
--iregex PATTERN custom pattern selecting file paths to reformat
(case insensitive, overridden by -regex)
-v, --verbose be more verbose, ineffective without -i
--style STYLE specify formatting style: either a style name (for
example "pep8" or "google"), or the name of a file
with style settings. The default is pep8 unless a
.style.yapf or setup.cfg or pyproject.toml file
located in the same directory as the source or one of
its parent directories (for stdin, the current
directory is used).
--binary BINARY location of binary to use for YAPF
ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT
قم بمحاذاة قوس الإغلاق مع المسافة البادئة المرئية.
ALLOW_MULTILINE_LAMBDAS
السماح بتنسيق lambdas على أكثر من سطر واحد.
ALLOW_MULTILINE_DICTIONARY_KEYS
السماح بوجود مفاتيح القاموس على أسطر متعددة. على سبيل المثال:
x = {
( 'this is the first element of a tuple' ,
'this is the second element of a tuple' ):
value ,
}
ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS
السماح بالتقسيم قبل التعيين الافتراضي/المسمى في قائمة الوسائط.
ALLOW_SPLIT_BEFORE_DICT_VALUE
السماح بالانقسامات قبل قيمة القاموس.
ARITHMETIC_PRECEDENCE_INDICATION
دع التباعد يشير إلى أسبقية عامل التشغيل. على سبيل المثال:
a = 1 * 2 + 3 / 4
b = 1 / 2 - 3 * 4
c = ( 1 + 2 ) * ( 3 - 4 )
d = ( 1 - 2 ) / ( 3 + 4 )
e = 1 * 2 - 3
f = 1 + 2 + 3 + 4
سيتم تنسيقها على النحو التالي للإشارة إلى الأسبقية:
a = 1 * 2 + 3 / 4
b = 1 / 2 - 3 * 4
c = ( 1 + 2 ) * ( 3 - 4 )
d = ( 1 - 2 ) / ( 3 + 4 )
e = 1 * 2 - 3
f = 1 + 2 + 3 + 4
BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION
يضبط عدد الأسطر الفارغة المطلوبة المحيطة بتعريفات الوظيفة والفئة ذات المستوى الأعلى. على سبيل المثال:
class Foo :
pass
# <------ having two blank lines here
# <------ is the default setting
class Bar :
pass
BLANK_LINE_BEFORE_CLASS_DOCSTRING
أدخل سطرًا فارغًا قبل سلسلة المستندات على مستوى الفصل الدراسي.
BLANK_LINE_BEFORE_MODULE_DOCSTRING
أدخل سطرًا فارغًا قبل مستند الوحدة النمطية.
BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF
أدخل سطرًا فارغًا قبل أن يتم تداخل
def
أوclass
على الفور داخلdef
أوclass
آخر. على سبيل المثال:
class Foo :
# <------ this blank line
def method ():
pass
BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES
يضبط عدد الأسطر الفارغة المطلوبة بين الواردات ذات المستوى الأعلى والتعريفات المتغيرة. مفيد للتوافق مع أدوات مثل isort.
COALESCE_BRACKETS
لا تقسم بين قوسين متتاليين. يكون ذلك مناسبًا فقط عند تعيين
DEDENT_CLOSING_BRACKETS
أوINDENT_CLOSING_BRACKETS
. على سبيل المثال:
call_func_that_takes_a_dict (
{
'key1' : 'value1' ,
'key2' : 'value2' ,
}
)
سيتم إعادة التنسيق إلى:
call_func_that_takes_a_dict ({
'key1' : 'value1' ,
'key2' : 'value2' ,
})
COLUMN_LIMIT
حد العمود (أو الحد الأقصى لطول الخط)
CONTINUATION_ALIGN_STYLE
أسلوب استمرار المحاذاة. القيم المحتملة هي:
SPACE
: استخدم المسافات لمحاذاة الاستمرار. هذا هو السلوك الافتراضي.FIXED
: استخدام عدد ثابت (CONTINUATION_INDENT_WIDTH
) من الأعمدة (مثل علامات التبويبCONTINUATION_INDENT_WIDTH
/INDENT_WIDTH
أو مسافاتCONTINUATION_INDENT_WIDTH
) لاستمرار المحاذاة.VALIGN-RIGHT
: محاذاة خطوط الاستمرار عموديًا إلى عدة أعمدةINDENT_WIDTH
. إلى اليمين قليلاً (علامة تبويب واحدة أو مسافات قليلة) إذا لم تتمكن من محاذاة خطوط الاستمرار عموديًا باستخدام الأحرف البادئة.
CONTINUATION_INDENT_WIDTH
عرض المسافة البادئة المستخدمة لاستمرارية الخط.
DEDENT_CLOSING_BRACKETS
ضع أقواس الإغلاق على سطر منفصل، متباعدًا، إذا كان التعبير بين قوسين لا يمكن احتواؤه في سطر واحد. ينطبق على جميع أنواع الأقواس، بما في ذلك تعريفات الوظائف واستدعاءاتها. على سبيل المثال:
config = {
'key1' : 'value1' ,
'key2' : 'value2' ,
} # <--- this bracket is dedented and on a separate line
time_series = self . remote_client . query_entity_counters (
entity = 'dev3246.region1' ,
key = 'dns.query_latency_tcp' ,
transform = Transformation . AVERAGE ( window = timedelta ( seconds = 60 )),
start_ts = now () - timedelta ( days = 3 ),
end_ts = now (),
) # <--- this bracket is dedented and on a separate line
DISABLE_ENDING_COMMA_HEURISTIC
قم بتعطيل الإرشاد الذي يضع كل عنصر من عناصر القائمة في سطر منفصل إذا كانت القائمة منتهية بفاصلة.
ملاحظة: تغير سلوك هذه العلامة في الإصدار 0.40.3. في السابق، إذا كانت هذه العلامة صحيحة، كنا نقوم بتقسيم القوائم التي تحتوي على فاصلة زائدة أو تعليق. الآن، لدينا علامة منفصلة،
DISABLE_SPLIT_LIST_WITH_COMMENT
، التي تتحكم في التقسيم عندما تحتوي القائمة على تعليق. للحصول على السلوك القديم، قم بتعيين كلتا العلامتين على القيمة true. مزيد من المعلومات في CHANGELOG.md.
DISABLE_SPLIT_LIST_WITH_COMMENT
لا تضع كل عنصر في سطر جديد ضمن القائمة التي تحتوي على تعليقات بينية.
بدون هذه العلامة (الافتراضي):
[ a, b, # c ]
بهذا العلم :
[ a, b, # c ]
يعكس هذا سلوك تنسيق clang وهو مفيد لتشكيل "مجموعات منطقية" من العناصر في القائمة. كما أنه يعمل في إعلانات الوظائف.
EACH_DICT_ENTRY_ON_SEPARATE_LINE
ضع كل إدخال في القاموس في السطر الخاص به.
FORCE_MULTILINE_DICT
احترم
EACH_DICT_ENTRY_ON_SEPARATE_LINE
حتى لو كان الخط أقصر منCOLUMN_LIMIT
.
I18N_COMMENT
التعبير العادي لتعليق التدويل. يؤدي وجود هذا التعليق إلى إيقاف إعادة تنسيق هذا السطر، لأنه يجب أن تكون التعليقات بجوار السلسلة التي يترجمونها.
I18N_FUNCTION_CALL
تقوم وظيفة التدويل باستدعاء الأسماء. يؤدي وجود هذه الوظيفة إلى إيقاف إعادة التنسيق على هذا السطر، لأن السلسلة التي تحتوي عليها لا يمكن نقلها بعيدًا عن تعليق i18n.
INDENT_BLANK_LINES
اضبط على
True
لتفضيل الأسطر الفارغة ذات المسافة البادئة بدلاً من الأسطر الفارغة
INDENT_CLOSING_BRACKETS
ضع أقواس الإغلاق على سطر منفصل، مع ترك مسافة بادئة، إذا كان التعبير بين قوسين لا يمكن احتواؤه في سطر واحد. ينطبق على جميع أنواع الأقواس، بما في ذلك تعريفات الوظائف واستدعاءاتها. على سبيل المثال:
config = {
'key1' : 'value1' ,
'key2' : 'value2' ,
} # <--- this bracket is indented and on a separate line
time_series = self . remote_client . query_entity_counters (
entity = 'dev3246.region1' ,
key = 'dns.query_latency_tcp' ,
transform = Transformation . AVERAGE ( window = timedelta ( seconds = 60 )),
start_ts = now () - timedelta ( days = 3 ),
end_ts = now (),
) # <--- this bracket is indented and on a separate line
INDENT_DICTIONARY_VALUE
ضع مسافة بادئة لقيمة القاموس إذا لم يكن من الممكن احتواؤها على نفس السطر مثل مفتاح القاموس. على سبيل المثال:
config = {
'key1' :
'value1' ,
'key2' : value1 +
value2 ,
}
INDENT_WIDTH
عدد الأعمدة المطلوب استخدامها للمسافة البادئة.
JOIN_MULTIPLE_LINES
ضم الأسطر القصيرة إلى سطر واحد. على سبيل المثال، سطر واحد
if
البيانات.
NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS
لا تقم بتضمين مسافات حول عوامل التشغيل الثنائية المحددة. على سبيل المثال:
1 + 2 * 3 - 4 / 5
سيتم تنسيقه على النحو التالي عند تكوينه باستخدام
*
و/
:
1 + 2 * 3 - 4 / 5
SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET
أدخل مسافة بين فاصلة النهاية وقوس الإغلاق في القائمة، وما إلى ذلك.
SPACE_INSIDE_BRACKETS
Use spaces inside brackets, braces, and parentheses. For example:
method_call ( 1 )
my_dict [ 3 ][ 1 ][ get_index ( * args , ** kwargs ) ]
my_set = { 1 , 2 , 3 }
SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN
قم بالتعيين على
True
لتفضيل المسافات حول عامل التعيين للوسائط الافتراضية أو وسيطات الكلمات الرئيسية.
SPACES_AROUND_DICT_DELIMITERS
يضيف مسافة بعد محددات الإملاء الافتتاحية '{' وقبل النهاية '}'.
{ 1 : 2 }
سيتم تنسيقها على النحو التالي:
{ 1 : 2 }
SPACES_AROUND_LIST_DELIMITERS
لإضافة مسافة بعد محددات القائمة الافتتاحية '[' وقبل النهاية ']'.
[ 1 , 2 ]
سيتم تنسيقها على النحو التالي:
[ 1 , 2 ]
SPACES_AROUND_POWER_OPERATOR
اضبط على
True
لتفضيل استخدام المسافات حول**
.
SPACES_AROUND_SUBSCRIPT_COLON
استخدم المسافات حول عامل التشغيل المنخفض/الشريحة. على سبيل المثال:
my_list [ 1 : 10 : 2 ]
SPACES_AROUND_TUPLE_DELIMITERS
إضافة مسافة بعد محددات المجموعة الافتتاحية '(' وقبل النهاية ')'.
( 1 , 2 , 3 )
سيتم تنسيقها على النحو التالي:
( 1 , 2 , 3 )
SPACES_BEFORE_COMMENT
عدد المسافات المطلوبة قبل التعليق اللاحق. يمكن أن تكون هذه قيمة واحدة (تمثل عدد المسافات قبل كل تعليق لاحق) أو قائمة قيم (تمثل قيم أعمدة المحاذاة؛ سيتم محاذاة التعليقات اللاحقة داخل الكتلة إلى قيمة العمود الأول الأكبر من الحد الأقصى لطول السطر داخل الكتلة حاجز).
ملاحظة: قد يلزم ذكر قوائم القيم في بعض السياقات (على سبيل المثال، الأصداف أو ملفات تكوين المحرر).
على سبيل المثال، مع
spaces_before_comment=5
:
1 + 1 # Adding values
سيتم تنسيقها على النحو التالي:
1 + 1 # Adding values <-- 5 spaces between the end of the statement and comment
spaces_before_comment="15, 20"
:
1 + 1 # Adding values
two + two # More adding
longer_statement # This is a longer statement
short # This is a shorter statement
a_very_long_statement_that_extends_beyond_the_final_column # Comment
short # This is a shorter statement
سيتم تنسيقها على النحو التالي:
1 + 1 # Adding values <-- end of line comments in block aligned to col 15
two + two # More adding
longer_statement # This is a longer statement <-- end of line comments in block aligned to col 20
short # This is a shorter statement
a_very_long_statement_that_extends_beyond_the_final_column # Comment <-- the end of line comments are aligned based on the line length
short # This is a shorter statement
SPLIT_ALL_COMMA_SEPARATED_VALUES
إذا كانت هناك قائمة مفصولة بفواصل (
dict
، أوlist
، أوtuple
، أو functiondef
) على سطر طويل جدًا، فقم بتقسيمها بحيث يكون كل عنصر على سطر منفصل.
SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES
تباين في
SPLIT_ALL_COMMA_SEPARATED_VALUES
، حيث إذا كان التعبير الفرعي الذي يحتوي على فاصلة مناسبًا في سطر البداية الخاص به، فلن يتم تقسيم التعبير الفرعي. يؤدي هذا إلى تجنب الانقسامات مثل تلك الخاصة بـb
في هذا الكود:
abcdef (
aReallyLongThing : int ,
b : [ Int ,
Int ])
مع المقبض الجديد يتم تقسيم هذا على النحو التالي:
abcdef (
aReallyLongThing : int ,
b : [ Int , Int ])
SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED
قم بالتقسيم قبل الوسيطات إذا تم إنهاء قائمة الوسيطات بفاصلة.
SPLIT_BEFORE_ARITHMETIC_OPERATOR
اضبط على
True
لتفضيل التقسيم قبل+
أو-
أو*
أو/
أو//
أو@
وليس بعده.
SPLIT_BEFORE_BITWISE_OPERATOR
اضبط على
True
لتفضيل التقسيم قبل&
،|
أو^
بدلاً من بعد.
SPLIT_BEFORE_CLOSING_BRACKET
قم بالتقسيم قبل قوس الإغلاق إذا كانت
list
أوdict
لا يتناسب مع سطر واحد.
SPLIT_BEFORE_DICT_SET_GENERATOR
انقسم قبل القاموس أو قم بتعيين المولد (
comp_for
). على سبيل المثال، لاحظ التقسيم قبلfor
:
foo = {
variable : 'Hello world, have a nice day!'
for variable in bar if variable != 42
}
SPLIT_BEFORE_DOT
انقسام قبل
.
إذا أردنا تقسيم تعبير أطول:
foo = ( 'This is a really long string: {}, {}, {}, {}' . format ( a , b , c , d ))
سيتم إعادة التنسيق إلى شيء مثل:
foo = ( 'This is a really long string: {}, {}, {}, {}'
. format ( a , b , c , d ))
SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN
قم بالتقسيم بعد قوس الفتح الذي يحيط بالتعبير إذا لم يكن مناسبًا لسطر واحد.
SPLIT_BEFORE_FIRST_ARGUMENT
إذا كان سيتم تقسيم قائمة الوسائط/المعلمات، فقم بتقسيمها قبل الوسيطة الأولى.
SPLIT_BEFORE_LOGICAL_OPERATOR
اضبط على
True
لتفضيل التقسيم قبلand
or
من بعده.
SPLIT_BEFORE_NAMED_ASSIGNS
تقسيم المهام المسماة إلى أسطر فردية.
SPLIT_COMPLEX_COMPREHENSION
بالنسبة لفهم القائمة وتعبيرات المولدات التي تحتوي على عبارات متعددة (على سبيل المثال، متعددة
for
،if
تعبيرات التصفية) والتي تحتاج إلى إعادة التدفق، قم بتقسيم كل عبارة على سطر خاص بها. على سبيل المثال:
result = [
a_var + b_var for a_var in xrange ( 1000 ) for b_var in xrange ( 1000 )
if a_var % b_var ]
سيتم إعادة التنسيق إلى شيء مثل:
result = [
a_var + b_var
for a_var in xrange ( 1000 )
for b_var in xrange ( 1000 )
if a_var % b_var ]
SPLIT_PENALTY_AFTER_OPENING_BRACKET
عقوبة التقسيم مباشرة بعد قوس الافتتاح.
SPLIT_PENALTY_AFTER_UNARY_OPERATOR
عقوبة تقسيم الخط بعد المشغل الأحادي.
SPLIT_PENALTY_ARITHMETIC_OPERATOR
عقوبة تقسيم الخط حول عوامل التشغيل
+
و-
و*
و/
و//
و%
و@
.
SPLIT_PENALTY_BEFORE_IF_EXPR
عقوبة التقسيم مباشرة قبل تعبير
if
.
SPLIT_PENALTY_BITWISE_OPERATOR
عقوبة تقسيم الخط حول
&
,|
و^
عوامل التشغيل.
SPLIT_PENALTY_COMPREHENSION
عقوبة تقسيم فهم القائمة أو تعبير المولد.
SPLIT_PENALTY_EXCESS_CHARACTER
عقوبة الأحرف التي تتجاوز حد العمود.
SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT
العقوبة المتكبدة عن طريق إضافة خط منقسم إلى الخط المنطقي. كلما زاد عدد انقسامات الخط زادت العقوبة.
SPLIT_PENALTY_IMPORT_NAMES
عقوبة تقسيم قائمة
import as
كأسماء. على سبيل المثال:
from a_very_long_or_indented_module_name_yada_yad import ( long_argument_1 ,
long_argument_2 ,
long_argument_3 )
سيتم إعادة التنسيق إلى شيء مثل:
from a_very_long_or_indented_module_name_yada_yad import (
long_argument_1 , long_argument_2 , long_argument_3 )
SPLIT_PENALTY_LOGICAL_OPERATOR
عقوبة تقسيم الخط حول
and
وor
المشغلين.
USE_TABS
استخدم حرف Tab للمسافة البادئة.
تحاول YAPF جاهدة الحصول على التنسيق الصحيح. لكن بالنسبة لبعض التعليمات البرمجية، لن تكون بنفس جودة التنسيق اليدوي. على وجه الخصوص، قد تصبح البيانات الحرفية الكبيرة مشوهة بشكل رهيب تحت YAPF.
أسباب ذلك كثيرة. باختصار، YAPF هي مجرد أداة للمساعدة في التنمية. سيقوم بتنسيق الأشياء لتتوافق مع دليل الأسلوب، لكن هذا قد لا يعني سهولة القراءة.
ما يمكن فعله للتخفيف من هذا الموقف هو الإشارة إلى المناطق التي يجب على YAPF تجاهلها عند إعادة تنسيق شيء ما:
# yapf: disable
FOO = {
# ... some very large, complex data literal.
}
BAR = [
# ... another large data literal.
]
# yapf: enable
يمكنك أيضًا تعطيل التنسيق لحرف واحد مثل هذا:
BAZ = {
( 1 , 2 , 3 , 4 ),
( 5 , 6 , 7 , 8 ),
( 9 , 10 , 11 , 12 ),
} # yapf: disable
للحفاظ على أقواس الإغلاق المتعرجة، استخدم dedent_closing_brackets
في أسلوبك. لاحظ أنه في هذه الحالة، ستستخدم جميع الأقواس، بما في ذلك تعريفات الوظائف واستدعاءاتها، هذا النمط. وهذا يوفر الاتساق عبر قاعدة التعليمات البرمجية المنسقة.
أردنا استخدام خوارزمية إعادة التنسيق الخاصة بتنسيق clang. إنها قوية جدًا ومصممة للتوصل إلى أفضل تنسيق ممكن. تم إنشاء الأدوات الحالية مع وضع أهداف مختلفة في الاعتبار، وستتطلب تعديلات واسعة النطاق للتحويل إلى استخدام خوارزمية تنسيق clang.
من فضلك افعل! تم تصميم YAPF لاستخدامه كمكتبة بالإضافة إلى أداة لسطر الأوامر. هذا يعني أن الأداة أو البرنامج الإضافي IDE مجاني لاستخدام YAPF.
تحاول YAPF جاهدة أن تكون متوافقة تمامًا مع PEP 8. ومع ذلك، فمن الأهمية بمكان عدم المخاطرة بتغيير دلالات التعليمات البرمجية الخاصة بك. وبالتالي، تحاول YAPF أن تكون آمنة قدر الإمكان ولا تغير تدفق الرمز المميز (على سبيل المثال، عن طريق إضافة الأقواس). ومع ذلك، يمكن إصلاح كل هذه الحالات يدويًا بسهولة. على سبيل المثال،
from my_package import my_function_1 , my_function_2 , my_function_3 , my_function_4 , my_function_5
FOO = my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 + my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8
لن يتم تقسيمها، ولكن يمكنك تصحيحها بسهولة بمجرد إضافة الأقواس:
from my_package import ( my_function_1 , my_function_2 , my_function_3 ,
my_function_4 , my_function_5 )
FOO = ( my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 +
my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8 )
بنية البيانات الرئيسية في YAPF هي كائن LogicalLine
. إنه يحتوي على قائمة FormatToken
s، التي نرغب في وضعها على سطر واحد إذا لم يكن هناك حد للأعمدة. الاستثناء كونه تعليقًا في منتصف عبارة التعبير سيفرض تنسيق السطر على أكثر من سطر واحد. يعمل المنسق على كائن LogicalLine
واحد في كل مرة.
عادةً لن يؤثر الخط LogicalLine
على تنسيق الأسطر قبله أو بعده. يوجد جزء من الخوارزمية يمكنه ضم خطين أو أكثر من LogicalLine
في سطر واحد. على سبيل المثال، يمكن وضع عبارة if-then ذات النص القصير في سطر واحد:
if a == 42 : continue
تقوم خوارزمية التنسيق الخاصة بـ YAPF بإنشاء شجرة مرجحة تعمل كمساحة حل للخوارزمية. تمثل كل عقدة في الشجرة نتيجة قرار التنسيق --- أي ما إذا كان سيتم التقسيم أم لا قبل الرمز المميز. كل قرار تنسيق له تكلفة مرتبطة به. لذلك، يتم تحقيق التكلفة على الحافة بين العقدتين. (في الواقع، لا تحتوي الشجرة الموزونة على كائنات حافة منفصلة، وبالتالي فإن التكلفة تقع على العقد نفسها.)
على سبيل المثال، خذ مقتطف كود بايثون التالي. في هذا المثال، افترض أن السطر (1) ينتهك قيود حد الأعمدة ويحتاج إلى إعادة تنسيقه.
def xxxxxxxxxxx ( aaaaaaaaaaaa , bbbbbbbbb , cccccccc , dddddddd , eeeeee ): # 1
pass # 2
بالنسبة للسطر (1)، ستقوم الخوارزمية ببناء شجرة حيث تكون كل عقدة (كائن FormattingDecisionState
) هي حالة السطر عند ذلك الرمز المميز نظرًا لقرار التقسيم قبل الرمز المميز أم لا. ملاحظة: يتم نسخ كائنات FormatDecisionState
حسب القيمة بحيث تكون كل عقدة في الرسم البياني فريدة ولا يؤثر التغيير في إحداها على العقد الأخرى.
يتم استخدام الاستدلال لتحديد تكاليف التقسيم أو عدم التقسيم. نظرًا لأن العقدة تحتفظ بحالة الشجرة حتى إدخال الرمز المميز، فيمكنها بسهولة تحديد ما إذا كان قرار التقسيم سينتهك أحد متطلبات النمط. على سبيل المثال، يستطيع الاستدلال تطبيق عقوبة إضافية على الحافة عند عدم التقسيم بين الرمز المميز السابق والرمز الذي تتم إضافته.
هناك بعض الحالات التي لن نرغب فيها مطلقًا في تقسيم الخط، لأن القيام بذلك سيكون ضارًا دائمًا (على سبيل المثال، سيتطلب سطرًا جديدًا مائلًا عكسيًا، وهو أمر نادرًا ما يكون مرغوبًا فيه). بالنسبة للسطر (1)، لن نرغب أبدًا في تقسيم الرموز الثلاثة الأولى: def
و xxxxxxxxxxx
و (
. ولن نرغب في الفصل بين )
و :
في النهاية. ويقال إن هذه المناطق "غير قابلة للكسر". وينعكس هذا في الشجرة من خلال عدم وجود قرار "منقسم" (الفرع الأيسر) داخل المنطقة غير القابلة للكسر.
الآن بعد أن أصبح لدينا الشجرة، يمكننا تحديد التنسيق "الأفضل" من خلال إيجاد المسار عبر الشجرة بأقل تكلفة.
وهذا كل شيء!