Merge branch 'google:gh-pages' into gh-pages

This commit is contained in:
Tien Nguyen Minh 2024-02-29 16:34:12 +07:00 committed by GitHub
commit 888f2a9bcb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 3779 additions and 2048 deletions

View File

@ -21,8 +21,8 @@ this power brings with it complexity, which in turn can make
code more bug-prone and harder to read and maintain.</p>
<p>The goal of this guide is to manage this complexity by
describing in detail the dos and don'ts of writing C++ code
. These rules exist to
describing in detail the dos and don'ts of writing C++
code. These rules exist to
keep the code base manageable while still allowing
coders to use C++ language features productively.</p>
@ -164,9 +164,8 @@ input.</p>
<h2 id="C++_Version">C++ Version</h2>
<p>Currently, code should target C++17, i.e., should not use C++2x
features, with the exception of <a href="#Designated_initializers">designated
initializers</a>. The C++ version targeted by this guide will advance
<p>Currently, code should target C++20, i.e., should not use C++23
features. The C++ version targeted by this guide will advance
(aggressively) over time.</p>
@ -176,7 +175,7 @@ input.</p>
<div>
<p>Consider portability to other environments before using features
from C++14 and C++17 in your project.</p>
from C++17 and C++20 in your project.</p>
</div>
<h2 id="Header_Files">Header Files</h2>
@ -415,6 +414,18 @@ should be included as:</p>
<pre>#include "base/logging.h"
</pre>
<p>Headers should only be included using an angle-bracketed path if the library
requires you to do so. In particular, the following headers require angle
brackets:</p>
<ul>
<li>C and C++ standard library headers (e.g. <code>&lt;stdlib.h&gt;</code>
and <code>&lt;string&gt;</code>).</li>
<li>POSIX, Linux, and Windows system headers (e.g. <code>&lt;unistd.h&gt;</code>
and <code>&lt;windows.h&gt;</code>).</li>
<li>In rare cases, third_party libraries (e.g. <code>&lt;Python.h&gt;</code>).</li>
</ul>
<p>In <code><var>dir/foo</var>.cc</code> or
<code><var>dir/foo_test</var>.cc</code>, whose main
purpose is to implement or test the stuff in
@ -426,9 +437,9 @@ as follows:</p>
<li>A blank line</li>
<li>C system headers (more precisely: headers in angle brackets with the
<code>.h</code> extension), e.g., <code>&lt;unistd.h&gt;</code>,
<code>&lt;stdlib.h&gt;</code>.</li>
<li>C system headers, and any other headers in angle brackets with the
<code>.h</code> extension, e.g., <code>&lt;unistd.h&gt;</code>,
<code>&lt;stdlib.h&gt;</code>, <code>&lt;Python.h&gt;</code>.</li>
<li>A blank line</li>
@ -664,9 +675,9 @@ namespace baz = ::foo::bar::baz;
<pre>// Shorten access to some commonly used names (in a .h file).
namespace librarian {
namespace impl { // Internal, not part of the API.
namespace internal { // Internal, not part of the API.
namespace sidetable = ::pipeline_diagnostics::sidetable;
} // namespace impl
} // namespace internal
inline void my_inline_function() {
// namespace alias local to a function (or method).
@ -686,6 +697,11 @@ inline void my_inline_function() {
using ::absl::container_internal::ImplementationDetail;
</pre>
</li>
<li><p>Single-line nested namespace declarations
are preferred in new code, but are not required.</p>
</li>
</ul>
<a id="Unnamed_Namespaces_and_Static_Variables"></a>
@ -932,7 +948,7 @@ the formal language of the C++ standard. It means that the initializing
expression is a constant expression, and if the object is initialized by a
constructor call, then the constructor must be specified as
<code>constexpr</code>, too:</p>
<pre>struct Foo { constexpr Foo(int) {} };
<pre class="goodcode">struct Foo { constexpr Foo(int) {} };
int n = 5; // Fine, 5 is a constant expression.
Foo x(2); // Fine, 2 is a constant expression and the chosen constructor is constexpr.
@ -940,12 +956,8 @@ Foo a[] = { Foo(1), Foo(2), Foo(3) }; // Fine</pre>
<p>Constant initialization is always allowed. Constant initialization of
static storage duration variables should be marked with <code>constexpr</code>
or where possible the
<a href="https://github.com/abseil/abseil-cpp/blob/03c1513538584f4a04d666be5eb469e3979febba/absl/base/attributes.h#L540">
<code>ABSL_CONST_INIT</code></a>
attribute. Any non-local static storage
or <code>constinit</code>.
Any non-local static storage
duration variable that is not so marked should be presumed to have
dynamic initialization, and reviewed very carefully.</p>
@ -1017,10 +1029,8 @@ does not make an observable difference. For example:</p>
<p><code>thread_local</code> variables that aren't declared inside a function
must be initialized with a true compile-time constant,
and this must be enforced by using the
<a href="https://github.com/abseil/abseil-cpp/blob/master/absl/base/attributes.h">
<code>ABSL_CONST_INIT</code></a>
<a href="https://en.cppreference.com/w/cpp/language/constinit">
<code>constinit</code></a>
attribute. Prefer
<code>thread_local</code> over other ways of defining thread-local data.</p>
@ -1093,13 +1103,11 @@ get a particularly hard to diagnose use-after-free.</p>
initialized with a true compile-time constant (i.e., they must have no
dynamic initialization). To enforce this, <code>thread_local</code> variables
at class or namespace scope must be annotated with
<a href="https://github.com/abseil/abseil-cpp/blob/master/absl/base/attributes.h">
<code>ABSL_CONST_INIT</code></a>
<a href="https://en.cppreference.com/w/cpp/language/constinit">
<code>constinit</code></a>
(or <code>constexpr</code>, but that should be rare):</p>
<pre> ABSL_CONST_INIT thread_local Foo foo = ...;
<pre> constinit thread_local Foo foo = ...;
</pre>
<p><code>thread_local</code> variables inside a function have no initialization
@ -1177,8 +1185,7 @@ for your code ,
terminating the program may be an appropriate error handling
response. Otherwise, consider a factory function
or <code>Init()</code> method as described in
<a href="https://abseil.io/tips/42">TotW #42</a>
.
<a href="https://abseil.io/tips/42">TotW #42</a>.
Avoid <code>Init()</code> methods on objects with
no other states that affect which public methods may be called
(semi-constructed objects of this form are particularly hard to work
@ -1445,8 +1452,6 @@ by making their constructors protected, by declaring their destructors protected
or by giving them one or more pure virtual member functions. Prefer to avoid
deriving from concrete classes.</p>
<h3 id="Structs_vs._Classes">Structs vs. Classes</h3>
<p>Use a <code>struct</code> only for passive objects that
@ -1466,9 +1471,9 @@ break those invariants. Constructors, destructors, and helper methods may
be present; however, these methods must not require or enforce any
invariants.</p>
<p>If more functionality or invariants are required, a
<code>class</code> is more appropriate. If in doubt, make
it a <code>class</code>.</p>
<p>If more functionality or invariants are required, or struct has wide visibility and expected to
evolve, then a <code>class</code> is more appropriate. If in doubt, make it a <code>class</code>.
</p>
<p>For consistency with STL, you can use
<code>struct</code> instead of <code>class</code> for
@ -1678,17 +1683,23 @@ definitions. If possible, avoid defining operators as templates,
because they must satisfy this rule for any possible template
arguments. If you define an operator, also define
any related operators that make sense, and make sure they
are defined consistently. For example, if you overload
<code>&lt;</code>, overload all the comparison operators,
and make sure <code>&lt;</code> and <code>&gt;</code> never
return true for the same arguments.</p>
are defined consistently.</p>
<p>Prefer to define non-modifying binary operators as
non-member functions. If a binary operator is defined as a
class member, implicit conversions will apply to the
right-hand argument, but not the left-hand one. It will
confuse your users if <code>a &lt; b</code> compiles but
<code>b &lt; a</code> doesn't.</p>
confuse your users if <code>a + b</code> compiles but
<code>b + a</code> doesn't.</p>
<p>For a type <code>T</code> whose values can be compared for
equality, define a non-member <code>operator==</code> and document when
two values of type <code>T</code> are considered equal.
If there is a single obvious notion of when a value <code>t1</code>
of type <code>T</code> is less than another such value <code>t2</code> then
you may also define <code>operator&lt;=&gt;</code>, which should be
consistent with <code>operator==</code>.
Prefer not to overload the other comparison and ordering operators.</p>
<p>Don't go out of your way to avoid defining operator
overloads. For example, prefer to define <code>==</code>,
@ -1788,7 +1799,7 @@ improve readability, and often provide the same or better
performance.</p>
<p>Prefer to return by value or, failing that, return by reference.
Avoid returning a pointer unless it can be null.</p>
Avoid returning a raw pointer unless it can be null.</p>
<p>Parameters are either inputs to the function, outputs from the
function, or both. Non-optional input parameters should usually be values
@ -1802,10 +1813,10 @@ optional outputs and optional input/output parameters.</p>
<p>
Avoid defining functions that require a <code>const</code> reference parameter
to outlive the call, because <code>const</code> reference parameters bind
to temporaries. Instead, find a way to eliminate the lifetime requirement
(for example, by copying the parameter), or pass it by <code>const</code>
Avoid defining functions that require a reference parameter to outlive the call.
In some cases reference parameters can bind to temporaries, leading to lifetime
bugs. Instead, find a way to eliminate the lifetime requirement
(for example, by copying the parameter), or pass retained parameters by
pointer and document the lifetime and non-null requirements.
</p>
@ -2249,10 +2260,10 @@ qualifier to methods), except as follows:</p>
<li>You may use them to define pairs of overloads, such as one taking
<code>Foo&amp;&amp;</code> and the other taking <code>const Foo&amp;</code>.
Usually the preferred solution is just to pass by value, but an overloaded
pair of functions sometimes yields better performance and is sometimes
necessary in generic code that needs to support a wide variety of types.
As always: if you're writing more complicated code for the sake of
performance, make sure you have evidence that it actually helps.</li>
pair of functions sometimes yields better performance, for example if the
functions sometimes don't consume the input. As always: if you're writing
more complicated code for the sake of performance, make sure you have evidence
that it actually helps.</li>
</ul>
<h3 id="Friends">Friends</h3>
@ -2636,9 +2647,9 @@ casts when explicit type conversion is necessary.
including <code>void*</code>. Use this
only if you know what you are doing and you understand the aliasing
issues. Also, consider dereferencing the pointer (without a cast) and
using <code>absl::bit_cast</code> to cast the resulting value.</li>
using <code>std::bit_cast</code> to cast the resulting value.</li>
<li>Use <code>absl::bit_cast</code> to interpret the raw bits of a
<li>Use <code>std::bit_cast</code> to interpret the raw bits of a
value using a different type of the same size (a type pun), such as
interpreting the bits of a <code>double</code> as
<code>int64_t</code>.</li>
@ -2874,10 +2885,13 @@ putting the "adjective" (<code>const</code>) before the
<code>const</code> first, we do not require it. But be
consistent with the code around you!</p>
<h3 id="Use_of_constexpr">Use of constexpr</h3>
<h3 id="Use_of_constexpr">Use of constexpr, constinit, and consteval</h3>
<p>Use <code>constexpr</code> to define true
constants or to ensure constant initialization.</p>
constants or to ensure constant initialization.
Use <code>constinit</code> to ensure constant
initialization for non-constant variables.
</p>
<p class="definition"></p>
<p> Some variables can be declared <code>constexpr</code>
@ -2885,7 +2899,8 @@ to indicate the variables are true constants, i.e., fixed at
compilation/link time. Some functions and constructors
can be declared <code>constexpr</code> which enables them
to be used in defining a <code>constexpr</code>
variable.</p>
variable. Functions can be declared <code>consteval</code>
to restrict their use to compile time.</p>
<p class="pros"></p>
<p>Use of <code>constexpr</code> enables definition of
@ -2906,9 +2921,11 @@ in these definitions.</p>
robust specification of the constant parts of an
interface. Use <code>constexpr</code> to specify true
constants and the functions that support their
definitions. Avoid complexifying function definitions to
definitions. <code>consteval</code> may be used for
code that must not be invoked at runtime.
Avoid complexifying function definitions to
enable their use with <code>constexpr</code>. Do not use
<code>constexpr</code> to force inlining.</p>
<code>constexpr</code> or <code>consteval</code> to force inlining.</p>
<h3 id="Integer_Types">Integer Types</h3>
@ -2948,7 +2965,9 @@ like <code>int16_t</code>, <code>uint32_t</code>,
<code>int64_t</code>, etc. You should always use
those in preference to <code>short</code>, <code>unsigned
long long</code> and the like, when you need a guarantee
on the size of an integer. Of the built-in integer types, only
on the size of an integer. Prefer to omit the <code>std::</code>
prefix for these types, as the extra 5 characters do
not merit the added clutter. Of the built-in integer types, only
<code>int</code> should be used. When appropriate, you
are welcome to use standard type aliases like
<code>size_t</code> and <code>ptrdiff_t</code>.</p>
@ -3148,7 +3167,6 @@ possible:</p>
<li>Prefer not using <code>##</code> to generate
function/class/variable names.</li>
</ul>
<p>Exporting macros from headers (i.e., defining them in a header
@ -3230,8 +3248,8 @@ auto c = b; // c is an int
auto d{42}; // d is an int, not a std::initializer_list&lt;int&gt;
</pre>
<code>auto</code> can be qualified with <code>const</code>, and can be
used as part of a pointer or reference type, but it can't be used as a
template argument. A rare variant of this syntax uses
used as part of a pointer or reference type, and (since C++17) as a
non-type template argument. A rare variant of this syntax uses
<code>decltype(auto)</code> instead of <code>auto</code>, in which case
the deduced type is the result of applying
<a href="https://en.cppreference.com/w/cpp/language/decltype"><code>decltype</code></a>
@ -3525,8 +3543,8 @@ ordering of fields than the <code>Point</code> example above.</p>
<p class="cons"></p>
<p>While designated initializers have long been part of the C standard and
supported by C++ compilers as an extension, only recently have they made it
into the C++ standard, being added as part of C++20.</p>
supported by C++ compilers as an extension, they were not supported by
C++ prior to C++20.</p>
<p>The rules in the C++ standard are stricter than in C and compiler extensions,
requiring that the designated initializers appear in the same order as the
@ -3768,6 +3786,113 @@ error messages are part of your user interface, and your code should
be tweaked as necessary so that the error messages are understandable
and actionable from a user point of view.</p>
<h3 id="Concepts">Concepts and Constraints</h3>
<p>Use concepts sparingly.
In general, concepts and constraints should only be used in cases
where templates would have been used prior to C++20.
Avoid introducing new concepts in headers,
unless the headers are marked as internal to the library.
Do not define concepts that are not enforced by the compiler.
Prefer constraints over template metaprogramming, and
avoid the <code>template&lt;<i>Concept</i> T&gt;</code> syntax;
instead, use the <code>requires(<i>Concept&lt;T&gt;</i>)</code>
syntax.</p>
<p class="definition"></p>
<p>The <code>concept</code> keyword is a new mechanism for defining
requirements (such as type traits or interface specifications)
for a template parameter.
The <code>requires</code> keyword provides mechanisms for placing
anonymous constraints on templates and verifying that constraints
are satisfied at compile time.
Concepts and constraints are often used together, but can be
also used independently.</p>
<p class="pros"></p>
<ul>
<li>Concepts allow the compiler to generate much better error
messages when templates are involved, which can reduce confusion
and significantly improve the development experience.</li>
<li>Concepts can reduce the boilerplate necessary for defining
and using compile-time constraints, often increasing the clarity
of the resulting code.</li>
<li>Constraints provide some capabilities that are difficult to
achieve with templates and SFINAE techniques.</li>
</ul>
<p class="cons"></p>
<ul>
<li>As with templates, concepts can make code significantly more
complex and difficult to understand.</li>
<li>Concept syntax can be confusing to readers, as concepts
appear similar to class types at their usage sites.</li>
<li>Concepts, especially at API boundaries, increase code
coupling, rigidity, and ossification.</li>
<li>Concepts and constraints can replicate logic from a function
body, resulting in code duplication and increased maintenance
costs.</li>
<li>Concepts muddy the source of truth for their underlying
contracts, as they are standalone named entities that can be
utilized in multiple locations, all of which evolve separately
from each other.
This can cause the stated and implied requirements to diverge
over time.</li>
<li>Concepts and constraints affect overload resolution in novel
and non-obvious ways.</li>
<li>As with SFINAE, constraints make it harder to refactor code
at scale.</li>
</ul>
<p class="decision"></p>
<p>Predefined concepts in the standard library should be
preferred to type traits, when equivalent ones exist.
(e.g., if <code>std::is_integral_v</code> would have been used
before C++20, then <code>std::integral</code> should be used in
C++20 code.)
Similarly, prefer modern constraint syntax
(via <code>requires(<i>Condition</i>)</code>).
Avoid legacy template metaprogramming constructs
(such as <code>std::enable_if&lt;<i>Condition</i>&gt;</code>)
as well as the <code>template&lt;<i>Concept</i> T&gt;</code>
syntax.</p>
<p>Do not manually re-implement any existing concepts or traits.
For example, use
<code>requires(std::default_initializable&lt;T&gt;)</code>
instead of
<code>requires(requires { T v; })</code>
or the like.
</p><p>New <code>concept</code> declarations should be rare, and only
defined internally within a library, such that they are not
exposed at API boundaries.
More generally, do not use concepts or constraints in cases where
you wouldn't use their legacy template equivalents in C++17.
</p>
<p>Do not define concepts that duplicate the function body,
or impose requirements that would be insignificant or obvious
from reading the body of the code or the resulting error messages.
For example, avoid the following:
</p><pre class="badcode">template &lt;typename T&gt; // Bad - redundant with negligible benefit
concept Addable = std::copyable&lt;T&gt; &amp;&amp; requires(T a, T b) { a + b; };
template &lt;Addable T&gt;
T Add(T x, T y, T z) { return x + y + z; }
</pre>
Instead, prefer to leave code as an ordinary template unless
you can demonstrate that concepts result in significant
improvement for that particular case, such as in the resulting
error messages for a deeply nested or non-obvious
requirement.
<p>Concepts should be statically verifiable by the compiler.
Do not use any concept whose primary benefits would come from a
semantic (or otherwise unenforced) constraint.
Requirements that are unenforced at compile time should instead
be imposed via other mechanisms such as comments, assertions,
or tests.</p>
<h3 id="Boost">Boost</h3>
<p>Use only approved libraries from the Boost library
@ -3955,9 +4080,10 @@ guide, the following C++ features may not be used:</p>
<p class="definition"></p>
<p>There are several ways to create names that are aliases of other entities:</p>
<pre>typedef Foo Bar;
using Bar = Foo;
using other_namespace::Foo;
<pre>using Bar = Foo;
typedef Foo Bar; // But prefer `using` in C++ code.
using ::other_namespace::Foo;
using enum MyEnumType; // Creates aliases for all enumerators in MyEnumType.
</pre>
<p>In new code, <code>using</code> is preferable to <code>typedef</code>,
@ -4245,6 +4371,10 @@ using PropertiesMap = hash_map&lt;UrlTableProperties *, std::string&gt;;
enum class UrlTableError { ...
</pre>
<h3 id="Concept_Names">Concept Names</h3>
Concept names follow the same rules as <a href="#Type_Names">type names</a>.
<h3 id="Variable_Names">Variable Names</h3>
<p>The names of variables (including function parameters) and data members are
@ -4308,9 +4438,10 @@ const int kAndroid8_0_0 = 24; // Android 8.0.0
<p>All such variables with static storage duration (i.e., statics and globals,
see <a href="http://en.cppreference.com/w/cpp/language/storage_duration#Storage_duration">
Storage Duration</a> for details) should be named this way. This
convention is optional for variables of other storage classes, e.g., automatic
variables; otherwise the usual variable naming rules apply. For example:</p>
Storage Duration</a> for details) should be named this way, including those in templates where
different instantiations of the template may have different values. This convention is optional for
variables of other storage classes, e.g., automatic variables; otherwise the usual variable naming
rules apply. For example:</p>
<pre>void ComputeFoo(absl::string_view suffix) {
// Either of these is acceptable.
@ -4515,7 +4646,7 @@ author line, consider deleting the author line.
New files should usually not contain copyright notice or
author line.</p>
<h3 id="Class_Comments">Class Comments</h3>
<h3 id="Class_Comments">Struct and Class Comments</h3>
<p>Every non-obvious class or struct declaration should have an
accompanying comment that describes what it is for and how it should
@ -4532,6 +4663,8 @@ class GargantuanTableIterator {
};
</pre>
<h4 id="Class_Comments_Details">Class Comments</h4>
<p>The class comment should provide the reader with enough information to know
how and when to use the class, as well as any additional considerations
necessary to correctly use the class. Document the synchronization assumptions
@ -4925,7 +5058,8 @@ if included in the source as straight UTF-8.</p>
<p>When possible, avoid the <code>u8</code> prefix.
It has significantly different semantics starting in C++20
than in C++17, producing arrays of <code>char8_t</code>
rather than <code>char</code>.
rather than <code>char</code>, and will change again in C++23.
</p><p>You shouldn't use <code>char16_t</code> and
<code>char32_t</code> character types, since they're for
@ -5091,7 +5225,8 @@ double d = 1248e6;
</pre>
<pre class="goodcode">float f = 1.0f;
float f2 = 1; // Also OK
float f2 = 1.0; // Also OK
float f3 = 1; // Also OK
long double ld = -0.5L;
double d = 1248.0e6;
</pre>

View File

@ -597,7 +597,11 @@ to have them in the same package.
Code within a package can access unexported identifiers in the package. If you
have a few related types whose *implementation* is tightly coupled, placing them
in the same package lets you achieve this coupling without polluting the public
API with these details.
API with these details. A good test for this coupling is to imagine a
hypothetical user of two packages, where the packages cover closely related
topics: if the user must import both packages in order to use either in any
meaningful way, combining them together is usually the right thing to do. The
standard library generally demonstrates this kind of scoping and layering well.
All of that being said, putting your entire project in a single package would
likely make that package too large. When something is conceptually distinct,
@ -776,7 +780,7 @@ var (
ErrMarsupial = errors.New("marsupials are not supported")
)
func pet(animal Animal) error {
func process(animal Animal) error {
switch {
case seen[animal]:
return ErrDuplicate
@ -849,6 +853,8 @@ to know if using status codes is the right choice.
[`os.PathError`]: https://pkg.go.dev/os#PathError
[`errors.Is`]: https://pkg.go.dev/errors#Is
[`errors.As`]: https://pkg.go.dev/errors#As
[`package cmp`]: https://pkg.go.dev/github.com/google/go-cmp/cmp
[status]: https://pkg.go.dev/google.golang.org/grpc/status
[canonical codes]: https://pkg.go.dev/google.golang.org/grpc/codes
@ -978,6 +984,10 @@ func (*FortuneTeller) SuggestFortune(context.Context, *pb.SuggestionRequest) (*p
}
```
See also:
* [Error Documentation Conventions](#documentation-conventions-errors)
<a id="error-percent-w"></a>
### Placement of %w in errors
@ -1255,7 +1265,7 @@ information to the reader:
// string.
//
// format is the format, and data is the interpolation data.
func Sprintf(format string, data ...interface{}) string
func Sprintf(format string, data ...any) string
```
However, this snippet demonstrates a code scenario similar to the previous where
@ -1272,7 +1282,7 @@ reader:
// the format specification, the function will inline warnings about formatting
// errors into the output string as described by the Format errors section
// above.
func Sprintf(format string, data ...interface{}) string
func Sprintf(format string, data ...any) string
```
Consider your likely audience in choosing what to document and at what depth.
@ -1317,9 +1327,9 @@ func (Worker) Run(ctx context.Context) error
```
Where context behavior is different or non-obvious, it should be expressly
documented:
documented if any of the following are true.
* If the function returns an error other than `ctx.Err()` when the context is
* The function returns an error other than `ctx.Err()` when the context is
cancelled:
```go
@ -1330,8 +1340,7 @@ documented:
func (Worker) Run(ctx context.Context) error
```
* If the function has other mechanisms that may interrupt it or affect
lifetime:
* The function has other mechanisms that may interrupt it or affect lifetime:
```go
// Good:
@ -1347,7 +1356,7 @@ documented:
func (Worker) Stop()
```
* If the function has special expectations about context lifetime, lineage, or
* The function has special expectations about context lifetime, lineage, or
attached values:
```go
@ -1394,9 +1403,9 @@ Similarly, the extra remark about concurrency can safely be removed here:
func (*Buffer) Grow(n int)
```
Documentation is strongly encouraged if:
Documentation is strongly encouraged if any of the following are true.
* it is unclear whether the operation is read-only or a mutating
* It is unclear whether the operation is read-only or mutating:
```go
// Good:
@ -1411,7 +1420,7 @@ Documentation is strongly encouraged if:
Why? A cache hit when looking up the key mutate a LRU cache internally. How
this is implemented may not be obvious to all readers.
* synchronization is provided by API
* Synchronization is provided by the API:
```go
// Good:
@ -1427,7 +1436,7 @@ Documentation is strongly encouraged if:
**Note:** If the API is a type and the API provides synchronization in
entirety, conventionally only the type definition documents the semantics.
* the API consumes user-implemented types of interfaces, and the interface's
* The API consumes user-implemented types of interfaces, and the interface's
consumer has particular concurrency requirements:
```go
@ -1489,6 +1498,84 @@ If it is potentially unclear how to clean up the resources, explain how:
func (c *Client) Get(url string) (resp *Response, err error)
```
See also:
* [GoTip #110: Dont Mix Exit With Defer]
[GoTip #110: Dont Mix Exit With Defer]: https://google.github.io/styleguide/go/index.html#gotip
<a id="documentation-conventions-errors"></a>
#### Errors
Document significant error sentinel values or error types that your functions
return to callers so that callers can anticipate what types of conditions they
can handle in their code.
```go
// Good:
package os
// Read reads up to len(b) bytes from the File and stores them in b. It returns
// the number of bytes read and any error encountered.
//
// At end of file, Read returns 0, io.EOF.
func (*File) Read(b []byte) (n int, err error) {
```
When a function returns a specific error type, correctly note whether the error
is a pointer receiver or not:
```go
// Good:
package os
type PathError struct {
Op string
Path string
Err error
}
// Chdir changes the current working directory to the named directory.
//
// If there is an error, it will be of type *PathError.
func Chdir(dir string) error {
```
Documenting whether the values returned are pointer receivers enables callers to
correctly compare the errors using [`errors.Is`], [`errors.As`], and
[`package cmp`]. This is because a non-pointer value is not equivalent to a
pointer value.
**Note:** In the `Chdir` example, the return type is written as `error` rather
than `*PathError` due to
[how nil interface values work](https://go.dev/doc/faq#nil_error).
Document overall error conventions in the
[package's documentation](decisions#package-comments) when the behavior is
applicable to most errors found in the package:
```go
// Good:
// Package os provides a platform-independent interface to operating system
// functionality.
//
// Often, more information is available within the error. For example, if a
// call that takes a file name fails, such as Open or Stat, the error will
// include the failing file name when printed and will be of type *PathError,
// which may be unpacked for more information.
package os
```
Thoughtful application of these approaches can add
[extra information to errors](#error-extra-info) without much effort and help
callers avoid adding redundant annotations.
See also:
* [Go Tip #106: Error Naming Conventions](https://google.github.io/styleguide/go/index.html#gotip)
* [Go Tip #89: When to Use Canonical Status Codes as Errors](https://google.github.io/styleguide/go/index.html#gotip)
<a id="documentation-preview"></a>
### Preview
@ -1944,7 +2031,7 @@ func foo(ctx context.Context) {
}
```
**Note**: [Contexts are never included in option structs](decisions#contexts).
**Note:** [Contexts are never included in option structs](decisions#contexts).
This option is often preferred when some of the following apply:
@ -2411,7 +2498,7 @@ func ExerciseGame(t *testing.T, cfg *Config, p chess.Player) error {
if cfg.Simulation == Modem {
conn, err := modempool.Allocate()
if err != nil {
t.Fatalf("no modem for the opponent could be provisioned: %v", err)
t.Fatalf("No modem for the opponent could be provisioned: %v", err)
}
t.Cleanup(func() { modempool.Return(conn) })
}
@ -2437,7 +2524,7 @@ func TestAcceptance(t *testing.T) {
player := deepblue.New()
err := chesstest.ExerciseGame(t, chesstest.SimpleGame, player)
if err != nil {
t.Errorf("deepblue player failed acceptance test: %v", err)
t.Errorf("Deep Blue player failed acceptance test: %v", err)
}
}
```
@ -2578,14 +2665,14 @@ func paint(color string) error {
func badSetup(t *testing.T) {
// This should call t.Helper, but doesn't.
if err := paint("taupe"); err != nil {
t.Fatalf("could not paint the house under test: %v", err) // line 15
t.Fatalf("Could not paint the house under test: %v", err) // line 15
}
}
func mustGoodSetup(t *testing.T) {
t.Helper()
if err := paint("lilac"); err != nil {
t.Fatalf("could not paint the house under test: %v", err)
t.Fatalf("Could not paint the house under test: %v", err)
}
}
@ -2605,10 +2692,10 @@ differs:
```text
=== RUN TestBad
paint_test.go:15: could not paint the house under test: no "taupe" paint today
paint_test.go:15: Could not paint the house under test: no "taupe" paint today
--- FAIL: TestBad (0.00s)
=== RUN TestGood
paint_test.go:32: could not paint the house under test: no "lilac" paint today
paint_test.go:32: Could not paint the house under test: no "lilac" paint today
--- FAIL: TestGood (0.00s)
FAIL
```
@ -2616,7 +2703,7 @@ FAIL
The error with `paint_test.go:15` refers to the line of the setup function that
failed in `badSetup`:
`t.Fatalf("could not paint the house under test: %v", err)`
`t.Fatalf("Could not paint the house under test: %v", err)`
Whereas `paint_test.go:32` refers to the line of the test that failed in
`TestGood`:
@ -2695,33 +2782,41 @@ and those should not depend on the system under test. Therefore, if a test
helper [registers a fatal test failure](#test-helper-error-handling), it can and
should do so from the test's goroutine.
<a id="t-field-names"></a>
### Use field names in struct literals
<a id="t-field-labels"></a>
### Use field labels for struct literals
In table-driven tests, prefer to specify the key for each test case specified.
This is helpful when the test cases cover a large amount of vertical space (e.g.
more than 20-30 lines), when there are adjacent fields with the same type, and
also when you wish to omit fields which have the zero value. For example:
In table-driven tests, prefer to specify field names when initializing test case
struct literals. This is helpful when the test cases cover a large amount of
vertical space (e.g. more than 20-30 lines), when there are adjacent fields with
the same type, and also when you wish to omit fields which have the zero value.
For example:
```go
// Good:
tests := []struct {
foo *pb.Foo
bar *pb.Bar
func TestStrJoin(t *testing.T) {
tests := []struct {
slice []string
separator string
skipEmpty bool
want string
}{
}{
{
foo: pb.Foo_builder{
Name: "foo",
// ...
}.Build(),
bar: pb.Bar_builder{
Name: "bar",
// ...
}.Build(),
want: "result",
slice: []string{"a", "b", ""},
separator: ",",
want: "a,b,",
},
{
slice: []string{"a", "b", ""},
separator: ",",
skipEmpty: true,
want: "a,b",
},
// ...
}
// ...
}
```
@ -2742,7 +2837,7 @@ func mustLoadDataset(t *testing.T) []byte {
data, err := os.ReadFile("path/to/your/project/testdata/dataset")
if err != nil {
t.Fatalf("could not load dataset: %v", err)
t.Fatalf("Could not load dataset: %v", err)
}
return data
}
@ -2756,7 +2851,7 @@ func TestParseData(t *testing.T) {
data := mustLoadDataset(t)
parsed, err := ParseData(data)
if err != nil {
t.Fatalf("unexpected error parsing data: %v", err)
t.Fatalf("Unexpected error parsing data: %v", err)
}
want := &DataTable{ /* ... */ }
if got := parsed; !cmp.Equal(got, want) {
@ -2768,7 +2863,7 @@ func TestListContents(t *testing.T) {
data := mustLoadDataset(t)
contents, err := ListContents(data)
if err != nil {
t.Fatalf("unexpected error listing contents: %v", err)
t.Fatalf("Unexpected error listing contents: %v", err)
}
want := []string{ /* ... */ }
if got := contents; !cmp.Equal(got, want) {
@ -2916,7 +3011,7 @@ func mustLoadDataset(t *testing.T) []byte {
dataset.err = err
})
if err := dataset.err; err != nil {
t.Fatalf("could not load dataset: %v", err)
t.Fatalf("Could not load dataset: %v", err)
}
return dataset.data
}
@ -2972,8 +3067,8 @@ guidance outlines when each method is preferred.
### Prefer "+" for simple cases
Prefer using "+" when concatenating few strings. This method is the
syntactically the simplest and requires no import.
Prefer using "+" when concatenating few strings. This method is syntactically
the simplest and requires no import.
```go
// Good:
@ -3024,7 +3119,7 @@ for i, d := range digitsOfPi {
str := b.String()
```
**NOTE**: For more discussion, see
**Note:** For more discussion, see
[GoTip #29: Building Strings Efficiently](https://google.github.io/styleguide/go/index.html#gotip).
<a id="string-constants"></a>

View File

@ -897,9 +897,14 @@ import (
)
```
It is acceptable to split the project packages into multiple groups, for example
if you want a separate group for renamed, imported-only-for-side-effects or
another special group of imports.
It is acceptable to split the project packages into multiple groups if you want
a separate group, as long as the groups have some meaning. Common reasons to do
this:
* renamed imports
* packages imported for their side-effects
Example:
```go
// Good:
@ -1273,14 +1278,19 @@ maintainable.
#### Field names
Struct literals should usually specify **field names** for types defined outside
the current package.
Struct literals must specify **field names** for types defined outside the
current package.
* Include field names for types from other packages.
```go
// Good:
good := otherpkg.Type{A: 42}
// https://pkg.go.dev/encoding/csv#Reader
r := csv.Reader{
Comma: ',',
Comment: '#',
FieldsPerRecord: 4,
}
```
The position of fields in a struct and the full set of fields (both of which
@ -1290,19 +1300,9 @@ the current package.
```go
// Bad:
// https://pkg.go.dev/encoding/csv#Reader
r := csv.Reader{',', '#', 4, false, false, false, false}
```
Field names may be omitted within small, simple structs whose composition
and order are documented as being stable.
```go
// Good:
okay := image.Point{42, 54}
also := image.Point{X: 42, Y: 54}
```
* For package-local types, field names are optional.
```go
@ -1721,33 +1721,6 @@ func (r *SomeType) SomeLongFunctionName(foo1, foo2, foo3 string,
See [best practices](best-practices#funcargs) for a few options for shortening
the call sites of functions that would otherwise have many arguments.
```go
// Good:
good := foo.Call(long, CallOptions{
Names: list,
Of: of,
The: parameters,
Func: all,
Args: on,
Now: separate,
Visible: lines,
})
```
```go
// Bad:
bad := foo.Call(
long,
list,
of,
parameters,
all,
on,
separate,
lines,
)
```
Lines can often be shortened by factoring out local variables.
```go
@ -1770,9 +1743,9 @@ bad := foo.Call(long, list, of, parameters,
with, arbitrary, line, breaks)
```
Do not add comments to specific function parameters. Instead, use an
[option struct](best-practices#option-structure) or add more detail to the
function documentation.
Avoid adding inline comments to specific function arguments where possible.
Instead, use an [option struct](best-practices#option-structure) or add more
detail to the function documentation.
```go
// Good:
@ -1787,21 +1760,6 @@ bad := server.New(
)
```
If call-sites are uncomfortably long, consider refactoring:
```go
// Good:
// Sometimes variadic arguments can be factored out
replacements := []string{
"from", "to", // related values can be formatted adjacent to one another
"source", "dest",
"original", "new",
}
// Use the replacement struct as inputs to NewReplacer.
replacer := strings.NewReplacer(replacements...)
```
If the API cannot be changed or if the local call is unusual (whether or not the
call is too long), it is always permissible to add line breaks if it aids in
understanding the call.
@ -2110,7 +2068,7 @@ exclusively at
func MustParse(version string) *Version {
v, err := Parse(version)
if err != nil {
log.Fatalf("MustParse(%q) = _, %v", version, err)
panic(fmt.Sprintf("MustParse(%q) = _, %v", version, err))
}
return v
}
@ -2120,8 +2078,6 @@ func MustParse(version string) *Version {
var DefaultVersion = MustParse("1.2.3")
```
**Note:** `log.Fatalf` is not the standard library log. See [#logging].
The same convention may be used in test helpers that only stop the current test
(using `t.Fatal`). Such helpers are often convenient in creating test values,
for example in struct fields of [table driven tests](#table-driven-tests), as
@ -2133,7 +2089,7 @@ func mustMarshalAny(t *testing.T, m proto.Message) *anypb.Any {
t.Helper()
any, err := anypb.New(m)
if err != nil {
t.Fatalf("MustMarshalAny(t, m) = %v; want %v", err, nil)
t.Fatalf("mustMarshalAny(t, m) = %v; want %v", err, nil)
}
return any
}
@ -2189,8 +2145,8 @@ func Version(o *servicepb.Object) (*version.Version, error) {
When you spawn goroutines, make it clear when or whether they exit.
Goroutines can leak by blocking on channel sends or receives. The garbage
collector will not terminate a goroutine even if the channels it is blocked on
are unreachable.
collector will not terminate a goroutine blocked on a channel even if no other
goroutine has a reference to the channel.
Even when goroutines do not leak, leaving them in-flight when they are no longer
needed can cause other subtle and hard-to-diagnose problems. Sending on a
@ -2764,11 +2720,11 @@ See also:
### Logging
Go programs in the Google codebase use a variant of the
[standard `log` package]. It has a similar but more powerful interface and
interoperates well with internal Google systems. An open source version of this
library is available as [package `glog`], and open source Google projects may
use that, but this guide refers to it as `log` throughout.
Go programs in the Google codebase use a variant of the standard [`log`]
package. It has a similar but more powerful interface and interoperates well
with internal Google systems. An open source version of this library is
available as [package `glog`], and open source Google projects may use that, but
this guide refers to it as `log` throughout.
**Note:** For abnormal program exits, this library uses `log.Fatal` to abort
with a stacktrace, and `log.Exit` to stop without one. There is no `log.Panic`
@ -2785,7 +2741,8 @@ See also:
* When and how to use the log package to
[stop the program](best-practices#checks-and-panics)
[standard `log` package]: https://pkg.go.dev/log
[`log`]: https://pkg.go.dev/log
[`log/slog`]: https://pkg.go.dev/log/slog
[package `glog`]: https://pkg.go.dev/github.com/golang/glog
[`log.Exit`]: https://pkg.go.dev/github.com/golang/glog#Exit
[`log.Fatal`]: https://pkg.go.dev/github.com/golang/glog#Fatal
@ -2978,15 +2935,15 @@ right:
// Bad:
package assert
func IsNotNil(t *testing.T, name string, val interface{}) {
func IsNotNil(t *testing.T, name string, val any) {
if val == nil {
t.Fatalf("data %s = nil, want not nil", name)
t.Fatalf("Data %s = nil, want not nil", name)
}
}
func StringEq(t *testing.T, name, got, want string) {
if got != want {
t.Fatalf("data %s = %q, want %q", name, got, want)
t.Fatalf("Data %s = %q, want %q", name, got, want)
}
}
```
@ -3013,7 +2970,7 @@ want := BlogPost{
}
if !cmp.Equal(got, want) {
t.Errorf("blog post = %v, want = %v", got, want)
t.Errorf("Blog post = %v, want = %v", got, want)
}
```
@ -3029,7 +2986,7 @@ func TestBlogPost_VeritableRant(t *testing.T) {
post := BlogPost{Body: "I am Gunnery Sergeant Hartman, your senior drill instructor."}
if got, want := postLength(post), 60; got != want {
t.Errorf("length of post = %v, want %v", got, want)
t.Errorf("Length of post = %v, want %v", got, want)
}
}
```
@ -3361,7 +3318,8 @@ than relying on parsing the error message.
Within unit tests, it is common to only care whether an error occurred or not.
If so, then it is sufficient to only test whether the error was non-nil when you
expected an error. If you would like to test that the error semantically matches
some other error, then consider using `cmp` with [`cmpopts.EquateErrors`].
some other error, then consider using [`errors.Is`] or `cmp` with
[`cmpopts.EquateErrors`].
> **Note:** If a test uses [`cmpopts.EquateErrors`] but all of its `wantErr`
> values are either `nil` or `cmpopts.AnyError`, then using `cmp` is
@ -3370,9 +3328,10 @@ some other error, then consider using `cmp` with [`cmpopts.EquateErrors`].
>
> ```go
> // Good:
> gotErr := f(test.input) != nil
> err := f(test.input)
> gotErr := err != nil
> if gotErr != test.wantErr {
> t.Errorf("f(%q) returned err = %v, want error presence = %v", test.input, gotErr, test.wantErr)
> t.Errorf("f(%q) = %v, want error presence = %v", test.input, err, test.wantErr)
> }
> ```
@ -3381,6 +3340,7 @@ See also
[tott-350]: https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html
[`cmpopts.EquateErrors`]: https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts#EquateErrors
[`errors.Is`]: https://pkg.go.dev/errors#Is
<a id="test-structure"></a>
@ -3471,6 +3431,9 @@ t.Run("check that there is no mention of scratched records or hovercrafts", ...)
t.Run("AM/PM confusion", ...)
```
See also
[Go Tip #117: Subtest Names](https://google.github.io/styleguide/go/index.html#gotip).
[Go test runner]: https://golang.org/cmd/go/#hdr-Testing_flags
[identify the inputs]: #identify-the-input
[special meaning for test filters]: https://blog.golang.org/subtests#:~:text=Perhaps%20a%20bit,match%20any%20tests
@ -3491,18 +3454,17 @@ similar testing logic.
[tests of `fmt.Sprintf`]: https://cs.opensource.google/go/go/+/master:src/fmt/fmt_test.go
[tests for `net.Dial`]: https://cs.opensource.google/go/go/+/master:src/net/dial_test.go;l=318;drc=5b606a9d2b7649532fe25794fa6b99bd24e7697c
Here is the minimal structure of a table-driven test, copied from the standard
`strings` library. If needed, you may use different names, move the test slice
into the test function, or add extra facilities such as subtests or setup and
cleanup functions. Always keep [useful test failures](#useful-test-failures) in
mind.
Here is the minimal structure of a table-driven test. If needed, you may use
different names or add extra facilities such as subtests or setup and cleanup
functions. Always keep [useful test failures](#useful-test-failures) in mind.
```go
// Good:
var compareTests = []struct {
func TestCompare(t *testing.T) {
compareTests := []struct {
a, b string
i int
}{
want int
}{
{"", "", 0},
{"a", "", 1},
{"", "a", -1},
@ -3517,13 +3479,12 @@ var compareTests = []struct {
{"abcdefgh", "abcdefgh", 0},
{"abcdefghi", "abcdefghi", 0},
{"abcdefghi", "abcdefghj", -1},
}
}
func TestCompare(t *testing.T) {
for _, tt := range compareTests {
cmp := Compare(tt.a, tt.b)
if cmp != tt.i {
t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
for _, test := range compareTests {
got := Compare(test.a, test.b)
if got != test.want {
t.Errorf("Compare(%q, %q) = %v, want %v", test.a, test.b, got, test.want)
}
}
}
@ -3639,7 +3600,7 @@ func TestDecode(t *testing.T) {
case prod:
codex = setupCodex(t)
default:
t.Fatalf("unknown codex type: %v", codex)
t.Fatalf("Unknown codex type: %v", codex)
}
output, err := Decode(test.input, codex)
if got, want := output, test.output; got != want {
@ -3673,7 +3634,7 @@ tests := []struct {
}
for i, d := range tests {
if strings.ToUpper(d.input) != d.want {
t.Errorf("failed on case #%d", i)
t.Errorf("Failed on case #%d", i)
}
}
```

View File

@ -419,8 +419,8 @@ initial capitalization.
### Line length
There is no fixed line length for Go source code. If a line feels too long, it
should be refactored instead of broken. If it is already as short as it is
There is no fixed line length for Go source code. If a line feels too long,
prefer refactoring instead of splitting it. If it is already as short as it is
practical for it to be, the line should be allowed to remain long.
Do not split a line:

View File

@ -2,13 +2,16 @@ table {
border-collapse: collapse;
}
td, th {
td,
th {
border: 1px solid #ccc;
padding: 2px 12px;
font-size: 10pt;
}
code, samp, var {
code,
samp,
var {
color: #060;
}
@ -17,16 +20,9 @@ pre {
display: block;
color: #060;
background-color: #e8fff6;
border-color: #f0fff0;
border-style: solid;
border-top-width: 1px;
border-bottom-width: 1px;
border-right-width: 1px;
border: 1px solid #f0fff0;
border-left-width: 5px;
padding-left: 12px;
padding-right: 12px;
padding-top: 4px;
padding-bottom: 4px;
padding: 4px 12px;
}
pre.badcode {
@ -42,10 +38,8 @@ hr {
}
html {
margin-top:2em;
margin-left:10%;
margin-right:10%;
padding:0;
margin: 2em 10% 0;
padding: 0;
}
.bp-reset-element,
@ -104,32 +98,32 @@ tbody,
tfoot,
thead,
tr {
margin:0;
padding:0;
border:0;
font-weight:inherit;
font-style:inherit;
font-size:100%;
font-family:inherit;
vertical-align:baseline;
margin: 0;
padding: 0;
border: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}
body {
font-family:'Arial', sans-serif;
font-size:81.25%;
color:#222;
background-color:#fff;
line-height:1.67;
font-family: 'Arial', sans-serif;
font-size: 81.25%;
color: #222;
background-color: #fff;
line-height: 1.67;
overflow: auto;
}
.change {
text-align: right;
margin-bottom:1em;
margin-bottom: 1em;
}
em {
font-style: italic
font-style: italic;
}
h1,
@ -138,12 +132,12 @@ h3,
h4,
h5,
h6 {
font-weight:bold;
font-weight: bold;
}
h1 {
margin-bottom:.50em;
text-align: center
margin-bottom: 0.5em;
text-align: center;
}
h2,
@ -151,22 +145,36 @@ h3,
h4,
h5,
h6 {
margin-top:1.5em;
margin-bottom:.75em;
margin-top: 1.5em;
margin-bottom: 0.75em;
}
h1 {font-size:200%;}
h2 {font-size:167%;}
h3 {font-size:133%;}
h4 {font-size:120%;}
h5 {font-size:110%;}
h1 {
font-size: 200%;
}
h2 {
font-size: 167%;
}
h3 {
font-size: 133%;
}
h4 {
font-size: 120%;
}
h5 {
font-size: 110%;
}
p {
margin:0 0 1.5em;
margin: 0 0 1.5em;
}
a[href=''] {
cursor:default;
cursor: default;
}
h1 img,
@ -175,238 +183,238 @@ h3 img,
h4 img,
h5 img,
h6 img {
margin:0;
margin: 0;
}
a img {
border:none;
border: none;
}
pre {
margin:1.5em 0;
white-space:pre;
margin: 1.5em 0;
white-space: pre;
}
pre,
code,
kbd,
tt {
font:1em 'Droid Sans Mono', monospace;
line-height:1.5;
font: 1em 'Droid Sans Mono', monospace;
line-height: 1.5;
}
dl {
margin:0 0 1.5em 0;
margin: 0 0 1.5em;
}
dl dt {
font-weight:bold;
font-weight: bold;
}
dd {
margin-left:1.5em;
margin-left: 1.5em;
}
dd.toc3 {
margin-left:3em;
margin-left: 3em;
}
hr {
height:0;
border:0;
border-top:1px solid #ccc;
background-color:#ccc;
height: 0;
border: 0;
border-top: 1px solid #ccc;
background-color: #ccc;
}
table {
border:1px solid #bbb;
border-spacing:0;
border-collapse:collapse;
margin:0 0 1.5em;
vertical-align:middle;
width:100%;
border: 1px solid #bbb;
border-spacing: 0;
border-collapse: collapse;
margin: 0 0 1.5em;
vertical-align: middle;
width: 100%;
}
table.unlined,
table.unlined th,
table.unlined tr,
table.unlined td {
border:0;
border: 0;
}
th,
td,
caption {
float:none !important;
text-align:left;
font-weight:normal;
vertical-align:middle;
padding:4px;
float: none !important;
text-align: left;
font-weight: normal;
vertical-align: middle;
padding: 4px;
}
caption {
padding:0;
padding: 0;
}
td {
border:1px solid #bbb;
vertical-align:top;
border: 1px solid #bbb;
vertical-align: top;
}
th {
border:0;
border-bottom:1px solid black;
font-weight:bold;
background:rgb(229, 236, 249);
border: 0;
border-bottom: 1px solid black;
font-weight: bold;
background: rgb(229, 236, 249);
}
table th code {
background-color:inherit;
color:inherit;
background-color: inherit;
color: inherit;
}
table tfoot th {
border:1px solid #bbb;
border: 1px solid #bbb;
}
tfoot {
font-style:italic;
font-style: italic;
}
caption {
background:#eee;
background: #eee;
}
table[border='0'] {
border:none;
border: none;
}
table[border='0']>tbody>tr>td,
table[border='0']>tr>td {
border:none;
table[border='0'] > tbody > tr > td,
table[border='0'] > tr > td {
border: none;
}
tr.alt td,
td.alt {
background-color:#efefef;
background-color: #efefef;
}
table.striped tr:nth-child(even) td,
table tr.even td {
background:#efefef;
background: #efefef;
}
table.columns {
border:none;
border: none;
}
table.columns>tbody>tr>td,
table.columns>tr>td {
border:none;
padding:0 3em 0 0;
table.columns > tbody > tr > td,
table.columns > tr > td {
border: none;
padding: 0 3em 0 0;
}
table.columns>tbody>tr>td:last-child,
table.columns>tr>td:last-child {
border:none;
padding:0;
table.columns > tbody > tr > td:last-child,
table.columns > tr > td:last-child {
border: none;
padding: 0;
}
ul,
ol {
margin:0 1.5em 1.5em 0;
padding-left:2em;
margin: 0 1.5em 1.5em 0;
padding-left: 2em;
}
li ul,
li ol {
margin:0;
margin: 0;
}
ul {
list-style-type:disc;
list-style-type: disc;
}
ol {
list-style-type:decimal;
list-style-type: decimal;
}
ul {
list-style-type:disc;
list-style-type: disc;
}
ul ul {
list-style-type:circle;
list-style-type: circle;
}
ul ul ul {
list-style-type:square;
list-style-type: square;
}
ul.disc {
list-style-type:disc;
list-style-type: disc;
}
ul.circle {
list-style-type:circle;
list-style-type: circle;
}
ul.square {
list-style-type:square;
list-style-type: square;
}
ol {
list-style-type:decimal;
list-style-type: decimal;
}
ol ol {
list-style-type:lower-alpha;
list-style-type: lower-alpha;
}
ol ol ol {
list-style-type:lower-roman;
list-style-type: lower-roman;
}
ol ul {
list-style-type:circle;
list-style-type: circle;
}
ol.decimal {
list-style-type:decimal;
list-style-type: decimal;
}
ol.upper-alpha {
list-style-type:upper-alpha;
list-style-type: upper-alpha;
}
ol.lower-alpha {
list-style-type:lower-alpha;
list-style-type: lower-alpha;
}
ol.upper-roman {
list-style-type:upper-roman;
list-style-type: upper-roman;
}
ol.lower-roman {
list-style-type:lower-roman;
list-style-type: lower-roman;
}
ol.nolist,
ul.nolist {
padding-left:0;
list-style-image:none;
list-style-type:none;
margin-left:0;
padding-left: 0;
list-style-image: none;
list-style-type: none;
margin-left: 0;
}
.center {
text-align:center;
text-align: center;
}
code,
kbd,
pre {
color:#009900;
color: #090;
}
kbd {
@ -414,107 +422,108 @@ kbd {
}
table.striped code {
background-color:inherit;
background-color: inherit;
}
pre {
padding:6px 10px;
background-color:#FAFAFA;
border:1px solid #bbb;
overflow:auto;
padding: 6px 10px;
background-color: #fafafa;
border: 1px solid #bbb;
overflow: auto;
}
pre.prettyprint {
padding:6px 10px !important;
border:1px solid #bbb !important;
padding: 6px 10px !important;
border: 1px solid #bbb !important;
}
code.bad, code.badcode {
code.bad,
code.badcode {
color: magenta;
}
pre.bad, pre.badcode {
background-color:#ffe6d8;
border-top:1px inset #a03;
border-left:1px inset #a03;
pre.bad,
pre.badcode {
background-color: #ffe6d8;
border-top: 1px inset #a03;
border-left: 1px inset #a03;
}
.tip {
background-color:#fffbd9;
padding:6px 8px 6px 10px;
border-left:6px solid #ffef70;
background-color: #fffbd9;
padding: 6px 8px 6px 10px;
border-left: 6px solid #ffef70;
}
.note {
background-color:#e5ecf9;
padding:6px 8px 6px 10px;
border-left:6px solid #36c;
background-color: #e5ecf9;
padding: 6px 8px 6px 10px;
border-left: 6px solid #36c;
}
@media print {
.str {
color:#060;
color: #060;
}
.kwd {
color:#006;
font-weight:bold;
color: #006;
font-weight: bold;
}
.com {
color:#600;
font-style:italic;
color: #600;
font-style: italic;
}
.typ {
color:#404;
font-weight:bold;
color: #404;
font-weight: bold;
}
.lit {
color:#044;
color: #044;
}
.pun,
.opn,
.clo {
color:#440;
color: #440;
}
.pln {
color:#000;
color: #000;
}
.tag {
color:#006;
font-weight:bold;
color: #006;
font-weight: bold;
}
.atn {
color:#404;
color: #404;
}
.atv {
color:#060;
color: #060;
}
h1 {
font-style:italic;
font-style: italic;
}
}
ol.linenums {
margin-top:0;
margin-bottom:0;
margin-top: 0;
margin-bottom: 0;
}
code {
background-color:#FAFAFA;
background-color: #fafafa;
padding: 0.25em 0.5em;
white-space: nowrap
white-space: nowrap;
}
/* TOC CSS */
table.columns {
@ -552,15 +561,16 @@ li.toc_entry {
* at href boundaries
*/
li.toc_entry::after {
content: " ";
}
content: ' ';
}
li.toc_entry a {
white-space: nowrap;
}
/* Horizontal TOC */
.toc td, .toc th {
.toc td,
.toc th {
border-width: 1px 5px;
overflow: hidden;
}
@ -568,7 +578,7 @@ li.toc_entry a {
/* Vertical TOC */
.toc td.two_columns {
border-width: 0px;
border-width: 0;
}
/* Numbered sections */

View File

@ -47,6 +47,7 @@ See README.md for details.
+ [3.8.2 Modules](#s3.8.2-comments-in-modules)
+ [3.8.2.1 Test modules](#s3.8.2.1-test-modules)
+ [3.8.3 Functions and Methods](#s3.8.3-functions-and-methods)
+ [3.8.3.1 Overridden Methods](#s3.8.3.1-overridden-methods)
+ [3.8.4 Classes](#s3.8.4-comments-in-classes)
+ [3.8.5 Block and Inline Comments](#s3.8.5-block-and-inline-comments)
+ [3.8.6 Punctuation, Spelling, and Grammar](#s3.8.6-punctuation-spelling-and-grammar)
@ -213,8 +214,8 @@ that the arguments are actually unused.
<a id="imports"></a>
### 2.2 Imports
Use `import` statements for packages and modules only, not for individual
classes or functions.
Use `import` statements for packages and modules only, not for individual types,
classes, or functions.
<a id="s2.2.1-definition"></a>
<a id="221-definition"></a>
@ -404,11 +405,15 @@ Exceptions must follow certain conditions:
- Make use of built-in exception classes when it makes sense. For example,
raise a `ValueError` to indicate a programming mistake like a violated
precondition (such as if you were passed a negative number but required a
positive one). Do not use `assert` statements for validating argument values
of a public API. `assert` is used to ensure internal correctness, not to
enforce correct usage nor to indicate that some unexpected event occurred.
If an exception is desired in the latter cases, use a raise statement. For
precondition, such as may happen when validating function arguments.
- Do not use `assert` statements in place of conditionals or validating
preconditions. They must not be critical to the application logic. A litmus
test would be that the `assert` could be removed without breaking the code.
`assert` conditionals are
[not guaranteed](https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement)
to be evaluated. For [pytest](https://pytest.org) based tests, `assert` is
okay and expected to verify expectations. For
example:
@ -435,6 +440,7 @@ Exceptions must follow certain conditions:
if port is None:
raise ConnectionError(
f'Could not connect to service on port {minimum} or higher.')
# The code does not depend on the result of this assert.
assert port >= minimum, (
f'Unexpected port {port} when minimum was {minimum}.')
return port
@ -452,8 +458,10 @@ Exceptions must follow certain conditions:
The new minimum port.
"""
assert minimum >= 1024, 'Minimum port must be at least 1024.'
# The following code depends on the previous assert.
port = self._find_next_open_port(minimum)
assert port is not None
# The type checking of the return statement relies on the assert.
return port
```
@ -642,20 +650,18 @@ Complicated comprehensions or generator expressions can be hard to read.
<a id="comprehensions-decision"></a>
#### 2.7.4 Decision
Okay to use for simple cases. Each portion must fit on one line: mapping
expression, `for` clause, filter expression. Multiple `for` clauses or filter
expressions are not permitted. Use loops instead when things get more
complicated.
Comprehensions are allowed, however multiple `for` clauses or filter expressions
are not permitted. Optimize for readability, not conciseness.
```python
Yes:
result = [mapping_expr for value in iterable if filter_expr]
result = [{'key': value} for value in iterable
if a_long_filter_expression(value)]
result = [complicated_transform(x)
for x in iterable if predicate(x)]
result = [
is_valid(metric={'key': value})
for value in interesting_iterable
if a_longer_filter_expression(value)
]
descriptive_name = [
transform({'key': key, 'value': value}, color='black')
@ -669,32 +675,29 @@ Yes:
if x * y > 10:
result.append((x, y))
return {x: complicated_transform(x)
return {
x: complicated_transform(x)
for x in long_generator_function(parameter)
if x is not None}
if x is not None
}
squares_generator = (x**2 for x in range(10))
return (x**2 for x in range(10))
unique_names = {user.name for user in users if user is not None}
eat(jelly_bean for jelly_bean in jelly_beans
if jelly_bean.color == 'black')
```
```python
No:
result = [complicated_transform(
x, some_argument=x+1)
for x in iterable if predicate(x)]
result = [(x, y) for x in range(10) for y in range(5) if x * y > 10]
return ((x, y, z)
return (
(x, y, z)
for x in range(5)
for y in range(5)
if x != y
for z in range(5)
if y != z)
if y != z
)
```
<a id="s2.8-default-iterators-and-operators"></a>
@ -848,8 +851,8 @@ function may only contain an expression.
<a id="lambdas-decision"></a>
#### 2.10.4 Decision
Okay to use them for one-liners. If the code inside the lambda function is
longer than 60-80 chars, it's probably better to define it as a regular
Lambdas are allowed. If the code inside the lambda function spans multiple lines
or is longer than 60-80 chars, it might be better to define it as a regular
[nested function](#lexical-scoping).
For common operations like multiplication, use the functions from the `operator`
@ -992,7 +995,7 @@ _FOO = flags.DEFINE_string(...)
No: def foo(a, b=[]):
...
No: def foo(a, b=time.time()): # The time the module was loaded???
No: def foo(a, b=time.time()): # Is `b` supposed to represent when this module was loaded?
...
No: def foo(a, b=_FOO.value): # sys.argv has not yet been parsed...
...
@ -1071,7 +1074,7 @@ implement computations a subclass may ever want to override and extend.
<a id="truefalse-evaluations"></a>
### 2.14 True/False Evaluations
Use the "implicit" false if at all possible.
Use the "implicit" false if at all possible (with a few caveats).
<a id="s2.14.1-definition"></a>
<a id="2141-definition"></a>
@ -1798,6 +1801,150 @@ Trailing commas in sequences of items are recommended only when the closing
container token `]`, `)`, or `}` does not appear on the same line as the final
element, as well as for tuples with a single element. The presence of a trailing
comma is also used as a hint to our Python code auto-formatter
[Black](https://github.com/psf/black) or [Pyink](https://github.com/google/pyink)
to direct it to auto-format the container of items to one item per line when the
`,` after the final element is present.
```python
Yes: golomb3 = [0, 1, 3]
golomb4 = [
0,
1,
4,
6,
]
```
```python
No: golomb4 = [
0,
1,
4,
6,]
```
<a id="s3.5-blank-lines"></a>
<a id="35-blank-lines"></a>
<a id="blank-lines"></a>
### 3.5 Blank Lines
Two blank lines between top-level definitions, be they function or class
definitions. One blank line between method definitions and between the docstring
of a `class` and the first method. No blank line following a `def` line. Use
single blank lines as you judge appropriate within functions or methods.
Blank lines need not be anchored to the definition. For example, related
comments immediately preceding function, class, and method definitions can make
sense. Consider if your comment might be more useful as part of the docstring.
<a id="s3.6-whitespace"></a>
<a id="36-whitespace"></a>
<a id="whitespace"></a>
### 3.6 Whitespace
Follow standard typographic rules for the use of spaces around punctuation.
No whitespace inside parentheses, brackets or braces.
```python
Yes: spam(ham[1], {'eggs': 2}, [])
```
```python
No: spam( ham[ 1 ], { 'eggs': 2 }, [ ] )
```
No whitespace before a comma, semicolon, or colon. Do use whitespace after a
comma, semicolon, or colon, except at the end of the line.
```python
Yes: if x == 4:
print(x, y)
x, y = y, x
```
```python
No: if x == 4 :
print(x , y)
x , y = y , x
```
No whitespace before the open paren/bracket that starts an argument list,
indexing or slicing.
```python
Yes: spam(1)
```
```python
No: spam (1)
```
```python
Yes: dict['key'] = list[index]
```
```python
No: dict ['key'] = list [index]
```
No trailing whitespace.
Surround binary operators with a single space on either side for assignment
(`=`), comparisons (`==, <, >, !=, <>, <=, >=, in, not in, is, is not`), and
Booleans (`and, or, not`). Use your better judgment for the insertion of spaces
around arithmetic operators (`+`, `-`, `*`, `/`, `//`, `%`, `**`, `@`).
```python
Yes: x == 1
```
```python
No: x<1
```
Never use spaces around `=` when passing keyword arguments or defining a default
parameter value, with one exception:
[when a type annotation is present](#typing-default-values), *do* use spaces
around the `=` for the default parameter value.
```python
Yes: def complex(real, imag=0.0): return Magic(r=real, i=imag)
Yes: def complex(real, imag: float = 0.0): return Magic(r=real, i=imag)
```
```python
No: def complex(real, imag = 0.0): return Magic(r = real, i = imag)
No: def complex(real, imag: float=0.0): return Magic(r = real, i = imag)
```
Don't use spaces to vertically align tokens on consecutive lines, since it
becomes a maintenance burden (applies to `:`, `#`, `=`, etc.):
```python
Yes:
foo = 1000 # comment
long_name = 2 # comment that should not be aligned
dictionary = {
'foo': 1,
'long_name': 2,
}
```
```python
No:
foo = 1000 # comment
long_name = 2 # comment that should not be aligned
dictionary = {
'foo' : 1,
'long_name': 2,
}
```
<a id="Python_Interpreter"></a>
<a id="s3.7-shebang-line"></a>
@ -1929,15 +2076,6 @@ should use the same style as the docstring for an attribute or a
<a href="#doc-function-args">function argument</a> (`"""The Bigtable path."""`,
rather than `"""Returns the Bigtable path."""`).
A method that overrides a method from a base class may have a simple docstring
sending the reader to its overridden method's docstring, such as `"""See base
class."""`. The rationale is that there is no need to repeat in many places
documentation that is already present in the base method's docstring. However,
if the overriding method's behavior is substantially different from the
overridden method, or details need to be provided (e.g., documenting additional
side effects), a docstring with at least those differences is required on the
overriding method.
Certain aspects of a function should be documented in special sections, listed
below. Each section begins with a heading line, which ends with a colon. All
sections other than the heading should maintain a hanging indent of two or four
@ -1961,16 +2099,18 @@ aptly described using a one-line docstring.
: Describe the semantics of the return value, including any type information
that the type annotation does not provide. If the function only returns
None, this section is not required. It may also be omitted if the docstring
starts with Returns or Yields (e.g. `"""Returns row from Bigtable as a tuple
of strings."""`) and the opening sentence is sufficient to describe the
return value. Do not imitate 'NumPy style'
([example](http://numpy.org/doc/stable/reference/generated/numpy.linalg.qr.html)),
which frequently documents a tuple return value as if it were multiple
starts with "Return", "Returns", "Yield", or "Yields" (e.g. `"""Returns row
from Bigtable as a tuple of strings."""`) *and* the opening sentence is
sufficient to describe the return value. Do not imitate older 'NumPy style'
([example](https://numpy.org/doc/1.24/reference/generated/numpy.linalg.qr.html)),
which frequently documented a tuple return value as if it were multiple
return values with individual names (never mentioning the tuple). Instead,
describe such a return value as: "Returns: A tuple (mat_a, mat_b), where
mat_a is ..., and ...". The auxiliary names in the docstring need not
necessarily correspond to any internal names used in the function body (as
those are not part of the API).
those are not part of the API). If the function uses `yield` (is a
generator), the `Yields:` section should document the object returned by
`next()`, instead of the generator object itself that the call evaluates to.
<a id="doc-function-raises"></a>
[*Raises:*](#doc-function-raises)
@ -2057,6 +2197,47 @@ def fetch_smalltable_rows(
"""
```
<a id="s3.8.3.1-overridden-methods"></a>
<a id="overridden-method-docs"></a>
##### 3.8.3.1 Overridden Methods
A method that overrides a method from a base class does not need a docstring if
it is explicitly decorated with
[`@override`](https://typing-extensions.readthedocs.io/en/latest/#override)
(from `typing_extensions` or `typing` modules), unless the overriding method's
behavior materially refines the base method's contract, or details need to be
provided (e.g., documenting additional side effects), in which case a docstring
with at least those differences is required on the overriding method.
```python
from typing_extensions import override
class Parent:
def do_something(self):
"""Parent method, includes docstring."""
# Child class, method annotated with override.
class Child(Parent):
@override
def do_something(self):
pass
```
```python
# Child class, but without @override decorator, a docstring is required.
class Child(Parent):
def do_something(self):
pass
# Docstring is trivial, @override is sufficient to indicate that docs can be
# found in the base class.
class Child(Parent):
@override
def do_something(self):
"""See base class."""
```
<a id="s3.8.4-comments-in-classes"></a>
<a id="384-classes"></a>
<a id="comments-in-classes"></a>
@ -2065,8 +2246,8 @@ def fetch_smalltable_rows(
#### 3.8.4 Classes
Classes should have a docstring below the class definition describing the class.
If your class has public attributes, they should be documented here in an
`Attributes` section and follow the same formatting as a
Public attributes, excluding [properties](#properties), should be documented
here in an `Attributes` section and follow the same formatting as a
[function's `Args`](#doc-function-args) section.
```python
@ -2090,8 +2271,9 @@ class SampleClass:
self.likes_spam = likes_spam
self.eggs = 0
def public_method(self):
"""Performs operation blah."""
@property
def butter_sticks(self) -> int:
"""The number of butter sticks we have."""
```
All class docstrings should start with a one-line summary that describes what
@ -2366,7 +2548,7 @@ messages shown to the user) should follow three guidelines:
```python
Yes:
if not 0 <= p <= 1:
raise ValueError(f'Not a probability: {p!r}')
raise ValueError(f'Not a probability: {p=}')
try:
os.rmdir(workdir)
@ -2378,7 +2560,7 @@ messages shown to the user) should follow three guidelines:
```python
No:
if p < 0 or p > 1: # PROBLEM: also false for float('nan')!
raise ValueError(f'Not a probability: {p!r}')
raise ValueError(f'Not a probability: {p=}')
try:
os.rmdir(workdir)
@ -2477,27 +2659,36 @@ documentation must explain clearly how resource lifetime is managed.
Use `TODO` comments for code that is temporary, a short-term solution, or
good-enough but not perfect.
A `TODO` comment begins with the word `TODO` in all caps, and a parenthesized
context identifier. Ideally a bug reference, sometimes a username. A bug
reference like `TODO(https://crbug.com/bug_id_number):` is
preferable, because bugs are tracked and have follow-up comments, whereas
individuals move around and may lose context over time. The `TODO` is followed by an explanation of
what there is to do.
A `TODO` comment begins with the word `TODO` in all caps, a following colon, and
a link to a resource that contains the context, ideally a bug reference. A bug
reference is preferable because bugs are tracked and have follow-up comments.
Follow this piece of context with an explanatory string introduced with a hyphen
`-`.
The purpose is to have a consistent `TODO` format that can be searched to find
out how to get more details. A `TODO` is not a commitment that the person
referenced will fix the problem. Thus when you create a `TODO` with a username,
it is almost always your *own* username that is given.
out how to get more details.
```python
# TODO: crbug.com/192795 - Investigate cpufreq optimizations.
```
Old style, formerly recommended, but discouraged for use in new code:
```python
# TODO(crbug.com/192795): Investigate cpufreq optimizations.
# TODO(yourusername): File an issue and use a '*' for repetition.
# TODO(yourusername): Use a "\*" here for concatenation operator.
```
Avoid adding TODOs that refer to an individual or team as the context:
```python
# TODO: @yourusername - File an issue and use a '*' for repetition.
```
If your `TODO` is of the form "At a future date do something" make sure that you
either include a very specific date ("Fix by November 2009") or a very specific
event ("Remove this code when all clients can handle XML responses.") that
future code maintainers will comprehend.
future code maintainers will comprehend. Issues are ideal for tracking this.
<a id="s3.13-imports-formatting"></a>
<a id="313-imports-formatting"></a>
@ -2722,7 +2913,9 @@ Always use a `.py` filename extension. Never use dashes.
class.
- Prepending a single underscore (`_`) has some support for protecting module
variables and functions (linters will flag protected member access).
variables and functions (linters will flag protected member access). Note
that it is okay for unit tests to access protected constants from the
modules under test.
- Prepending a double underscore (`__` aka "dunder") to an instance variable
or method effectively makes the variable or method private to its class
@ -2930,13 +3123,20 @@ the function into smaller and more manageable pieces.
* Familiarize yourself with [PEP-484](https://peps.python.org/pep-0484/).
* In methods, only annotate `self`, or `cls` if it is necessary for proper
type information. e.g.,
* Annotating `self` or `cls` is generally not necessary.
[`Self`](https://docs.python.org/3/library/typing.html#typing.Self) can be
used if it is necessary for proper type information, e.g.
```python
from typing import Self
class BaseClass:
@classmethod
def create(cls: Type[_T]) -> _T:
return cls()
def create(cls) -> Self:
...
def difference(self, other: Self) -> float:
...
```
* Similarly, don't feel compelled to annotate the return value of `__init__`
@ -3327,15 +3527,16 @@ return type is the same as the argument type in the code above, use
<a id="typing-imports"></a>
#### 3.19.12 Imports For Typing
For symbols from the `typing` and `collections.abc` modules used to support
static analysis and type checking, always import the symbol itself. This keeps
common annotations more concise and matches typing practices used around the
world. You are explicitly allowed to import multiple specific classes on one
line from the `typing` and `collections.abc` modules. Ex:
For symbols (including types, functions, and constants) from the `typing` or
`collections.abc` modules used to support static analysis and type checking,
always import the symbol itself. This keeps common annotations more concise and
matches typing practices used around the world. You are explicitly allowed to
import multiple specific symbols on one line from the `typing` and
`collections.abc` modules. For example:
```python
from collections.abc import Mapping, Sequence
from typing import Any, Generic
from typing import Any, Generic, cast, TYPE_CHECKING
```
Given that this way of importing adds items to the local namespace, names in

View File

@ -5,7 +5,7 @@
# Its canonical open-source location is:
# https://google.github.io/styleguide/pylintrc
[MASTER]
[MAIN]
# Files or directories to be skipped. They should be base names, not paths.
ignore=third_party
@ -50,7 +50,8 @@ confidence=
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=abstract-method,
disable=R,
abstract-method,
apply-builtin,
arguments-differ,
attribute-defined-outside-init,
@ -66,7 +67,6 @@ disable=abstract-method,
coerce-method,
delslice-method,
div-method,
duplicate-code,
eq-without-hash,
execfile-builtin,
file-builtin,
@ -80,7 +80,6 @@ disable=abstract-method,
import-error,
import-self,
import-star-module-level,
inconsistent-return-statements,
input-builtin,
intern-builtin,
invalid-str-codec,
@ -94,10 +93,6 @@ disable=abstract-method,
next-method-called,
next-method-defined,
no-absolute-import,
no-else-break,
no-else-continue,
no-else-raise,
no-else-return,
no-init, # added
no-member,
no-name-in-module,
@ -123,24 +118,12 @@ disable=abstract-method,
standarderror-builtin,
suppressed-message,
sys-max-int,
too-few-public-methods,
too-many-ancestors,
too-many-arguments,
too-many-boolean-expressions,
too-many-branches,
too-many-instance-attributes,
too-many-locals,
too-many-nested-blocks,
too-many-public-methods,
too-many-return-statements,
too-many-statements,
trailing-newlines,
unichr-builtin,
unicode-builtin,
unnecessary-pass,
unpacking-in-except,
useless-else-on-loop,
useless-object-inheritance,
useless-suppression,
using-cmp-argument,
wrong-import-order,
@ -225,7 +208,7 @@ no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=10
docstring-min-length=12
[TYPECHECK]
@ -235,10 +218,6 @@ docstring-min-length=10
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
@ -261,7 +240,7 @@ generated-members=
# Maximum number of characters on a single line.
max-line-length=80
# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt
# TODO(https://github.com/pylint-dev/pylint/issues/3352): Direct pylint to exempt
# lines made too long by directives to pytype.
# Regexp for a line that is allowed to be longer than the limit.
@ -418,12 +397,3 @@ valid-classmethod-first-arg=cls,
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=builtins.StandardError,
builtins.Exception,
builtins.BaseException

View File

@ -7,7 +7,13 @@ body {
margin-left: 100px;
}
h1, h2, h3, h4, h5, h6, .toc_title {
h1,
h2,
h3,
h4,
h5,
h6,
.toc_title {
color: #06c;
margin-top: 2em;
margin-bottom: 1em;
@ -18,38 +24,47 @@ h1 {
font-size: 18pt;
}
h2, .toc_title {
h2,
.toc_title {
font-weight: bold;
font-size: 12pt;
margin-left: -40px;
}
h3, h4, h5, h6 {
h3,
h4,
h5,
h6 {
font-size: 10pt;
margin-left: -20px;
}
.toc_category, .toc_stylepoint {
.toc_category,
.toc_stylepoint {
font-size: 10pt;
padding-top: .3em;
padding-bottom: .3em;
padding-top: 0.3em;
padding-bottom: 0.3em;
}
table {
border-collapse: collapse;
}
td, th {
td,
th {
border: 1px solid #ccc;
padding: 2px 12px;
font-size: 10pt;
}
.toc td, .toc th {
.toc td,
.toc th {
border-width: 1px 5px;
}
code, samp, var {
code,
samp,
var {
color: #060;
}
@ -58,16 +73,9 @@ pre {
display: block;
color: #060;
background-color: #f8fff8;
border-color: #f0fff0;
border-style: solid;
border-top-width: 1px;
border-bottom-width: 1px;
border-right-width: 1px;
border: 1px solid #f0fff0;
border-left-width: 5px;
padding-left: 12px;
padding-right: 12px;
padding-top: 4px;
padding-bottom: 4px;
padding: 4px 12px;
}
pre.badcode {
@ -79,8 +87,7 @@ pre.badcode {
.showhide_button {
float: left;
cursor: pointer;
border-width: 1px;
border-style: solid;
border: 1px solid;
border-color: #ddd #aaa #aaa #ddd;
padding: 0 3px 1px;
margin: 0 4px 8px 0;
@ -93,9 +100,7 @@ pre.badcode {
float: left;
display: none;
background-color: #f8f8ff;
border-color: #f0f0ff;
border-style: solid;
border-width: 1px;
border: 1px solid #f0f0ff;
font-size: 75%;
margin-top: 0;
margin-left: -50px;
@ -118,7 +123,7 @@ hr {
.stylepoint_section {
display: block;
margin-bottom: 1em;
color: #5588ff;
color: #58f;
font-family: sans-serif;
font-size: 90%;
font-weight: bold;
@ -126,7 +131,7 @@ hr {
}
.stylepoint_subsection {
color: #667799;
color: #679;
font-family: sans-serif;
font-size: 90%;
font-weight: bold;
@ -134,7 +139,7 @@ hr {
}
.stylepoint_subsubsection {
color: #667799;
color: #679;
font-family: sans-serif;
font-size: 80%;
font-weight: bold;
@ -144,4 +149,3 @@ hr {
.revision {
text-align: right;
}

File diff suppressed because it is too large Load Diff