Skip to content

Commit 073b1e1

Browse files
committed
Linting. Add linting to CI.
1 parent 9e73b59 commit 073b1e1

11 files changed

+133
-42
lines changed

Diff for: .github/workflows/tests.yml

+8
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ jobs:
8989
- name: Doctest
9090
run: |
9191
sphinx-build -b doctest -d docs/_build/doctrees2 docs docs/_build/doctest2
92+
- name: Lint
93+
if: matrix.python-version == '3.10' && startsWith(runner.os, 'Linux')
94+
# We only need to do this on one version.
95+
# We do this here rather than a separate job to avoid the compilation overhead.
96+
run: |
97+
pip install -U pylint
98+
python -m pylint --rcfile=.pylintrc greenlet
99+
92100
- name: Publish package to PyPI (mac)
93101
# We cannot 'uses: pypa/[email protected]' because
94102
# that's apparently a container action, and those don't run on

Diff for: .pylintrc

+109-22
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,85 @@
11
[MASTER]
2-
load-plugins=pylint.extensions.bad_builtin
2+
load-plugins=pylint.extensions.bad_builtin,
3+
pylint.extensions.code_style,
4+
pylint.extensions.dict_init_mutate,
5+
pylint.extensions.dunder,
6+
pylint.extensions.comparison_placement,
7+
pylint.extensions.confusing_elif,
8+
pylint.extensions.for_any_all,
9+
pylint.extensions.consider_refactoring_into_while_condition,
10+
pylint.extensions.check_elif,
11+
pylint.extensions.eq_without_hash,
12+
pylint.extensions.overlapping_exceptions,
13+
14+
# pylint.extensions.comparetozero,
15+
# Takes out ``if x == 0:`` and wants you to write ``if not x:``
16+
# but in many cases, the == 0 is actually much more clear.
17+
18+
# pylint.extensions.mccabe,
19+
# We have too many too-complex methods. We should enable this and fix them
20+
# one by one.
21+
22+
# pylint.extensions.redefined_variable_type,
23+
# We use that pattern during initialization.
24+
25+
# magic_value wants you to not use arbitrary strings and numbers
26+
# inline in the code. But it's overzealous and has way too many false
27+
# positives. Trust people to do the most readable thing.
28+
# pylint.extensions.magic_value
29+
30+
# Empty comment would be good, except it detects blank lines within
31+
# a single comment block.
32+
#
33+
# Those are often used to separate paragraphs, like here.
34+
# pylint.extensions.empty_comment,
35+
36+
# consider_ternary_expression is a nice check, but is also overzealous.
37+
# Trust the human to do the readable thing.
38+
# pylint.extensions.consider_ternary_expression,
39+
40+
# redefined_loop_name tends to catch us with things like
41+
# for name in (a, b, c): name = name + '_column' ...
42+
# pylint.extensions.redefined_loop_name,
43+
44+
# This wants you to turn ``x in (1, 2)`` into ``x in {1, 2}``.
45+
# They both result in the LOAD_CONST bytecode, one a tuple one a
46+
# frozenset. In theory a set lookup using hashing is faster than
47+
# a linear scan of a tuple; but if the tuple is small, it can often
48+
# actually be faster to scan the tuple.
49+
# pylint.extensions.set_membership,
50+
351
# Fix zope.cachedescriptors.property.Lazy; the property-classes doesn't seem to
452
# do anything.
553
# https://stackoverflow.com/questions/51160955/pylint-how-to-specify-a-self-defined-property-decorator-with-property-classes
6-
init-hook = "import astroid.bases; astroid.bases.POSSIBLE_PROPERTIES.add('Lazy')"
54+
# For releases prior to 2.14.2, this needs to be a one-line, quoted string. After that,
55+
# a multi-line string.
56+
# - Make zope.cachedescriptors.property.Lazy look like a property;
57+
# fixes pylint thinking it is a method.
58+
# - Run in Pure Python mode (ignore C extensions that respect this);
59+
# fixes some issues with zope.interface, like IFoo.providedby(ob)
60+
# claiming not to have the right number of parameters...except no, it does not.
61+
init-hook =
62+
import astroid.bases
63+
astroid.bases.POSSIBLE_PROPERTIES.add('Lazy')
64+
astroid.bases.POSSIBLE_PROPERTIES.add('LazyOnClass')
65+
astroid.bases.POSSIBLE_PROPERTIES.add('readproperty')
66+
astroid.bases.POSSIBLE_PROPERTIES.add('non_overridable')
67+
import os
68+
os.environ['PURE_PYTHON'] = ("1")
69+
# Ending on a quoted string
70+
# breaks pylint 2.14.5 (it strips the trailing quote. This is
71+
# probably because it tries to handle one-line quoted strings as well as multi-blocks).
72+
# The parens around it fix the issue.
73+
74+
extension-pkg-whitelist=greenlet._greenlet
75+
76+
# Control the amount of potential inferred values when inferring a single
77+
# object. This can help the performance when dealing with large functions or
78+
# complex, nested conditions.
79+
# gevent: The changes for Python 3.7 in _ssl3.py lead to infinite recursion
80+
# in pylint 2.3.1/astroid 2.2.5 in that file unless we this this to 1
81+
# from the default of 100.
82+
limit-inference-results=1
783

