YAPF adalah pemformat Python berdasarkan clang-format
(dikembangkan oleh Daniel Jasper). Intinya, algoritme mengambil kode dan menghitung pemformatan terbaik yang sesuai dengan gaya yang dikonfigurasi. Ini menghilangkan banyak kerumitan dalam memelihara kode Anda.
Tujuan utamanya adalah agar kode yang dihasilkan YAPF sama bagusnya dengan kode yang akan ditulis oleh seorang programmer jika mereka mengikuti panduan gaya.
Catatan YAPF bukanlah produk resmi Google (eksperimental atau lainnya), ini hanyalah kode yang dimiliki oleh Google.
Untuk menginstal YAPF dari PyPI:
$ pip install yapf
YAPF masih dianggap dalam tahap "beta", dan versi yang dirilis mungkin sering berubah; oleh karena itu, cara terbaik untuk tetap mengetahui perkembangan terkini adalah dengan mengkloning repositori ini atau menginstal langsung dari github:
$ pip install git+https://github.com/google/yapf.git
Perhatikan bahwa jika Anda ingin menggunakan YAPF sebagai alat baris perintah dan bukan sebagai pustaka, instalasi tidak diperlukan. YAPF mendukung dijalankan sebagai direktori oleh juru bahasa Python. Jika Anda mengkloning/membuka ritsleting YAPF ke DIR
, Anda dapat menjalankan:
$ PYTHONPATH=DIR python DIR/yapf [options] ...
YAPF didukung oleh banyak editor melalui ekstensi atau plugin komunitas. Lihat Dukungan Editor untuk info lebih lanjut.
YAPF mendukung Python 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
Biasanya YAPF mengembalikan nol pada penghentian program yang berhasil dan bukan nol sebaliknya.
Jika --diff
diberikan, YAPF mengembalikan nol ketika tidak ada perubahan yang diperlukan, sebaliknya bukan nol (termasuk kesalahan program). Anda dapat menggunakan ini dalam alur kerja CI untuk menguji apakah kode telah diformat YAPF.
Selain pola pengecualian yang disediakan pada baris perintah, YAPF mencari pola tambahan yang ditentukan dalam file bernama .yapfignore
atau pyproject.toml
yang terletak di direktori kerja tempat YAPF dipanggil.
Sintaks .yapfignore
mirip dengan pencocokan pola nama file UNIX:
* matches everything
? matches any single character
[seq] matches any character in seq
[!seq] matches any character not in seq
Perhatikan bahwa entri tidak boleh dimulai dengan ./
.
Jika Anda menggunakan pyproject.toml
, pola pengecualian ditentukan oleh kunci ignore_patterns
di bagian [tool.yapfignore]
. Misalnya:
[tool.yapfignore]
ignore_patterns = [
" temp/**/*.py " ,
" temp2/*.py "
]
Gaya pemformatan yang digunakan oleh YAPF dapat dikonfigurasi dan terdapat banyak "kenop" yang dapat digunakan untuk menyesuaikan cara YAPF melakukan pemformatan. Lihat modul style.py
untuk daftar lengkapnya.
Untuk mengontrol gaya, jalankan YAPF dengan argumen --style
. Ia menerima salah satu gaya yang telah ditentukan sebelumnya (misalnya, pep8
atau google
), jalur ke file konfigurasi yang menentukan gaya yang diinginkan, atau kamus pasangan kunci/nilai.
File konfigurasi adalah daftar sederhana dari pasangan key = value
(tidak peka huruf besar-kecil) dengan judul [style]
. Misalnya:
[style]
based_on_style = pep8
spaces_before_comment = 4
split_before_logical_operator = true
Setelan based_on_style
menentukan gaya standar mana yang menjadi dasar gaya khusus ini (anggap saja seperti subkelas). Empat gaya telah ditentukan sebelumnya:
pep8
(standar)google
(berdasarkan Panduan Gaya Google Python)yapf
(untuk digunakan dengan proyek sumber terbuka Google)facebook
Lihat _STYLE_NAME_TO_FACTORY
di style.py
untuk detailnya.
Hal yang sama juga dapat dilakukan pada baris perintah dengan kamus. Misalnya:
--style= ' {based_on_style: pep8, indent_width: 2} '
Ini akan mengambil gaya dasar pep8
dan memodifikasinya menjadi dua lekukan spasi.
YAPF akan mencari gaya pemformatan dengan cara berikut:
[style]
file .style.yapf
di direktori saat ini atau salah satu direktori induknya.[yapf]
pada file setup.cfg
di direktori saat ini atau salah satu direktori induknya.[tool.yapf]
pada file pyproject.toml
di direktori saat ini atau salah satu direktori induknya.[style]
file ~/.config/yapf/style
di direktori home Anda.Jika tidak ada file yang ditemukan, gaya default PEP8 akan digunakan.
Contoh tipe pemformatan yang dapat dilakukan YAPF, akan mengambil kode jelek ini:
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 ]
dan format ulang menjadi:
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 ]
Dua API utama untuk memanggil YAPF adalah FormatCode
dan FormatFile
, keduanya memiliki beberapa argumen yang dijelaskan di bawah ini:
> >> 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
Argumen style_config
: Nama gaya atau jalur ke file yang berisi pengaturan gaya pemformatan. Jika Tidak Ada yang ditentukan, gunakan gaya default seperti yang diatur dalam style.DEFAULT_STYLE_FACTORY
.
> >> FormatCode ( "def g(): n return True" , style_config = 'pep8' )[ 0 ]
'def g(): n return True n '
Argumen lines
: Daftar tupel baris (int), [awal, akhir], yang ingin kita format. Garis-garis tersebut diindeks berdasarkan 1. Ini dapat digunakan oleh kode pihak ketiga (misalnya, IDE) saat memformat ulang cuplikan kode, bukan keseluruhan file.
> >> 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): Daripada mengembalikan sumber yang diformat ulang, kembalikan diff yang mengubah sumber yang diformat menjadi sumber yang diformat ulang.
>>> print(FormatCode("a==b", filename="foo.py", print_diff=True)[0])
--- foo.py (original)
+++ foo.py (reformatted)
@@ -1 +1 @@
- a==b
+ a == b
Catatan: argumen filename
untuk FormatCode
adalah apa yang dimasukkan ke dalam diff, defaultnya adalah <unknown>
.
FormatFile
mengembalikan kode yang diformat ulang dari file yang diteruskan beserta pengkodeannya:
> >> 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
Argumen in_place
menyimpan kode yang telah diformat ulang kembali ke file:
> >> FormatFile ( "foo.py" , in_place = True )[: 2 ]
( None , 'utf-8' )
> >> print ( open ( "foo.py" ). read ()) # contents of file (now fixed)
a == b
Pilihan:
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
Sejajarkan braket penutup dengan lekukan visual.
ALLOW_MULTILINE_LAMBDAS
Izinkan lambda diformat pada lebih dari satu baris.
ALLOW_MULTILINE_DICTIONARY_KEYS
Izinkan kunci kamus ada di beberapa baris. Misalnya:
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
Izinkan pemisahan sebelum penetapan default/bernama dalam daftar argumen.
ALLOW_SPLIT_BEFORE_DICT_VALUE
Izinkan pemisahan sebelum nilai kamus.
ARITHMETIC_PRECEDENCE_INDICATION
Biarkan spasi menunjukkan prioritas operator. Misalnya:
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
akan diformat sebagai berikut untuk menunjukkan prioritas:
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
Menetapkan jumlah baris kosong yang diinginkan di sekitar fungsi tingkat atas dan definisi kelas. Misalnya:
class Foo :
pass
# <------ having two blank lines here
# <------ is the default setting
class Bar :
pass
BLANK_LINE_BEFORE_CLASS_DOCSTRING
Sisipkan baris kosong sebelum docstring tingkat kelas.
BLANK_LINE_BEFORE_MODULE_DOCSTRING
Sisipkan baris kosong sebelum docstring modul.
BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF
Sisipkan baris kosong sebelum
def
atauclass
yang langsung disarangkan ke dalamdef
atauclass
lain. Misalnya:
class Foo :
# <------ this blank line
def method ():
pass
BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES
Menetapkan jumlah baris kosong yang diinginkan antara impor tingkat atas dan definisi variabel. Berguna untuk kompatibilitas dengan alat seperti isort.
COALESCE_BRACKETS
Jangan memisahkan tanda kurung yang berurutan. Hanya relevan jika
DEDENT_CLOSING_BRACKETS
atauINDENT_CLOSING_BRACKETS
disetel. Misalnya:
call_func_that_takes_a_dict (
{
'key1' : 'value1' ,
'key2' : 'value2' ,
}
)
akan memformat ulang menjadi:
call_func_that_takes_a_dict ({
'key1' : 'value1' ,
'key2' : 'value2' ,
})
COLUMN_LIMIT
Batas kolom (atau panjang garis maksimal)
CONTINUATION_ALIGN_STYLE
Gaya untuk penyelarasan lanjutan. Nilai yang mungkin adalah:
SPACE
: Gunakan spasi untuk penyelarasan lanjutan. Ini adalah perilaku default.FIXED
: Gunakan jumlah kolom yang tetap (CONTINUATION_INDENT_WIDTH
) (yaitu tabCONTINUATION_INDENT_WIDTH
/INDENT_WIDTH
atau spasiCONTINUATION_INDENT_WIDTH
) untuk penyelarasan lanjutan.VALIGN-RIGHT
: Menyejajarkan garis lanjutan secara vertikal ke beberapa kolomINDENT_WIDTH
. Sedikit ke kanan (satu tab atau beberapa spasi) jika tidak dapat menyelaraskan garis lanjutan secara vertikal dengan karakter indent.
CONTINUATION_INDENT_WIDTH
Lebar indentasi digunakan untuk kelanjutan garis.
DEDENT_CLOSING_BRACKETS
Letakkan tanda kurung tutup pada baris terpisah, dedented, jika ekspresi dalam tanda kurung tidak muat dalam satu baris. Berlaku untuk semua jenis tanda kurung, termasuk definisi fungsi dan panggilan. Misalnya:
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
Nonaktifkan heuristik yang menempatkan setiap elemen daftar pada baris terpisah jika daftar diakhiri dengan koma.
Catatan: Perilaku tanda ini berubah di v0.40.3. Sebelumnya, jika tanda ini benar, kami akan membagi daftar yang berisi tanda koma atau komentar. Sekarang, kami memiliki tanda terpisah,
DISABLE_SPLIT_LIST_WITH_COMMENT
, yang mengontrol pemisahan ketika daftar berisi komentar. Untuk mendapatkan perilaku lama, setel kedua tanda ke true. Informasi lebih lanjut di CHANGELOG.md.
DISABLE_SPLIT_LIST_WITH_COMMENT
Jangan letakkan setiap elemen pada baris baru dalam daftar yang berisi komentar pengantara.
Tanpa tanda ini (default):
[ a, b, # c ]
Dengan bendera ini:
[ a, b, # c ]
Ini mencerminkan perilaku format dentang dan berguna untuk membentuk "kelompok logis" elemen dalam daftar. Ini juga berfungsi dalam deklarasi fungsi.
EACH_DICT_ENTRY_ON_SEPARATE_LINE
Tempatkan setiap entri kamus pada barisnya masing-masing.
FORCE_MULTILINE_DICT
Hormati
EACH_DICT_ENTRY_ON_SEPARATE_LINE
meskipun garisnya lebih pendek dariCOLUMN_LIMIT
.
I18N_COMMENT
Regex untuk komentar internasionalisasi. Kehadiran komentar ini menghentikan pemformatan ulang baris tersebut, karena komentar harus berada di sebelah string yang diterjemahkannya.
I18N_FUNCTION_CALL
Nama panggilan fungsi internasionalisasi. Kehadiran fungsi ini menghentikan format ulang pada baris tersebut, karena string yang dimilikinya tidak dapat dipindahkan dari komentar i18n.
INDENT_BLANK_LINES
Atur ke
True
untuk memilih baris kosong yang menjorok ke dalam daripada kosong
INDENT_CLOSING_BRACKETS
Letakkan tanda kurung tutup pada baris terpisah, dengan menjorok ke dalam, jika ekspresi dalam tanda kurung tidak dapat dimuat dalam satu baris. Berlaku untuk semua jenis tanda kurung, termasuk definisi fungsi dan panggilan. Misalnya:
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
Indentasi nilai kamus jika tidak dapat ditempatkan pada baris yang sama dengan kunci kamus. Misalnya:
config = {
'key1' :
'value1' ,
'key2' : value1 +
value2 ,
}
INDENT_WIDTH
Jumlah kolom yang digunakan untuk indentasi.
JOIN_MULTIPLE_LINES
Gabungkan garis-garis pendek menjadi satu garis. Misalnya, pernyataan
if
satu baris.
NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS
Jangan sertakan spasi di sekitar operator biner yang dipilih. Misalnya:
1 + 2 * 3 - 4 / 5
akan diformat sebagai berikut ketika dikonfigurasi dengan
*
,/
:
1 + 2 * 3 - 4 / 5
SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET
Menyisipkan spasi di antara koma akhir dan tanda kurung tutup daftar, dll.
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
Atur ke
True
untuk memilih spasi di sekitar operator penugasan untuk argumen default atau kata kunci.
SPACES_AROUND_DICT_DELIMITERS
Menambahkan spasi setelah pembatas dict pembuka '{' dan sebelum akhiran '}'.
{ 1 : 2 }
akan diformat sebagai:
{ 1 : 2 }
SPACES_AROUND_LIST_DELIMITERS
Menambahkan spasi setelah pembatas daftar '[' pembuka dan sebelum akhiran ']'.
[ 1 , 2 ]
akan diformat sebagai:
[ 1 , 2 ]
SPACES_AROUND_POWER_OPERATOR
Setel ke
True
untuk memilih menggunakan spasi di sekitar**
.
SPACES_AROUND_SUBSCRIPT_COLON
Gunakan spasi di sekitar operator subskrip/irisan. Misalnya:
my_list [ 1 : 10 : 2 ]
SPACES_AROUND_TUPLE_DELIMITERS
Menambahkan spasi setelah pembatas tuple pembuka '(' dan sebelum akhir ')'.
( 1 , 2 , 3 )
akan diformat sebagai:
( 1 , 2 , 3 )
SPACES_BEFORE_COMMENT
Jumlah spasi yang diperlukan sebelum komentar tambahan. Ini bisa berupa nilai tunggal (mewakili jumlah spasi sebelum setiap komentar di akhir) atau daftar nilai (mewakili nilai kolom penyelarasan; komentar di akhir dalam blok akan disejajarkan dengan nilai kolom pertama yang lebih besar dari panjang baris maksimum dalam memblokir).
Catatan: Daftar nilai mungkin perlu dikutip dalam beberapa konteks (misalnya shell atau file konfigurasi editor).
Misalnya, dengan
spaces_before_comment=5
:
1 + 1 # Adding values
akan diformat sebagai:
1 + 1 # Adding values <-- 5 spaces between the end of the statement and comment
dengan
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
akan diformat sebagai:
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
Jika daftar yang dipisahkan koma (
dict
,list
,tuple
, atau functiondef
) berada pada baris yang terlalu panjang, pisahkan sedemikian rupa sehingga setiap elemen berada pada baris terpisah.
SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES
Variasi pada
SPLIT_ALL_COMMA_SEPARATED_VALUES
yang mana, jika subekspresi dengan koma pas di garis awalnya, maka subekspresi tersebut tidak dipecah. Ini menghindari perpecahan seperti yang terjadi padab
dalam kode ini:
abcdef (
aReallyLongThing : int ,
b : [ Int ,
Int ])
dengan kenop baru ini dibagi menjadi:
abcdef (
aReallyLongThing : int ,
b : [ Int , Int ])
SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED
Pisahkan sebelum argumen jika daftar argumen diakhiri dengan koma.
SPLIT_BEFORE_ARITHMETIC_OPERATOR
Setel ke
True
untuk memilih pemisahan sebelum+
,-
,*
,/
,//
, atau@
daripada setelahnya.
SPLIT_BEFORE_BITWISE_OPERATOR
Setel ke
True
untuk memilih pemisahan sebelum&
,|
atau^
daripada setelahnya.
SPLIT_BEFORE_CLOSING_BRACKET
Pisahkan sebelum tanda kurung tutup jika
list
ataudict
literal tidak muat dalam satu baris.
SPLIT_BEFORE_DICT_SET_GENERATOR
Pisahkan sebelum kamus atau set generator (
comp_for
). Misalnya, perhatikan pemisahan sebelumfor
:
foo = {
variable : 'Hello world, have a nice day!'
for variable in bar if variable != 42
}
SPLIT_BEFORE_DOT
Berpisah sebelum
.
jika kita perlu membagi ekspresi yang lebih panjang:
foo = ( 'This is a really long string: {}, {}, {}, {}' . format ( a , b , c , d ))
akan memformat ulang menjadi sesuatu seperti:
foo = ( 'This is a really long string: {}, {}, {}, {}'
. format ( a , b , c , d ))
SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN
Pisahkan setelah tanda kurung pembuka yang mengelilingi ekspresi jika tidak muat dalam satu baris.
SPLIT_BEFORE_FIRST_ARGUMENT
Jika suatu argumen/daftar parameter akan dipecah, maka pisahkan sebelum argumen pertama.
SPLIT_BEFORE_LOGICAL_OPERATOR
Atur ke
True
untuk memilih pemisahan sebelumand
or
daripada setelahnya.
SPLIT_BEFORE_NAMED_ASSIGNS
Pisahkan tugas bernama ke dalam baris individual.
SPLIT_COMPLEX_COMPREHENSION
Untuk pemahaman daftar dan ekspresi generator dengan beberapa klausa (misalnya beberapa
for
,if
ekspresi filter) dan yang perlu dialirkan ulang, pisahkan setiap klausa ke dalam barisnya masing-masing. Misalnya:
result = [
a_var + b_var for a_var in xrange ( 1000 ) for b_var in xrange ( 1000 )
if a_var % b_var ]
akan memformat ulang menjadi sesuatu seperti:
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
Hukuman untuk split tepat setelah braket pembuka.
SPLIT_PENALTY_AFTER_UNARY_OPERATOR
Hukuman untuk memisahkan garis setelah operator unary.
SPLIT_PENALTY_ARITHMETIC_OPERATOR
Hukuman pemisahan garis di sekitar operator
+
,-
,*
,/
,//
,%
, dan@
.
SPLIT_PENALTY_BEFORE_IF_EXPR
Hukuman untuk pemisahan tepat sebelum ekspresi
if
.
SPLIT_PENALTY_BITWISE_OPERATOR
Hukuman membagi garis di sekitar
&
,|
, dan^
operator.
SPLIT_PENALTY_COMPREHENSION
Hukuman untuk memisahkan pemahaman daftar atau ekspresi generator.
SPLIT_PENALTY_EXCESS_CHARACTER
Hukuman untuk karakter melebihi batas kolom.
SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT
Penalti yang timbul dengan menambahkan pemisahan garis ke garis logis. Semakin banyak pembagian garis yang ditambahkan, semakin tinggi penaltinya.
SPLIT_PENALTY_IMPORT_NAMES
Hukuman pemisahan daftar
import as
nama. Misalnya:
from a_very_long_or_indented_module_name_yada_yad import ( long_argument_1 ,
long_argument_2 ,
long_argument_3 )
akan memformat ulang menjadi sesuatu seperti:
from a_very_long_or_indented_module_name_yada_yad import (
long_argument_1 , long_argument_2 , long_argument_3 )
SPLIT_PENALTY_LOGICAL_OPERATOR
Hukuman pemisahan garis di sekitar
and
danor
operator.
USE_TABS
Gunakan karakter Tab untuk lekukan.
YAPF berusaha keras untuk mendapatkan format yang benar. Namun untuk beberapa kode, ini tidak akan sebaik pemformatan tangan. Secara khusus, literal data berukuran besar mungkin menjadi rusak parah di bawah YAPF.
Alasannya bermacam-macam. Singkatnya, YAPF hanyalah sebuah alat untuk membantu pembangunan. Ini akan memformat sesuatu agar sesuai dengan panduan gaya, tapi itu mungkin tidak sama dengan keterbacaan.
Apa yang dapat dilakukan untuk mengatasi situasi ini adalah dengan menunjukkan wilayah yang harus diabaikan oleh YAPF ketika memformat ulang sesuatu:
# yapf: disable
FOO = {
# ... some very large, complex data literal.
}
BAR = [
# ... another large data literal.
]
# yapf: enable
Anda juga dapat menonaktifkan pemformatan untuk satu literal seperti ini:
BAZ = {
( 1 , 2 , 3 , 4 ),
( 5 , 6 , 7 , 8 ),
( 9 , 10 , 11 , 12 ),
} # yapf: disable
Untuk mempertahankan tanda kurung tutup yang bagus, gunakan dedent_closing_brackets
dalam gaya Anda. Perhatikan bahwa dalam kasus ini semua tanda kurung, termasuk definisi fungsi dan panggilan, akan menggunakan gaya tersebut. Hal ini memberikan konsistensi di seluruh basis kode yang diformat.
Kami ingin menggunakan algoritma pemformatan ulang clang-format. Ini sangat kuat dan dirancang untuk menghasilkan format terbaik. Alat yang ada dibuat dengan tujuan yang berbeda-beda, dan akan memerlukan modifikasi ekstensif untuk mengubahnya menggunakan algoritma format dentang.
Silakan lakukan! YAPF dirancang untuk digunakan sebagai perpustakaan serta alat baris perintah. Artinya suatu alat atau plugin IDE bebas menggunakan YAPF.
YAPF berusaha keras untuk sepenuhnya mematuhi PEP 8. Namun, yang terpenting adalah tidak mengambil risiko mengubah semantik kode Anda. Oleh karena itu, YAPF berusaha seaman mungkin dan tidak mengubah aliran token (misalnya, dengan menambahkan tanda kurung). Namun semua kasus ini dapat dengan mudah diperbaiki secara manual. Misalnya,
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
tidak akan dipecah, namun Anda dapat dengan mudah memperbaikinya hanya dengan menambahkan tanda kurung:
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 )
Struktur data utama di YAPF adalah objek LogicalLine
. Ini menyimpan daftar FormatToken
s, yang ingin kita tempatkan pada satu baris jika tidak ada batasan kolom. Pengecualian berupa komentar di tengah pernyataan ekspresi akan memaksa baris diformat lebih dari satu baris. Pemformat bekerja pada satu objek LogicalLine
dalam satu waktu.
LogicalLine
biasanya tidak akan memengaruhi pemformatan baris sebelum atau sesudahnya. Ada bagian dari algoritma yang dapat menggabungkan dua atau lebih LogicalLine
s menjadi satu baris. Misalnya, pernyataan if-then dengan isi pendek dapat ditempatkan pada satu baris:
if a == 42 : continue
Algoritma pemformatan YAPF menciptakan pohon berbobot yang bertindak sebagai ruang solusi untuk algoritma tersebut. Setiap node di pohon mewakili hasil keputusan pemformatan --- yaitu, apakah akan dipecah atau tidak sebelum token. Setiap keputusan pemformatan memiliki biaya yang terkait dengannya. Oleh karena itu, biaya direalisasikan pada tepi antara dua node. (Pada kenyataannya, pohon berbobot tidak memiliki objek tepi yang terpisah, sehingga biayanya berada pada node itu sendiri.)
Misalnya, ambil cuplikan kode Python berikut. Demi contoh ini, asumsikan bahwa baris (1) melanggar batasan batas kolom dan perlu diformat ulang.
def xxxxxxxxxxx ( aaaaaaaaaaaa , bbbbbbbbb , cccccccc , dddddddd , eeeeee ): # 1
pass # 2
Untuk baris (1), algoritme akan membangun pohon di mana setiap node (objek FormattingDecisionState
) adalah status garis pada token tersebut dengan keputusan untuk dipecah sebelum token atau tidak. Catatan: objek FormatDecisionState
disalin berdasarkan nilai sehingga setiap node dalam grafik bersifat unik dan perubahan pada salah satu node tidak memengaruhi node lainnya.
Heuristik digunakan untuk menentukan biaya pemisahan atau tidak pemisahan. Karena sebuah node menyimpan status pohon hingga penyisipan token, node tersebut dapat dengan mudah menentukan apakah keputusan pemisahan akan melanggar salah satu persyaratan gaya. Misalnya, heuristik dapat menerapkan penalti tambahan pada tepian ketika tidak memisahkan antara token sebelumnya dan token yang ditambahkan.
Ada beberapa contoh di mana kita tidak ingin membagi garis, karena hal ini akan selalu merugikan (yaitu, memerlukan garis miring terbalik-baris baru, yang sangat jarang diinginkan). Untuk baris (1), kita tidak ingin membagi tiga token pertama: def
, xxxxxxxxxxx
, dan (
. Kita juga tidak ingin membagi antara )
dan :
di akhir. Daerah-daerah ini dikatakan “tidak dapat dipecahkan”. Hal ini tercermin pada pohon dengan tidak adanya keputusan "terpisah" (cabang kiri) dalam wilayah yang tidak dapat dipecahkan.
Sekarang setelah kita memiliki pohonnya, kita menentukan format apa yang "terbaik" dengan mencari jalur melalui pohon dengan biaya terendah.
Dan itu saja!