Skip to content
Merged
Show file tree
Hide file tree
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
22 changes: 0 additions & 22 deletions .pylintrc

This file was deleted.

1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,5 @@
"editor.tabSize": 2
},
"python.envFile": "${workspaceFolder}/.vscode/env",
"python.linting.pylintEnabled": true,
"python.testing.pytestEnabled": true
}
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ adheres to [Semantic Versioning](https://semver.org/).
- Update GitHub actions dependencies
- Add tests for PyPy 3.10 and 3.11
- Improve tox & CI pipelines
- Use ruff as formatter
- Use ruff as linter and formatter

## [0.5.0] - 2023-02-27

Expand Down
1 change: 0 additions & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
build==1.3.0

# lint
pylint==2.16.2
ruff==0.13.1

# typing
Expand Down
37 changes: 37 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,40 @@
[tool.ruff]
src = ["src"]
target-version = "py39"

[tool.ruff.lint]
select = ["ALL"]
ignore = [
"C901",
"COM812",
"D",
"E501",
"EM",
"ERA001",
"FA100",
"PLR0912",
"PLR0913",
"TRY003",
"TRY301",
]

[tool.ruff.lint.per-file-ignores]
"tests/**" = [
"B018",
"FBT",
"INP001",
"PLR0915",
"PLR2004",
"S101",
"SLF001",
"TC001",
]

[tool.ruff.lint.isort]
force-sort-within-sections = true
known-first-party = ["xz"]

[tool.ruff.lint.flake8-pytest-style]
fixture-parentheses = false
mark-parentheses = false
parametrize-names-type = "list"
10 changes: 5 additions & 5 deletions src/xz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@
from xz.open import xz_open
from xz.strategy import KeepBlockReadStrategy, RollingBlockReadStrategy

# pylint: disable=redefined-builtin
open = xz_open
# pylint: enable=redefined-builtin
open = xz_open # noqa: A001


__all__ = (
"__version__",
__all__: tuple[str, ...] = (
"KeepBlockReadStrategy",
"RollingBlockReadStrategy",
"XZError",
"XZFile",
"__version__",
"open",
)
__all__ += (
# re-export from lzma for easy access
"CHECK_CRC32",
"CHECK_CRC64",
Expand Down
7 changes: 3 additions & 4 deletions src/xz/block.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from io import DEFAULT_BUFFER_SIZE, SEEK_SET
from lzma import FORMAT_XZ, LZMACompressor, LZMADecompressor, LZMAError
from typing import Optional, Tuple, Union
from typing import Optional, Union

from xz.common import (
XZError,
Expand Down Expand Up @@ -45,7 +45,6 @@ def decompress(self, pos: int, size: int) -> bytes:

skip_before = pos - self.pos

# pylint: disable=using-constant-test
if self.decompressor.eof:
raise XZError("block: decompressor eof")

Expand Down Expand Up @@ -95,7 +94,7 @@ def _write(self, data: bytes) -> None:
def compress(self, data: bytes) -> None:
self._write(self.compressor.compress(data))

def finish(self) -> Tuple[int, int]:
def finish(self) -> tuple[int, int]:
data = self.compressor.flush()

# footer
Expand Down Expand Up @@ -124,7 +123,7 @@ def __init__(
preset: _LZMAPresetType = None,
filters: _LZMAFiltersType = None,
block_read_strategy: Optional[_BlockReadStrategyType] = None,
):
) -> None:
super().__init__(uncompressed_size)
self.fileobj = fileobj
self.check = check
Expand Down
18 changes: 10 additions & 8 deletions src/xz/common.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# ruff: noqa: PLR2004

from binascii import crc32 as crc32int
import lzma
from struct import pack, unpack
from typing import List, Tuple, cast
from typing import cast

HEADER_MAGIC = b"\xfd7zXZ\x00"
FOOTER_MAGIC = b"YZ"
Expand All @@ -20,7 +22,7 @@ def encode_mbi(value: int) -> bytes:
return data


def decode_mbi(data: bytes) -> Tuple[int, int]:
def decode_mbi(data: bytes) -> tuple[int, int]:
value = 0
for size, byte in enumerate(data):
value |= (byte & 0x7F) << (size * 7)
Expand Down Expand Up @@ -52,7 +54,7 @@ def create_xz_header(check: int) -> bytes:
return HEADER_MAGIC + flags + crc32(flags)


def create_xz_index_footer(check: int, records: List[Tuple[int, int]]) -> bytes:
def create_xz_index_footer(check: int, records: list[tuple[int, int]]) -> bytes:
if not 0 <= check <= 0xF:
raise XZError("footer check")
# index
Expand All @@ -79,15 +81,15 @@ def parse_xz_header(header: bytes) -> int:
if crc32(header[6:8]) != header[8:12]:
raise XZError("header crc32")
flag_first_byte, check = cast(
Tuple[int, int],
"tuple[int, int]",
unpack("<BB", header[6:8]),
)
if flag_first_byte or not 0 <= check <= 0xF:
raise XZError("header flags")
return check


def parse_xz_index(index: bytes) -> List[Tuple[int, int]]:
def parse_xz_index(index: bytes) -> list[tuple[int, int]]:
if len(index) < 8 or len(index) % 4:
raise XZError("index length")
index = memoryview(index)
Expand Down Expand Up @@ -119,15 +121,15 @@ def parse_xz_index(index: bytes) -> List[Tuple[int, int]]:
return records


def parse_xz_footer(footer: bytes) -> Tuple[int, int]:
def parse_xz_footer(footer: bytes) -> tuple[int, int]:
if len(footer) != 12:
raise XZError("footer length")
if footer[10:12] != FOOTER_MAGIC:
raise XZError("footer magic")
if crc32(footer[4:10]) != footer[:4]:
raise XZError("footer crc32")
backward_size, flag_first_byte, check = cast(
Tuple[int, int, int],
"tuple[int, int, int]",
unpack("<IBB", footer[4:10]),
)
backward_size = (backward_size + 1) * 4
Expand All @@ -136,5 +138,5 @@ def parse_xz_footer(footer: bytes) -> Tuple[int, int]:
return (check, backward_size)


# find default value for check implicitely used by lzma
# find default value for check implicitly used by lzma
DEFAULT_CHECK = parse_xz_header(lzma.compress(b"")[:12])
10 changes: 5 additions & 5 deletions src/xz/file.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from io import SEEK_CUR, SEEK_END
import os
import sys
from typing import BinaryIO, List, Optional, cast
from typing import BinaryIO, Optional, cast
import warnings

from xz.common import DEFAULT_CHECK, XZError
Expand Down Expand Up @@ -83,8 +83,7 @@ def __init__(

# get fileobj
if isinstance(filename, (str, bytes, os.PathLike)):
# pylint: disable=consider-using-with, unspecified-encoding
self.fileobj = cast(BinaryIO, open(filename, self._mode + "b"))
self.fileobj = cast("BinaryIO", open(filename, self._mode + "b")) # noqa: PTH123, SIM115
self._close_fileobj = True
elif hasattr(filename, "read"): # weak check but better than nothing
self.fileobj = filename
Expand Down Expand Up @@ -141,6 +140,7 @@ def close(self) -> None:
"Empty XZFile: nothing was written, "
"so output is empty (and not a valid xz file).",
RuntimeWarning,
stacklevel=2,
)
finally:
if self._close_fileobj:
Expand All @@ -151,11 +151,11 @@ def close(self) -> None:
pass

@property
def stream_boundaries(self) -> List[int]:
def stream_boundaries(self) -> list[int]:
return list(self._fileobjs)

@property
def block_boundaries(self) -> List[int]:
def block_boundaries(self) -> list[int]:
return [
stream_pos + block_boundary
for stream_pos, stream in self._fileobjs.items()
Expand Down
18 changes: 8 additions & 10 deletions src/xz/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,14 @@ def __len__(self) -> int:
return self._length

def _check_not_closed(self) -> None:
# https://github.com/PyCQA/pylint/issues/3484
# pylint: disable=using-constant-test
if self.closed:
raise ValueError("I/O operation on closed file")

def fileno(self) -> int:
try:
return cast(BinaryIO, self.fileobj).fileno() # type: ignore[attr-defined]
return cast("BinaryIO", self.fileobj).fileno() # type: ignore[attr-defined]
except AttributeError:
raise UnsupportedOperation("fileno") # pylint: disable=raise-missing-from
raise UnsupportedOperation("fileno") from None

def seekable(self) -> bool:
"""Return a bool indicating whether object supports random access."""
Expand Down Expand Up @@ -188,7 +186,7 @@ def close(self) -> None:

# the methods below are expected to be implemented by subclasses

def _read(self, size: int) -> bytes: # pragma: no cover
def _read(self, size: int) -> bytes: # pragma: no cover # noqa: ARG002
"""Read and return up to size bytes, where size is an int.

The size will not exceed the number of bytes between self._pos and
Expand All @@ -205,7 +203,7 @@ def _write_before(self) -> None:
def _write_after(self) -> None:
"""This method is called after the last write operation (usually on file close)."""

def _write(self, data: bytes) -> int: # pragma: no cover
def _write(self, data: bytes) -> int: # pragma: no cover # noqa: ARG002
"""Writes as many bytes from data as possible, and return the number
of bytes written.

Expand All @@ -217,7 +215,7 @@ def _write(self, data: bytes) -> int: # pragma: no cover
"""
raise UnsupportedOperation("write")

def _truncate(self, size: int) -> None: # pragma: no cover
def _truncate(self, size: int) -> None: # pragma: no cover # noqa: ARG002
"""Truncate the file to the given size.
This resizing can extend or reduce the current file size.

Expand Down Expand Up @@ -286,7 +284,7 @@ def _write_after(self) -> None:
if self._fileobjs:
last_fileobj = self._fileobjs.last_item
if last_fileobj:
last_fileobj._write_end() # pylint: disable=protected-access
last_fileobj._write_end() # noqa: SLF001
else:
del self._fileobjs[self._fileobjs.last_key]

Expand All @@ -301,7 +299,7 @@ def _write(self, data: bytes) -> int:
fileobj = self._get_fileobj()

# newly created fileobj should be writable
# otherwire this will raise UnsupportedOperation
# otherwise this will raise UnsupportedOperation
return fileobj.write(data)

def _truncate(self, size: int) -> None:
Expand Down Expand Up @@ -329,7 +327,7 @@ def _change_fileobj(self) -> None:
last_fileobj = self._fileobjs.last_item
if last_fileobj:
if last_fileobj.writable():
last_fileobj._write_end() # pylint: disable=protected-access
last_fileobj._write_end() # noqa: SLF001
else:
del self._fileobjs[self._fileobjs.last_key]

Expand Down
8 changes: 4 additions & 4 deletions src/xz/open.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from functools import wraps
from io import TextIOWrapper
from typing import BinaryIO, List, Optional, Union, cast, overload
from typing import BinaryIO, Optional, Union, cast, overload

from xz.file import XZFile
from xz.typing import (
Expand Down Expand Up @@ -37,7 +37,7 @@ def __init__(
block_read_strategy=block_read_strategy,
)
super().__init__(
cast(BinaryIO, self.xz_file),
cast("BinaryIO", self.xz_file),
encoding,
errors,
newline,
Expand All @@ -46,8 +46,8 @@ def __init__(
check = AttrProxy[int]("xz_file")
preset = AttrProxy[_LZMAPresetType]("xz_file")
filters = AttrProxy[_LZMAFiltersType]("xz_file")
stream_boundaries = AttrProxy[List[int]]("xz_file")
block_boundaries = AttrProxy[List[int]]("xz_file")
stream_boundaries = AttrProxy[list[int]]("xz_file")
block_boundaries = AttrProxy[list[int]]("xz_file")
block_read_strategy = AttrProxy[_BlockReadStrategyType]("xz_file")

@property
Expand Down
4 changes: 2 additions & 2 deletions src/xz/strategy.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import time
from typing import TYPE_CHECKING, Dict
from typing import TYPE_CHECKING

if TYPE_CHECKING: # pragma: no cover
# avoid circular dependency
Expand All @@ -19,7 +19,7 @@ def on_read(self, block: "XZBlock") -> None:

class RollingBlockReadStrategy:
def __init__(self, max_block_read_nb: int = 8) -> None:
self.block_reads: Dict["XZBlock", float] = {}
self.block_reads: dict[XZBlock, float] = {}
self.max_block_read_nb = max_block_read_nb

def _freshly_used(self, block: "XZBlock") -> None:
Expand Down
4 changes: 2 additions & 2 deletions src/xz/stream.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from io import SEEK_CUR
from typing import BinaryIO, List, Optional
from typing import BinaryIO, Optional

from xz.block import XZBlock
from xz.common import (
Expand Down Expand Up @@ -36,7 +36,7 @@ def check(self) -> int:
return self._check

@property
def block_boundaries(self) -> List[int]:
def block_boundaries(self) -> list[int]:
return list(self._fileobjs)

@property
Expand Down
Loading