884
[MESSAGES CONTROL]
985

@@ -49,31 +125,55 @@ init-hook = "import astroid.bases; astroid.bases.POSSIBLE_PROPERTIES.add('Lazy')
49125
# Pylint 2.4 adds self-assigning-variable. But we do *that* to avoid unused-import when we
50126
# "export" the variable and don't have a __all__.
51127
# Pylint 2.6+ adds some python-3-only things that don't apply: raise-missing-from, super-with-arguments, consider-using-f-string, redundant-u-string-prefix
128+
# unnecessary-lambda-assignment: New check introduced in v2.14.0
129+
# unnecessary-dunder-call: New check introduced in v2.14.0
130+
# consider-using-assignment-expr: wants you to use the walrus operator.
131+
# It hits way too much and its not clear they would be improvements.
132+
# confusing-consecutive-elif: Are they though?
52133
disable=wrong-import-position,
53134
wrong-import-order,
54135
missing-docstring,
55136
ungrouped-imports,
56137
invalid-name,
138+
protected-access,
57139
too-few-public-methods,
140+
exec-used,
58141
global-statement,
142+
multiple-statements,
59143
locally-disabled,
144+
cyclic-import,
60145
too-many-arguments,
146+
redefined-builtin,
61147
useless-suppression,
62148
duplicate-code,
149+
undefined-all-variable,
150+
inconsistent-return-statements,
151+
useless-return,
63152
useless-object-inheritance,
64153
import-outside-toplevel,
65154
self-assigning-variable,
66-
consider-using-f-string
155+
raise-missing-from,
156+
super-with-arguments,
157+
consider-using-f-string,
158+
consider-using-assignment-expr,
159+
redundant-u-string-prefix,
160+
unnecessary-lambda-assignment,
161+
unnecessary-dunder-call,
162+
use-dict-literal,
163+
confusing-consecutive-elif,
164+
67165

166+
enable=consider-using-augmented-assign
68167

69168
[FORMAT]
70-
max-line-length=100
169+
# duplicated from setup.cfg
170+
max-line-length=160
71171
max-module-lines=1100
72172

73173
[MISCELLANEOUS]
74174
# List of note tags to take in consideration, separated by a comma.
75175
#notes=FIXME,XXX,TODO
76-
# Disable that, we don't want them to fail the lint CI job.
176+
# Disable that, we don't want them in the report (???)
77177
notes=
78178

79179
[VARIABLES]
@@ -85,14 +185,8 @@ dummy-variables-rgx=_.*
85185
# List of members which are set dynamically and missed by pylint inference
86186
# system, and so shouldn't trigger E1101 when accessed. Python regular
87187
# expressions are accepted.
88-
generated-members=REQUEST,acl_users,aq_parent,providedBy
89-
90-
91-
# Tells whether missing members accessed in mixin class should be ignored. A
92-
# mixin class is detected if its name ends with "mixin" (case insensitive).
93-
# XXX: deprecated in 2.14; replaced with ignored-checks-for-mixins.
94-
# The defaults for that value seem to be what we want
95-
#ignore-mixin-members=yes
188+
# gevent: this is helpful for py3/py2 code.
189+
generated-members=exc_clear
96190

97191
# List of classes names for which member attributes should not be checked
98192
# (useful for classes with attributes dynamically set). This can work
@@ -104,25 +198,18 @@ generated-members=REQUEST,acl_users,aq_parent,providedBy
104198
# (useful for modules/projects where namespaces are manipulated during runtime
105199
# and thus existing member attributes cannot be deduced by static analysis. It
106200
# supports qualified module names, as well as Unix pattern matching.
107-
#ignored-modules=gevent._corecffi,gevent.os,os,greenlet,threading,gevent.libev.corecffi,gevent.socket,gevent.core,gevent.testing.support
201+
ignored-modules=gevent._corecffi,gevent.os,os,greenlet,threading,gevent.libev.corecffi,gevent.socket,gevent.core,gevent.testing.support
108202

109203
[DESIGN]
110204
max-attributes=12
111205
max-parents=10
112206

113207
[BASIC]
208+
bad-functions=input
114209
# Prospector turns ot unsafe-load-any-extension by default, but
115210
# pylint leaves it off. This is the proximal cause of the
116211
# undefined-all-variable crash.
117212
unsafe-load-any-extension = yes
118-
property-classes=zope.cachedescriptors.property.Lazy,zope.cachedescriptors.property.Cached
119-
extension-pkg-allow-list=greenlet._greenlet
120-
121-
[CLASSES]
122-
# List of interface methods to ignore, separated by a comma. This is used for
123-
# instance to not check methods defines in Zope's Interface base class.
124-
125-
126213

