PB2 event parsing in Python
Stefan Schuermans

Stefan Schuermans commited on 2020-05-23 13:15:14
Showing 8 changed files, with 855 additions and 14 deletions.

... ...
@@ -25,7 +25,7 @@ apt-get install -y build-essential cmake gcc \
25 25
                    libprotobuf-c-dev libprotobuf-dev
26 26
                    ninja-build \
27 27
                    protobuf-c-compiler protobuf-compiler \
28
-                   python3 python3-protobuf
28
+                   pylint3 python3 python3-protobuf
29 29
 ```
30 30
 
31 31
 Change to the directory of this `REAMDE.md` file.
... ...
@@ -26,6 +26,7 @@ endfunction(pyfile)
26 26
 pyfile(__init__)
27 27
 pyfile(dump)
28 28
 pyfile(parse)
29
+pyfile(processes)
29 30
 
30 31
 add_custom_target(
31 32
   python3_uproctrace
... ...
@@ -1,18 +1,22 @@
1
+"""
2
+Dumping of uproctrace protobuf 2 events.
3
+"""
4
+
1 5
 import uproctrace.parse
2 6
 
3 7
 
4
-def dump_event(f, out):
8
+def dump_event(proto_file, out) -> bool:
5 9
     """
6 10
     Read the first event from f and dump it to out.
7 11
     Return True if an event could be found and dumped, False otherwise.
8 12
     """
9 13
     # read event
10
-    event = uproctrace.parse.read_event(f)
11
-    if event is None:
14
+    pb2_ev = uproctrace.parse.read_event(proto_file)
15
+    if pb2_ev is None:
12 16
         return False
13 17
     # dump event
14 18
     print('event {', file=out)
15
-    for line in repr(event).split('\n'):
19
+    for line in repr(pb2_ev).split('\n'):
16 20
         if line != '':
17 21
             print('  ' + line, file=out)
18 22
     print('}', file=out)
... ...
@@ -1,27 +1,218 @@
1
-import uproctrace.uproctrace_pb2 as pb2
1
+"""
2
+Parsing of uproctrace protobuf 2 events.
3
+"""
4
+
5
+import abc
2 6
 import struct
3 7
 
8
+import uproctrace.uproctrace_pb2 as pb2
9
+
4 10
 
5
-def read_event(f):
11
+def read_event(proto_file):
6 12
     """
7
-    Read the first event from f and return it.
13
+    Read the first event from proto_file and return it.
8 14
     Return None if no event could be found.
9 15
     """
10 16
     # skip till after magic
11
-    magic = f.read(4)
17
+    magic = proto_file.read(4)
12 18
     while magic != b'upt0':
13 19
         if len(magic) < 4:
14 20
             return None  # EOF
15
-        magic = magic[1:] + f.read(1)  # search for magic byte for byte
21
+        magic = magic[1:] + proto_file.read(1)  # search magic byte for byte
16 22
     # read size of next event (32 bit network byte order)
17
-    size = f.read(4)
23
+    size = proto_file.read(4)
18 24
     if len(size) < 4:
19 25
         return None  # EOF
20 26
     size = struct.unpack('!L', size)[0]
21 27
     # read event data
22
-    data = f.read(size)
28
+    data = proto_file.read(size)
23 29
     if len(data) < size:
24 30
         return None  # EOF
25 31
     # unpack event
26
-    event = pb2.event.FromString(data)
27
-    return event
32
+    pb2_ev = pb2.event.FromString(data)
33
+    return pb2_ev
34
+
35
+
36
+class BaseEvent():
37
+    """
38
+    Base class for all events.
39
+    """
40
+    def __init__(self, pb2_ev: pb2.event):
41
+        """
42
+        Initialize base event from PB2 event.
43
+        """
44
+        super().__init__()
45
+        self._pb2_ev = pb2_ev
46
+        self._timestamp = self._pb2GetTimespec(pb2_ev.timestamp)
47
+
48
+    def _pb2GetStringList(self, s_l: pb2.stringlist) -> list:
49
+        """
50
+        Get PB2 string list as Python list.
51
+        """
52
+        return [s for s in s_l.s]
53
+
54
+    def _pb2GetTimespec(self, t_s: pb2.timespec) -> float:
55
+        """
56
+        Get PB2 timespec value in seconds.
57
+        """
58
+        sec = t_s.sec
59
+        if t_s.hasField('nsec'):
60
+            sec += t_s.nsec * 1e-9
61
+        return sec
62
+
63
+    @property
64
+    def timestamp(self) -> float:
65
+        """
66
+        Time of event (in s from epoch).
67
+        """
68
+        return self._timestamp
69
+
70
+
71
+class ProcBegin(BaseEvent):
72
+    """
73
+    Process begin event.
74
+    """
75
+    def __init__(self, pb2_ev: pb2.event):
76
+        """
77
+        Initialize process begin event from PB2 event.
78
+        """
79
+        super().__init__(pb2_ev)
80
+        p_b = pb2_ev.proc_begin.pid
81
+        self._pid = p_b.pid
82
+        self._ppid = p_b.ppid if p_b.hasField('ppid') else None
83
+        self._exe = p_b.exe if p_b.hasField('exe') else None
84
+        self._cwd = p_b.cwd if p_b.hasField('cwd') else None
85
+        self._cmdline = self._pb2GetStringList(
86
+            p_b.cmdline) if p_b.hasField('cmdline') else None
87
+        self._environ = self._pb2GetStringList(
88
+            p_b.environ) if p_b.hasField('environ') else None
89
+
90
+    @property
91
+    def pid(self) -> int:
92
+        """
93
+        ID of process.
94
+        """
95
+        return self._pid
96
+
97
+    @property
98
+    def ppid(self) -> int:
99
+        """
100
+        ID of parent process.
101
+        """
102
+        return self._ppid
103
+
104
+    @property
105
+    def exe(self) -> str:
106
+        """
107
+        Executable name of process.
108
+        """
109
+        return self._exe
110
+
111
+    @property
112
+    def cwd(self) -> str:
113
+        """
114
+        Current working directory of process.
115
+        """
116
+        return self._cwd
117
+
118
+    @property
119
+    def cmdline(self) -> list:
120
+        """
121
+        Command line arguments of process (list of strings).
122
+        """
123
+        return self._cmdline.copy()
124
+
125
+    @property
126
+    def environ(self) -> list:
127
+        """
128
+        Environment variables of process (list of strings).
129
+        """
130
+        return self._environ.copy()
131
+
132
+
133
+class ProcEnd(BaseEvent):
134
+    """
135
+    Process end event.
136
+    """
137
+    def __init__(self, pb2_ev: pb2.event):
138
+        """
139
+        Initialize process end event from PB2 event.
140
+        """
141
+        super().__init__(pb2_ev)
142
+        p_e = pb2_ev.proc_end
143
+        self._pid = p_e.pid
144
+        self._cpu_time = self._pb2GetTimespec(
145
+            p_e.cpu_time) if p_e.hasField('cpu_time') else None
146
+        self._user_time = self._pb2GetTimespec(
147
+            p_e.user_time) if p_e.hasField('user_time') else None
148
+        self._sys_time = self._pb2GetTimespec(
149
+            p_e.sys_time) if p_e.hasField('sys_time') else None
150
+        self._max_rss_kb = p_e.max_rss_kb if p_e.hasField(
151
+            'max_rss_kb') else None
152
+
153
+    @property
154
+    def pid(self) -> int:
155
+        """
156
+        ID of process.
157
+        """
158
+        return self._pid
159
+
160
+    @property
161
+    def cpu_time(self) -> float:
162
+        """
163
+        CPU time usage (in s).
164
+        """
165
+        return self._cpu_time
166
+
167
+    @property
168
+    def user_time(self) -> float:
169
+        """
170
+        CPU time usage in user-space (in s).
171
+        """
172
+        return self._user_time
173
+
174
+    @property
175
+    def sys_time(self) -> float:
176
+        """
177
+        CPU time usage in system (kernel) (in s).
178
+        """
179
+        return self._sys_time
180
+
181
+    @property
182
+    def max_rss_kb(self) -> int:
183
+        """
184
+        Maximum amount of memory used (in KiB).
185
+        """
186
+        return self._max_rss_kb
187
+
188
+
189
+class Visitor(abc.ABC):
190
+    """
191
+    Visitor interface for events.
192
+    """
193
+    @abc.abstractmethod
194
+    def visitProcBegin(self, proc_begin: ProcBegin):
195
+        """
196
+        Visit a process begin event.
197
+        """
198
+
199
+    @abc.abstractmethod
200
+    def visitProcEnd(self, proc_end: ProcEnd):
201
+        """
202
+        Visit a process end event.
203
+        """
204
+
205
+
206
+def parse_event(proto_file, visitor: Visitor) -> bool:
207
+    """
208
+    Read the first event from f, parse it and call visitor.
209
+    Return True if an event could be read and processed, False otherwise.
210
+    """
211
+    pb2_ev = read_event(proto_file)
212
+    if pb2_ev is None:
213
+        return False
214
+    if pb2_ev.HasField('proc_begin'):
215
+        visitor.visitProcBeEnd(ProcBegin(pb2_ev))
216
+    if pb2_ev.HasField('proc_end'):
217
+        visitor.visitProcEnd(ProcEnd(pb2_ev))
218
+    return True
... ...
@@ -0,0 +1,77 @@
1
+"""
2
+Processes in a trace file.
3
+"""
4
+
5
+import uproctrace.parse
6
+
7
+
8
+class Process():
9
+    """
10
+    A process parsed from a trace.
11
+    """
12
+
13
+    def __init__(self, pid: int):
14
+        """
15
+        Initialize process.
16
+        """
17
+        self._pid = pid
18
+        self._begin = None
19
+        self._end = None
20
+
21
+    def setBegin(self, proc_begin: uproctrace.parse.ProcBegin):
22
+        """
23
+        set begin event of process
24
+        """
25
+        self._begin = proc_begin
26
+
27
+    def setEnd(self, proc_end: uproctrace.parse.ProcEnd):
28
+        """
29
+        set end event of process
30
+        """
31
+        self._end = proc_end
32
+
33
+
34
+class Processes(uproctrace.parse.Visitor):
35
+    """
36
+    Collection of all processes from a trace.
37
+    """
38
+
39
+    def __init__(self, proto_file):
40
+        """
41
+        Initialize processes from a trace file (f).
42
+        """
43
+        super().__init__()
44
+        self._processes = dict()  # pid -> Process
45
+        self._readTrace(proto_file)
46
+
47
+    def _readTrace(self, proto_file):
48
+        """
49
+        Read events from trace file (proto_file) and add them.
50
+        """
51
+        while uproctrace.parse.parse_event(proto_file, self):
52
+            pass
53
+
54
+    def visitProcBegin(self, proc_begin: uproctrace.parse.ProcBegin):
55
+        """
56
+        Process a process begin event.
57
+        """
58
+        # new process
59
+        proc = Process(proc_begin.pid)
60
+        # add process to dict of current processes
61
+        self._processes[proc_begin.pid] = proc
62
+        # set begin event of process
63
+        proc.setBegin(proc_begin)
64
+
65
+    def visitProcEnd(self, proc_end: uproctrace.parse.ProcEnd):
66
+        """
67
+        Process a process end event.
68
+        """
69
+        # get process (or create it it is not known)
70
+        if proc_end.pid in self._processes:
71
+            proc = self._processes[proc_end.pid]
72
+        else:
73
+            proc = Process(proc_end.pid)
74
+        # set end event of process
75
+        proc.setEnd(proc_end)
76
+        # remove process from dict of current processes (it ended)
77
+        self._processes[proc_end.pid] = None
... ...
@@ -1,2 +1,3 @@
1 1
 add_subdirectory(first)
2
+add_subdirectory(pylint)
2 3
 add_subdirectory(trace_build)
... ...
@@ -0,0 +1,14 @@
1
+add_test(
2
+  NAME
3
+  pylint
4
+  COMMAND
5
+  pylint3 --rcfile=${CMAKE_CURRENT_SOURCE_DIR}/pylint.rc
6
+          --ignore uproctrace_pb2.py uproctrace
7
+)
8
+
9
+SET_TESTS_PROPERTIES(
10
+  pylint
11
+  PROPERTIES
12
+  ENVIRONMENT
13
+  "PYTHONPATH=${CMAKE_BINARY_DIR}/python3"
14
+)
... ...
@@ -0,0 +1,553 @@
1
+[MASTER]
2
+
3
+# A comma-separated list of package or module names from where C extensions may
4
+# be loaded. Extensions are loading into the active Python interpreter and may
5
+# run arbitrary code
6
+extension-pkg-whitelist=
7
+
8
+# Add files or directories to the blacklist. They should be base names, not
9
+# paths.
10
+ignore=CVS
11
+
12
+# Add files or directories matching the regex patterns to the blacklist. The
13
+# regex matches against base names, not paths.
14
+ignore-patterns=
15
+
16
+# Python code to execute, usually for sys.path manipulation such as
17
+# pygtk.require().
18
+#init-hook=
19
+
20
+# Use multiple processes to speed up Pylint.
21
+jobs=1
22
+
23
+# List of plugins (as comma separated values of python modules names) to load,
24
+# usually to register additional checkers.
25
+load-plugins=
26
+
27
+# Pickle collected data for later comparisons.
28
+persistent=yes
29
+
30
+# Specify a configuration file.
31
+#rcfile=
32
+
33
+# When enabled, pylint would attempt to guess common misconfiguration and emit
34
+# user-friendly hints instead of false-positive error messages
35
+suggestion-mode=yes
36
+
37
+# Allow loading of arbitrary C extensions. Extensions are imported into the
38
+# active Python interpreter and may run arbitrary code.
39
+unsafe-load-any-extension=no
40
+
41
+
42
+[MESSAGES CONTROL]
43
+
44
+# Only show warnings with the listed confidence levels. Leave empty to show
45
+# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
46
+confidence=
47
+
48
+# Disable the message, report, category or checker with the given id(s). You
49
+# can either give multiple identifiers separated by comma (,) or put this
50
+# option multiple times (only on the command line, not in the configuration
51
+# file where it should appear only once).You can also use "--disable=all" to
52
+# disable everything first and then reenable specific checks. For example, if
53
+# you want to run only the similarities checker, you can use "--disable=all
54
+# --enable=similarities". If you want to run only the classes checker, but have
55
+# no Warning level messages displayed, use"--disable=all --enable=classes
56
+# --disable=W"
57
+disable=print-statement,
58
+        parameter-unpacking,
59
+        unpacking-in-except,
60
+        old-raise-syntax,
61
+        backtick,
62
+        long-suffix,
63
+        old-ne-operator,
64
+        old-octal-literal,
65
+        import-star-module-level,
66
+        non-ascii-bytes-literal,
67
+        invalid-unicode-literal,
68
+        raw-checker-failed,
69
+        bad-inline-option,
70
+        locally-disabled,
71
+        locally-enabled,
72
+        file-ignored,
73
+        suppressed-message,
74
+        useless-suppression,
75
+        deprecated-pragma,
76
+        apply-builtin,
77
+        basestring-builtin,
78
+        buffer-builtin,
79
+        cmp-builtin,
80
+        coerce-builtin,
81
+        execfile-builtin,
82
+        file-builtin,
83
+        long-builtin,
84
+        raw_input-builtin,
85
+        reduce-builtin,
86
+        standarderror-builtin,
87
+        unicode-builtin,
88
+        xrange-builtin,
89
+        coerce-method,
90
+        delslice-method,
91
+        getslice-method,
92
+        setslice-method,
93
+        no-absolute-import,
94
+        old-division,
95
+        dict-iter-method,
96
+        dict-view-method,
97
+        next-method-called,
98
+        metaclass-assignment,
99
+        indexing-exception,
100
+        raising-string,
101
+        reload-builtin,
102
+        oct-method,
103
+        hex-method,
104
+        nonzero-method,
105
+        cmp-method,
106
+        input-builtin,
107
+        round-builtin,
108
+        intern-builtin,
109
+        unichr-builtin,
110
+        map-builtin-not-iterating,
111
+        zip-builtin-not-iterating,
112
+        range-builtin-not-iterating,
113
+        filter-builtin-not-iterating,
114
+        using-cmp-argument,
115
+        eq-without-hash,
116
+        div-method,
117
+        idiv-method,
118
+        rdiv-method,
119
+        exception-message-attribute,
120
+        invalid-str-codec,
121
+        sys-max-int,
122
+        bad-python3-import,
123
+        deprecated-string-function,
124
+        deprecated-str-translate-call,
125
+        deprecated-itertools-function,
126
+        deprecated-types-field,
127
+        next-method-defined,
128
+        dict-items-not-iterating,
129
+        dict-keys-not-iterating,
130
+        dict-values-not-iterating,
131
+        deprecated-operator-function,
132
+        deprecated-urllib-function,
133
+        xreadlines-attribute,
134
+        deprecated-sys-function,
135
+        exception-escape,
136
+        comprehension-escape,
137
+        fixme,
138
+        no-self-use,
139
+        todo,
140
+        too-few-public-methods
141
+
142
+# Enable the message, report, category or checker with the given id(s). You can
143
+# either give multiple identifier separated by comma (,) or put this option
144
+# multiple time (only on the command line, not in the configuration file where
145
+# it should appear only once). See also the "--disable" option for examples.
146
+enable=c-extension-no-member
147
+
148
+
149
+[REPORTS]
150
+
151
+# Python expression which should return a note less than 10 (10 is the highest
152
+# note). You have access to the variables errors warning, statement which
153
+# respectively contain the number of errors / warnings messages and the total
154
+# number of statements analyzed. This is used by the global evaluation report
155
+# (RP0004).
156
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
157
+
158
+# Template used to display messages. This is a python new-style format string
159
+# used to format the message information. See doc for all details
160
+#msg-template=
161
+
162
+# Set the output format. Available formats are text, parseable, colorized, json
163
+# and msvs (visual studio).You can also give a reporter class, eg
164
+# mypackage.mymodule.MyReporterClass.
165
+output-format=text
166
+
167
+# Tells whether to display a full report or only the messages
168
+reports=no
169
+
170
+# Activate the evaluation score.
171
+score=yes
172
+
173
+
174
+[REFACTORING]
175
+
176
+# Maximum number of nested blocks for function / method body
177
+max-nested-blocks=5
178
+
179
+# Complete name of functions that never returns. When checking for
180
+# inconsistent-return-statements if a never returning function is called then
181
+# it will be considered as an explicit return statement and no message will be
182
+# printed.
183
+never-returning-functions=optparse.Values,sys.exit
184
+
185
+
186
+[SIMILARITIES]
187
+
188
+# Ignore comments when computing similarities.
189
+ignore-comments=yes
190
+
191
+# Ignore docstrings when computing similarities.
192
+ignore-docstrings=yes
193
+
194
+# Ignore imports when computing similarities.
195
+ignore-imports=no
196
+
197
+# Minimum lines number of a similarity.
198
+min-similarity-lines=4
199
+
200
+
201
+[BASIC]
202
+
203
+# Naming style matching correct argument names
204
+argument-naming-style=snake_case
205
+
206
+# Regular expression matching correct argument names. Overrides argument-
207
+# naming-style
208
+#argument-rgx=
209
+
210
+# Naming style matching correct attribute names
211
+attr-naming-style=snake_case
212
+
213
+# Regular expression matching correct attribute names. Overrides attr-naming-
214
+# style
215
+#attr-rgx=
216
+
217
+# Bad variable names which should always be refused, separated by a comma
218
+bad-names=foo,
219
+          bar,
220
+          baz,
221
+          toto,
222
+          tutu,
223
+          tata
224
+
225
+# Naming style matching correct class attribute names
226
+class-attribute-naming-style=any
227
+
228
+# Regular expression matching correct class attribute names. Overrides class-
229
+# attribute-naming-style
230
+#class-attribute-rgx=
231
+
232
+# Naming style matching correct class names
233
+class-naming-style=PascalCase
234
+
235
+# Regular expression matching correct class names. Overrides class-naming-style
236
+#class-rgx=
237
+
238
+# Naming style matching correct constant names
239
+const-naming-style=UPPER_CASE
240
+
241
+# Regular expression matching correct constant names. Overrides const-naming-
242
+# style
243
+#const-rgx=
244
+
245
+# Minimum line length for functions/classes that require docstrings, shorter
246
+# ones are exempt.
247
+docstring-min-length=-1
248
+
249
+# Naming style matching correct function names
250
+function-naming-style=snake_case
251
+
252
+# Regular expression matching correct function names. Overrides function-
253
+# naming-style
254
+#function-rgx=
255
+
256
+# Good variable names which should always be accepted, separated by a comma
257
+good-names=i,
258
+           j,
259
+           k,
260
+           ex,
261
+           Run,
262
+           _
263
+
264
+# Include a hint for the correct naming format with invalid-name
265
+include-naming-hint=no
266
+
267
+# Naming style matching correct inline iteration names
268
+inlinevar-naming-style=any
269
+
270
+# Regular expression matching correct inline iteration names. Overrides
271
+# inlinevar-naming-style
272
+#inlinevar-rgx=
273
+
274
+# Naming style matching correct method names
275
+method-naming-style=camelCase
276
+
277
+# Regular expression matching correct method names. Overrides method-naming-
278
+# style
279
+#method-rgx=
280
+
281
+# Naming style matching correct module names
282
+module-naming-style=snake_case
283
+
284
+# Regular expression matching correct module names. Overrides module-naming-
285
+# style
286
+#module-rgx=
287
+
288
+# Colon-delimited sets of names that determine each other's naming style when
289
+# the name regexes allow several styles.
290
+name-group=
291
+
292
+# Regular expression which should only match function or class names that do
293
+# not require a docstring.
294
+no-docstring-rgx=^_
295
+
296
+# List of decorators that produce properties, such as abc.abstractproperty. Add
297
+# to this list to register other decorators that produce valid properties.
298
+property-classes=abc.abstractproperty
299
+
300
+# Naming style matching correct variable names
301
+variable-naming-style=snake_case
302
+
303
+# Regular expression matching correct variable names. Overrides variable-
304
+# naming-style
305
+#variable-rgx=
306
+
307
+
308
+[SPELLING]
309
+
310
+# Limits count of emitted suggestions for spelling mistakes
311
+max-spelling-suggestions=4
312
+
313
+# Spelling dictionary name. Available dictionaries: none. To make it working
314
+# install python-enchant package.
315
+spelling-dict=
316
+
317
+# List of comma separated words that should not be checked.
318
+spelling-ignore-words=
319
+
320
+# A path to a file that contains private dictionary; one word per line.
321
+spelling-private-dict-file=
322
+
323
+# Tells whether to store unknown words to indicated private dictionary in
324
+# --spelling-private-dict-file option instead of raising a message.
325
+spelling-store-unknown-words=no
326
+
327
+
328
+[FORMAT]
329
+
330
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
331
+expected-line-ending-format=
332
+
333
+# Regexp for a line that is allowed to be longer than the limit.
334
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
335
+
336
+# Number of spaces of indent required inside a hanging  or continued line.
337
+indent-after-paren=4
338
+
339
+# String used as indentation unit. This is usually "    " (4 spaces) or "\t" (1
340
+# tab).
341
+indent-string='    '
342
+
343
+# Maximum number of characters on a single line.
344
+max-line-length=100
345
+
346
+# Maximum number of lines in a module
347
+max-module-lines=1000
348
+
349
+# List of optional constructs for which whitespace checking is disabled. `dict-
350
+# separator` is used to allow tabulation in dicts, etc.: {1  : 1,\n222: 2}.
351
+# `trailing-comma` allows a space between comma and closing bracket: (a, ).
352
+# `empty-line` allows space-only lines.
353
+no-space-check=trailing-comma,
354
+               dict-separator
355
+
356
+# Allow the body of a class to be on the same line as the declaration if body
357
+# contains single statement.
358
+single-line-class-stmt=no
359
+
360
+# Allow the body of an if to be on the same line as the test if there is no
361
+# else.
362
+single-line-if-stmt=no
363
+
364
+
365
+[TYPECHECK]
366
+
367
+# List of decorators that produce context managers, such as
368
+# contextlib.contextmanager. Add to this list to register other decorators that
369
+# produce valid context managers.
370
+contextmanager-decorators=contextlib.contextmanager
371
+
372
+# List of members which are set dynamically and missed by pylint inference
373
+# system, and so shouldn't trigger E1101 when accessed. Python regular
374
+# expressions are accepted.
375
+generated-members=
376
+
377
+# Tells whether missing members accessed in mixin class should be ignored. A
378
+# mixin class is detected if its name ends with "mixin" (case insensitive).
379
+ignore-mixin-members=yes
380
+
381
+# This flag controls whether pylint should warn about no-member and similar
382
+# checks whenever an opaque object is returned when inferring. The inference
383
+# can return multiple potential results while evaluating a Python object, but
384
+# some branches might not be evaluated, which results in partial inference. In
385
+# that case, it might be useful to still emit no-member and other checks for
386
+# the rest of the inferred objects.
387
+ignore-on-opaque-inference=yes
388
+
389
+# List of class names for which member attributes should not be checked (useful
390
+# for classes with dynamically set attributes). This supports the use of
391
+# qualified names.
392
+ignored-classes=optparse.Values,thread._local,_thread._local
393
+
394
+# List of module names for which member attributes should not be checked
395
+# (useful for modules/projects where namespaces are manipulated during runtime
396
+# and thus existing member attributes cannot be deduced by static analysis. It
397
+# supports qualified module names, as well as Unix pattern matching.
398
+ignored-modules=uproctrace.uproctrace_pb2
399
+
400
+# Show a hint with possible names when a member name was not found. The aspect
401
+# of finding the hint is based on edit distance.
402
+missing-member-hint=yes
403
+
404
+# The minimum edit distance a name should have in order to be considered a
405
+# similar match for a missing member name.
406
+missing-member-hint-distance=1
407
+
408
+# The total number of similar names that should be taken in consideration when
409
+# showing a hint for a missing member.
410
+missing-member-max-choices=1
411
+
412
+
413
+[LOGGING]
414
+
415
+# Logging modules to check that the string format arguments are in logging
416
+# function parameter format
417
+logging-modules=logging
418
+
419
+
420
+[VARIABLES]
421
+
422
+# List of additional names supposed to be defined in builtins. Remember that
423
+# you should avoid to define new builtins when possible.
424
+additional-builtins=
425
+
426
+# Tells whether unused global variables should be treated as a violation.
427
+allow-global-unused-variables=yes
428
+
429
+# List of strings which can identify a callback function by name. A callback
430
+# name must start or end with one of those strings.
431
+callbacks=cb_,
432
+          _cb
433
+
434
+# A regular expression matching the name of dummy variables (i.e. expectedly
435
+# not used).
436
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
437
+
438
+# Argument names that match this expression will be ignored. Default to name
439
+# with leading underscore
440
+ignored-argument-names=_.*|^ignored_|^unused_
441
+
442
+# Tells whether we should check for unused import in __init__ files.
443
+init-import=no
444
+
445
+# List of qualified module names which can have objects that can redefine
446
+# builtins.
447
+redefining-builtins-modules=six.moves,past.builtins,future.builtins,io,builtins
448
+
449
+
450
+[MISCELLANEOUS]
451
+
452
+# List of note tags to take in consideration, separated by a comma.
453
+notes=FIXME,
454
+      XXX,
455
+      TODO
456
+
457
+
458
+[CLASSES]
459
+
460
+# List of method names used to declare (i.e. assign) instance attributes.
461
+defining-attr-methods=__init__,
462
+                      __new__,
463
+                      setUp
464
+
465
+# List of member names, which should be excluded from the protected access
466
+# warning.
467
+exclude-protected=_asdict,
468
+                  _fields,
469
+                  _replace,
470
+                  _source,
471
+                  _make
472
+
473
+# List of valid names for the first argument in a class method.
474
+valid-classmethod-first-arg=cls
475
+
476
+# List of valid names for the first argument in a metaclass class method.
477
+valid-metaclass-classmethod-first-arg=mcs
478
+
479
+
480
+[IMPORTS]
481
+
482
+# Allow wildcard imports from modules that define __all__.
483
+allow-wildcard-with-all=no
484
+
485
+# Analyse import fallback blocks. This can be used to support both Python 2 and
486
+# 3 compatible code, which means that the block might have code that exists
487
+# only in one or another interpreter, leading to false positives when analysed.
488
+analyse-fallback-blocks=no
489
+
490
+# Deprecated modules which should not be used, separated by a comma
491
+deprecated-modules=regsub,
492
+                   TERMIOS,
493
+                   Bastion,
494
+                   rexec
495
+
496
+# Create a graph of external dependencies in the given file (report RP0402 must
497
+# not be disabled)
498
+ext-import-graph=
499
+
500
+# Create a graph of every (i.e. internal and external) dependencies in the
501
+# given file (report RP0402 must not be disabled)
502
+import-graph=
503
+
504
+# Create a graph of internal dependencies in the given file (report RP0402 must
505
+# not be disabled)
506
+int-import-graph=
507
+
508
+# Force import order to recognize a module as part of the standard
509
+# compatibility libraries.
510
+known-standard-library=
511
+
512
+# Force import order to recognize a module as part of a third party library.
513
+known-third-party=enchant
514
+
515
+
516
+[DESIGN]
517
+
518
+# Maximum number of arguments for function / method
519
+max-args=5
520
+
521
+# Maximum number of attributes for a class (see R0902).
522
+max-attributes=7
523
+
524
+# Maximum number of boolean expressions in a if statement
525
+max-bool-expr=5
526
+
527
+# Maximum number of branch for function / method body
528
+max-branches=12
529
+
530
+# Maximum number of locals for function / method body
531
+max-locals=15
532
+
533
+# Maximum number of parents for a class (see R0901).
534
+max-parents=7
535
+
536
+# Maximum number of public methods for a class (see R0904).
537
+max-public-methods=20
538
+
539
+# Maximum number of return / yield for function / method body
540
+max-returns=6
541
+
542
+# Maximum number of statements in function / method body
543
+max-statements=50
544
+
545
+# Minimum number of public methods for a class (see R0903).
546
+min-public-methods=2
547
+
548
+
549
+[EXCEPTIONS]
550
+
551
+# Exceptions that will emit a warning when being caught. Defaults to
552
+# "Exception"
553
+overgeneral-exceptions=Exception
0 554