Skip to content

change to ruff #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 16, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

.py text eol=lf
.rst text eol=lf
.txt text eol=lf
.yaml text eol=lf
.toml text eol=lf
.license text eol=lf
.md text eol=lf
43 changes: 11 additions & 32 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,42 +1,21 @@
# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò
# SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

repos:
- repo: https://github.com/python/black
rev: 22.3.0
hooks:
- id: black
- repo: https://github.com/fsfe/reuse-tool
rev: v0.14.0
hooks:
- id: reuse
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
rev: v4.5.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pycqa/pylint
rev: v2.15.5
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.4
hooks:
- id: pylint
name: pylint (library code)
types: [python]
args:
- --disable=consider-using-f-string
exclude: "^(docs/|examples/|tests/|setup.py$)"
- id: pylint
name: pylint (example code)
description: Run pylint rules on "examples/*.py" files
types: [python]
files: "^examples/"
args:
- --disable=missing-docstring,invalid-name,consider-using-f-string,duplicate-code
- id: pylint
name: pylint (test code)
description: Run pylint rules on "tests/*.py" files
types: [python]
files: "^tests/"
args:
- --disable=missing-docstring,consider-using-f-string,duplicate-code
- id: ruff-format
- id: ruff
args: ["--fix"]
- repo: https://github.com/fsfe/reuse-tool
rev: v3.0.1
hooks:
- id: reuse
399 changes: 0 additions & 399 deletions .pylintrc

This file was deleted.

6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
@@ -17,9 +17,9 @@ Introduction
:alt: Build Status


.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
:alt: Code Style: Black
.. image:: https://img.shields.io/endpoint?url=https://github.com/raw/astral-sh/ruff/main/assets/badge/v2.json
:target: https://github.com/astral-sh/ruff
:alt: Code Style: Ruff


This library is a reimplementation and subset of `json_stream <https://github.com/daggaz/json-stream>`_. It enables reading JSON data from a stream rather that loading it all into memory at once. The interface works like lists and dictionaries that are usually returned from ``json.load()`` but require in-order access. Out of order accesses will lead to missing keys and list entries.
23 changes: 9 additions & 14 deletions adafruit_json_stream.py
Original file line number Diff line number Diff line change
@@ -40,9 +40,7 @@ def read(self):
self.i += 1
return char