127214
# Local Variables:
128215
# mode: conf

Diff for: CHANGES.rst

+8-14
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,14 @@
22
Changes
33
=========
44

5-
3.1.0 (unreleased)
5+
3.0.3 (unreleased)
66
==================
77

88
- Python 3.12: Restore the full ability to walk the stack of a suspended
9-
greenlet; previously only the innermost frame was exposed.
10-
For performance reasons, there are still some restrictions relative to
11-
older Python versions; in particular, by default it is only valid to walk
12-
a suspended greenlet's stack in between a ``gr_frame`` access and the next
13-
resumption of the greenlet. A more flexible mode can be enabled by setting
14-
the greenlet's new ``gr_frames_always_exposed`` attribute to True. If you
15-
get a Python interpreter crash on 3.12+ when accessing the ``f_back`` of a
16-
suspended greenlet frame, you're probably accessing it in a way that
17-
requires you to set this attribute. See `issue 388
18-
<https://github.com/python-greenlet/greenlet/issues/388>`_.
9+
greenlet; previously only the innermost frame was exposed. See `issue 388
10+
<https://github.com/python-greenlet/greenlet/issues/388>`_. Fix by
11+
Joshua Oreman in `PR 393
12+
<https://github.com/python-greenlet/greenlet/pull/393/>`_.
1913

2014
3.0.2 (2023-12-08)
2115
==================
@@ -251,7 +245,7 @@ Known Issues
251245
====================
252246

253247
Platforms
254-
~~~~~~~~~
248+
---------
255249

256250
- Add experimental, untested support for 64-bit Windows on ARM using
257251
MSVC. See `PR 271 <https://github.com/python-greenlet/greenlet/pull/271>`_.
@@ -401,7 +395,7 @@ Changes
401395
- (Documentation) Publish the change log to https://greenlet.readthedocs.io
402396

403397
Supported Platforms
404-
~~~~~~~~~~~~~~~~~~~
398+
-------------------
405399

406400
- Drop support for Python 2.4, 2.5, 2.6, 3.0, 3.1, 3.2 and 3.4.
407401
The project metadata now includes the ``python_requires`` data to
@@ -411,7 +405,7 @@ Supported Platforms
411405
<https://github.com/python-greenlet/greenlet/pull/197>`_.
412406

413407
Packaging Changes
414-
~~~~~~~~~~~~~~~~~
408+
-----------------
415409

416410
- Require setuptools to build from source.
417411
- Stop asking setuptools to build both .tar.gz and .zip

Diff for: setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ def get_greenlet_version():
247247
extras_require={
248248
'docs': [
249249
'Sphinx',
250+
'furo',
250251
],
251252
'test': [
252253
'objgraph',

Diff for: src/greenlet/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
###
2626
# Metadata
2727
###
28-
__version__ = '3.1.0.dev0'
28+
__version__ = '3.0.3.dev0'
2929
from ._greenlet import _C_API # pylint:disable=no-name-in-module
3030

3131
###

Diff for: src/greenlet/tests/leakcheck.py

+1
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ def _run_test(self, args, kwargs):
220220

221221
def _growth_after(self):
222222
# Grab post snapshot
223+
# pylint:disable=no-member
223224
if 'urlparse' in sys.modules:
224225
sys.modules['urlparse'].clear_cache()
225226
if 'urllib.parse' in sys.modules:

Diff for: src/greenlet/tests/test_contextvars.py

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def _increment(self, greenlet_id, callback, counts, expect):
4747
callback()
4848

4949
def _test_context(self, propagate_by):
50+
# pylint:disable=too-many-branches
5051
ID_VAR.set(0)
5152

5253
callback = getcurrent().switch

Diff for: src/greenlet/tests/test_gc.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def test_dead_circular_ref(self):
2323

2424
def test_circular_greenlet(self):
2525
class circular_greenlet(greenlet.greenlet):
26-
pass
26+
self = None
2727
o = circular_greenlet()
2828
o.self = o
2929
o = weakref.ref(o)

Diff for: src/greenlet/tests/test_generator_nested.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def test_permutations(self):
149149
# XXX Test to make sure we are working as a generator expression
150150

151151
def test_genlet_simple(self):
152-
for g in [g1, g2, g3]:
152+
for g in g1, g2, g3:
153153
seen = []
154154
for _ in range(3):
155155
for j in g(5, seen):

Diff for: src/greenlet/tests/test_throw.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ def f1():
6767
main.switch("f1 ready to catch")
6868
except IndexError:
6969
return "caught"
70-
else:
71-
return "normal exit"
70+
return "normal exit"
7271

7372
def f2():
7473
main.switch("from f2")

Diff for: src/greenlet/tests/test_weakref.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import gc
22
import weakref
3-
import unittest
3+
44

55
import greenlet
66
from . import TestCase

0 commit comments

Comments
 (0)