Skip to content

Commit

Permalink
Linting. Add linting to CI.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Dec 21, 2023
1 parent 57414b6 commit 615ea84
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 42 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/tests.yml
Expand Up @@ -89,6 +89,14 @@ jobs:
- name: Doctest
run: |
sphinx-build -b doctest -d docs/_build/doctrees2 docs docs/_build/doctest2
- name: Lint
if: matrix.python-version == '3.10' && startsWith(runner.os, 'Linux')
# We only need to do this on one version.
# We do this here rather than a separate job to avoid the compilation overhead.
run: |
pip install -U pylint
python -m pylint --rcfile=.pylintrc greenlet
- name: Publish package to PyPI (mac)
# We cannot 'uses: pypa/gh-action-pypi-publish@v1.4.1' because
# that's apparently a container action, and those don't run on
Expand Down
131 changes: 109 additions & 22 deletions .pylintrc
@@ -1,9 +1,85 @@
[MASTER]
load-plugins=pylint.extensions.bad_builtin
load-plugins=pylint.extensions.bad_builtin,
pylint.extensions.code_style,
pylint.extensions.dict_init_mutate,
pylint.extensions.dunder,
pylint.extensions.comparison_placement,
pylint.extensions.confusing_elif,
pylint.extensions.for_any_all,
pylint.extensions.consider_refactoring_into_while_condition,
pylint.extensions.check_elif,
pylint.extensions.eq_without_hash,
pylint.extensions.overlapping_exceptions,

# pylint.extensions.comparetozero,
# Takes out ``if x == 0:`` and wants you to write ``if not x:``
# but in many cases, the == 0 is actually much more clear.

# pylint.extensions.mccabe,
# We have too many too-complex methods. We should enable this and fix them
# one by one.

# pylint.extensions.redefined_variable_type,
# We use that pattern during initialization.

# magic_value wants you to not use arbitrary strings and numbers
# inline in the code. But it's overzealous and has way too many false
# positives. Trust people to do the most readable thing.
# pylint.extensions.magic_value

# Empty comment would be good, except it detects blank lines within
# a single comment block.
#
# Those are often used to separate paragraphs, like here.
# pylint.extensions.empty_comment,

# consider_ternary_expression is a nice check, but is also overzealous.
# Trust the human to do the readable thing.
# pylint.extensions.consider_ternary_expression,

# redefined_loop_name tends to catch us with things like
# for name in (a, b, c): name = name + '_column' ...
# pylint.extensions.redefined_loop_name,

# This wants you to turn ``x in (1, 2)`` into ``x in {1, 2}``.
# They both result in the LOAD_CONST bytecode, one a tuple one a
# frozenset. In theory a set lookup using hashing is faster than
# a linear scan of a tuple; but if the tuple is small, it can often
# actually be faster to scan the tuple.
# pylint.extensions.set_membership,

# Fix zope.cachedescriptors.property.Lazy; the property-classes doesn't seem to
# do anything.
# https://stackoverflow.com/questions/51160955/pylint-how-to-specify-a-self-defined-property-decorator-with-property-classes
init-hook = "import astroid.bases; astroid.bases.POSSIBLE_PROPERTIES.add('Lazy')"
# For releases prior to 2.14.2, this needs to be a one-line, quoted string. After that,
# a multi-line string.
# - Make zope.cachedescriptors.property.Lazy look like a property;
# fixes pylint thinking it is a method.
# - Run in Pure Python mode (ignore C extensions that respect this);
# fixes some issues with zope.interface, like IFoo.providedby(ob)
# claiming not to have the right number of parameters...except no, it does not.
init-hook =
import astroid.bases
astroid.bases.POSSIBLE_PROPERTIES.add('Lazy')
astroid.bases.POSSIBLE_PROPERTIES.add('LazyOnClass')
astroid.bases.POSSIBLE_PROPERTIES.add('readproperty')
astroid.bases.POSSIBLE_PROPERTIES.add('non_overridable')
import os
os.environ['PURE_PYTHON'] = ("1")
# Ending on a quoted string
# breaks pylint 2.14.5 (it strips the trailing quote. This is
# probably because it tries to handle one-line quoted strings as well as multi-blocks).
# The parens around it fix the issue.

extension-pkg-whitelist=greenlet._greenlet

# Control the amount of potential inferred values when inferring a single
# object. This can help the performance when dealing with large functions or
# complex, nested conditions.
# gevent: The changes for Python 3.7 in _ssl3.py lead to infinite recursion
# in pylint 2.3.1/astroid 2.2.5 in that file unless we this this to 1
# from the default of 100.
limit-inference-results=1

[MESSAGES CONTROL]

Expand Down Expand Up @@ -49,31 +125,55 @@ init-hook = "import astroid.bases; astroid.bases.POSSIBLE_PROPERTIES.add('Lazy')
# Pylint 2.4 adds self-assigning-variable. But we do *that* to avoid unused-import when we
# "export" the variable and don't have a __all__.
# 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
# unnecessary-lambda-assignment: New check introduced in v2.14.0
# unnecessary-dunder-call: New check introduced in v2.14.0
# consider-using-assignment-expr: wants you to use the walrus operator.
# It hits way too much and its not clear they would be improvements.
# confusing-consecutive-elif: Are they though?
disable=wrong-import-position,
wrong-import-order,
missing-docstring,
ungrouped-imports,
invalid-name,
protected-access,
too-few-public-methods,
exec-used,
global-statement,
multiple-statements,
locally-disabled,
cyclic-import,
too-many-arguments,
redefined-builtin,
useless-suppression,
duplicate-code,
undefined-all-variable,
inconsistent-return-statements,
useless-return,
useless-object-inheritance,
import-outside-toplevel,
self-assigning-variable,
consider-using-f-string
raise-missing-from,
super-with-arguments,
consider-using-f-string,
consider-using-assignment-expr,
redundant-u-string-prefix,
unnecessary-lambda-assignment,
unnecessary-dunder-call,
use-dict-literal,
confusing-consecutive-elif,


enable=consider-using-augmented-assign

[FORMAT]
max-line-length=100
# duplicated from setup.cfg
max-line-length=160
max-module-lines=1100

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

[VARIABLES]
Expand All @@ -85,14 +185,8 @@ dummy-variables-rgx=_.*
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=REQUEST,acl_users,aq_parent,providedBy


# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
# XXX: deprecated in 2.14; replaced with ignored-checks-for-mixins.
# The defaults for that value seem to be what we want
#ignore-mixin-members=yes
# gevent: this is helpful for py3/py2 code.
generated-members=exc_clear

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

[DESIGN]
max-attributes=12
max-parents=10

[BASIC]
bad-functions=input
# Prospector turns ot unsafe-load-any-extension by default, but
# pylint leaves it off. This is the proximal cause of the
# undefined-all-variable crash.
unsafe-load-any-extension = yes
property-classes=zope.cachedescriptors.property.Lazy,zope.cachedescriptors.property.Cached
extension-pkg-allow-list=greenlet._greenlet

[CLASSES]
# List of interface methods to ignore, separated by a comma. This is used for
# instance to not check methods defines in Zope's Interface base class.



# Local Variables:
# mode: conf
Expand Down
22 changes: 8 additions & 14 deletions CHANGES.rst
Expand Up @@ -2,20 +2,14 @@
Changes
=========

3.1.0 (unreleased)
3.0.3 (unreleased)
==================

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

3.0.2 (2023-12-08)
==================
Expand Down Expand Up @@ -251,7 +245,7 @@ Known Issues
====================

Platforms
~~~~~~~~~
---------

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

Supported Platforms
~~~~~~~~~~~~~~~~~~~
-------------------

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

Packaging Changes
~~~~~~~~~~~~~~~~~
-----------------

- Require setuptools to build from source.
- Stop asking setuptools to build both .tar.gz and .zip
Expand Down
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -247,6 +247,7 @@ def get_greenlet_version():
extras_require={
'docs': [
'Sphinx',
'furo',
],
'test': [
'objgraph',
Expand Down
2 changes: 1 addition & 1 deletion src/greenlet/__init__.py
Expand Up @@ -25,7 +25,7 @@
###
# Metadata
###
__version__ = '3.1.0.dev0'
__version__ = '3.0.3.dev0'
from ._greenlet import _C_API # pylint:disable=no-name-in-module

###
Expand Down
1 change: 1 addition & 0 deletions src/greenlet/tests/leakcheck.py
Expand Up @@ -220,6 +220,7 @@ def _run_test(self, args, kwargs):

def _growth_after(self):
# Grab post snapshot
# pylint:disable=no-member
if 'urlparse' in sys.modules:
sys.modules['urlparse'].clear_cache()
if 'urllib.parse' in sys.modules:
Expand Down
1 change: 1 addition & 0 deletions src/greenlet/tests/test_contextvars.py
Expand Up @@ -47,6 +47,7 @@ def _increment(self, greenlet_id, callback, counts, expect):
callback()

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

callback = getcurrent().switch
Expand Down
2 changes: 1 addition & 1 deletion src/greenlet/tests/test_gc.py
Expand Up @@ -23,7 +23,7 @@ def test_dead_circular_ref(self):

def test_circular_greenlet(self):
class circular_greenlet(greenlet.greenlet):
pass
self = None
o = circular_greenlet()
o.self = o
o = weakref.ref(o)
Expand Down
2 changes: 1 addition & 1 deletion src/greenlet/tests/test_generator_nested.py
Expand Up @@ -149,7 +149,7 @@ def test_permutations(self):
# XXX Test to make sure we are working as a generator expression

def test_genlet_simple(self):
for g in [g1, g2, g3]:
for g in g1, g2, g3:
seen = []
for _ in range(3):
for j in g(5, seen):
Expand Down
3 changes: 1 addition & 2 deletions src/greenlet/tests/test_throw.py
Expand Up @@ -67,8 +67,7 @@ def f1():
main.switch("f1 ready to catch")
except IndexError:
return "caught"
else:
return "normal exit"
return "normal exit"

def f2():
main.switch("from f2")
Expand Down
2 changes: 1 addition & 1 deletion src/greenlet/tests/test_weakref.py
@@ -1,6 +1,6 @@
import gc
import weakref
import unittest


import greenlet
from . import TestCase
Expand Down

0 comments on commit 615ea84

Please sign in to comment.