def fast_forward(
self, closer, *, return_object=False
): # pylint: disable=too-many-branches
def fast_forward(self, closer, *, return_object=False):
"""
Read through the stream until the character is ``closer``, ``]``
(ending a list) or ``}`` (ending an object.) Intermediate lists and
@@ -87,7 +85,7 @@ def fast_forward(
elif close_stack[-1] == ord('"'):
# in a string so ignore [] and {}
pass
elif char in (ord("}"), ord("]")):
elif char in {ord("}"), ord("]")}:
# Mismatched list or object means we're done and already past the last comma.
return True
elif char == ord("{"):
@@ -116,7 +114,7 @@ def next_value(self, endswith=None):

if not in_string:
# end character or object/list end
if char == endswith or char in (ord("]"), ord("}")):
if char == endswith or char in {ord("]"), ord("}")}:
self.last_char = char
if len(buf) == 0:
return None
@@ -130,15 +128,12 @@ def next_value(self, endswith=None):
# start a string
if char == ord('"'):
in_string = True
else:
# skipping any closing or opening character if in a string
# also skipping escaped characters (like quotes in string)
if ignore_next:
ignore_next = False
elif char == ord("\\"):
ignore_next = True
elif char == ord('"'):
in_string = False
elif ignore_next:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FoamyGuy can we put these commend back in, just above this elif?

            # skipping any closing or opening character if in a string
            # also skipping escaped characters (like quotes in string)
            elif ignore_next:
                ignore_next = False
            elif char == ord("\\"):
                ignore_next = True
            elif char == ord('"'):
                in_string = False

ignore_next = False
elif char == ord("\\"):
ignore_next = True
elif char == ord('"'):
in_string = False

buf.append(char)

3 changes: 3 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -4,5 +4,8 @@
.. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py)
.. use this format as the module name: "adafruit_foo.foo"
API Reference
#############

.. automodule:: adafruit_json_stream
:members:
8 changes: 2 additions & 6 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# -*- coding: utf-8 -*-

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import datetime
import os
import sys
import datetime

sys.path.insert(0, os.path.abspath(".."))

@@ -53,9 +51,7 @@
creation_year = "2023"
current_year = str(datetime.datetime.now().year)
year_duration = (
current_year
if current_year == creation_year
else creation_year + " - " + current_year
current_year if current_year == creation_year else creation_year + " - " + current_year
)
copyright = year_duration + " Scott Shawcroft"
author = "Scott Shawcroft"
2 changes: 1 addition & 1 deletion examples/json_stream_local_file.py
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ def iter_content(self, chunk_size):
yield self.file.read(chunk_size)


f = open(sys.argv[1], "rb") # pylint: disable=consider-using-with
f = open(sys.argv[1], "rb")
obj = json_stream.load(FakeResponse(f).iter_content(32))

currently = obj["currently"]
2 changes: 1 addition & 1 deletion examples/json_stream_local_file_advanced.py
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ def iter_content(self, chunk_size):
yield self.file.read(chunk_size)


f = open(sys.argv[1], "rb") # pylint: disable=consider-using-with
f = open(sys.argv[1], "rb")
obj = json_stream.load(FakeResponse(f).iter_content(32))


2 changes: 2 additions & 0 deletions examples/json_stream_simpletest.py
Original file line number Diff line number Diff line change
@@ -5,9 +5,11 @@

import ssl
import time

import adafruit_requests
import socketpool
import wifi

import adafruit_json_stream as json_stream

pool = socketpool.SocketPool(wifi.radio)
108 changes: 108 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT

target-version = "py38"
line-length = 100

[lint]
preview = true
select = ["I", "PL", "UP"]

extend-select = [
"D419", # empty-docstring
"E501", # line-too-long
"W291", # trailing-whitespace
"PLC0414", # useless-import-alias
"PLC2401", # non-ascii-name
"PLC2801", # unnecessary-dunder-call
"PLC3002", # unnecessary-direct-lambda-call
"E999", # syntax-error
"PLE0101", # return-in-init
"F706", # return-outside-function
"F704", # yield-outside-function
"PLE0116", # continue-in-finally
"PLE0117", # nonlocal-without-binding
"PLE0241", # duplicate-bases
"PLE0302", # unexpected-special-method-signature
"PLE0604", # invalid-all-object
"PLE0605", # invalid-all-format
"PLE0643", # potential-index-error
"PLE0704", # misplaced-bare-raise
"PLE1141", # dict-iter-missing-items
"PLE1142", # await-outside-async
"PLE1205", # logging-too-many-args
"PLE1206", # logging-too-few-args
"PLE1307", # bad-string-format-type
"PLE1310", # bad-str-strip-call
"PLE1507", # invalid-envvar-value
"PLE2502", # bidirectional-unicode
"PLE2510", # invalid-character-backspace
"PLE2512", # invalid-character-sub
"PLE2513", # invalid-character-esc
"PLE2514", # invalid-character-nul
"PLE2515", # invalid-character-zero-width-space
"PLR0124", # comparison-with-itself
"PLR0202", # no-classmethod-decorator
"PLR0203", # no-staticmethod-decorator
"UP004", # useless-object-inheritance
"PLR0206", # property-with-parameters
"PLR0904", # too-many-public-methods
"PLR0911", # too-many-return-statements
"PLR0912", # too-many-branches
"PLR0913", # too-many-arguments
"PLR0914", # too-many-locals
"PLR0915", # too-many-statements
"PLR0916", # too-many-boolean-expressions
"PLR1702", # too-many-nested-blocks
"PLR1704", # redefined-argument-from-local
"PLR1711", # useless-return
"C416", # unnecessary-comprehension
"PLR1733", # unnecessary-dict-index-lookup
"PLR1736", # unnecessary-list-index-lookup

# ruff reports this rule is unstable
#"PLR6301", # no-self-use

"PLW0108", # unnecessary-lambda
"PLW0120", # useless-else-on-loop
"PLW0127", # self-assigning-variable
"PLW0129", # assert-on-string-literal
"B033", # duplicate-value
"PLW0131", # named-expr-without-context
"PLW0245", # super-without-brackets
"PLW0406", # import-self
"PLW0602", # global-variable-not-assigned
"PLW0603", # global-statement
"PLW0604", # global-at-module-level

# fails on the try: import typing used by libraries
#"F401", # unused-import

"F841", # unused-variable
"E722", # bare-except
"PLW0711", # binary-op-exception
"PLW1501", # bad-open-mode
"PLW1508", # invalid-envvar-default
"PLW1509", # subprocess-popen-preexec-fn
"PLW2101", # useless-with-lock
"PLW3301", # nested-min-max
]

ignore = [
"PLR2004", # magic-value-comparison
"UP030", # format literals
"PLW1514", # unspecified-encoding
"PLR0913", # too-many-arguments
"PLR0915", # too-many-statements
"PLR0917", # too-many-positional-arguments
"PLR0904", # too-many-public-methods
"PLR0912", # too-many-branches
"PLR0916", # too-many-boolean-expressions
"PLR6301", # could-be-static no-self-use
"PLC0415", # import outside toplevel
"PLC2701", # private import
]

[format]
line-ending = "lf"
17 changes: 5 additions & 12 deletions tests/test_json_stream.py
Original file line number Diff line number Diff line change
@@ -4,12 +4,10 @@

import json
import math
import pytest
import adafruit_json_stream

import pytest

# pylint: disable=invalid-name,pointless-statement,redefined-outer-name

import adafruit_json_stream

# ---------------
# Helpers
@@ -286,9 +284,7 @@ def test_dict_with_list_of_single_entries(dict_with_list_with_single_entries):

assert json.loads(dict_with_list_with_single_entries)

stream = adafruit_json_stream.load(
BytesChunkIO(dict_with_list_with_single_entries.encode())
)
stream = adafruit_json_stream.load(BytesChunkIO(dict_with_list_with_single_entries.encode()))
counter = 0
for obj in stream["list_1"]:
counter += 1
@@ -538,9 +534,7 @@ def test_complex_dict_buffer_sizes(chunk_size, complex_dict, expected_chunks):


# complex_dict is 1518 bytes
@pytest.mark.parametrize(
("chunk_size", "expected_chunks"), ((5, 61), (10, 31), (50, 7), (100, 4))
)
@pytest.mark.parametrize(("chunk_size", "expected_chunks"), ((5, 61), (10, 31), (50, 7), (100, 4)))
def test_complex_dict_not_looking_at_all_data_buffer_sizes(
chunk_size, complex_dict, expected_chunks
):
@@ -616,7 +610,6 @@ def test_as_object(complex_dict):


def test_as_object_stream(dict_with_all_types):

assert json.loads(dict_with_all_types)

stream = adafruit_json_stream.load(BytesChunkIO(dict_with_all_types.encode()))
@@ -746,7 +739,7 @@ def test_iterating_complex_dict(complex_dict):
stream = adafruit_json_stream.load(BytesChunkIO(complex_dict.encode()))

thing_num = 0
for (index, item) in enumerate(stream.items()):
for index, item in enumerate(stream.items()):
key, a_list = item
assert key == f"list_{index+1}"
for thing in a_list: