Skip to content

Commit

Permalink
x
Browse files Browse the repository at this point in the history
  • Loading branch information
anishathalye committed Dec 27, 2024
1 parent 3e5293f commit b3b1e02
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 112 deletions.
30 changes: 17 additions & 13 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,37 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "pypy-3.9"]
python: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy-3.9"]
name: "Test: Python ${{ matrix.python }}"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- run: |
python -m pip install --upgrade pip
pip install pytest
- run: pip install .
- run: pytest -v
- uses: pypa/hatch@install
- run: hatch test -v --cover --include python=$(echo ${{ matrix.python }} | tr -d '-')
- run: hatch run coverage:xml
- uses: codecov/codecov-action@v5
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
typecheck:
name: Type check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: |
python -m pip install --upgrade pip
pip install pytest mypy
- run: mypy --strict src test
python-version: "3.13"
- uses: pypa/hatch@install
- run: hatch run types:check
fmt:
name: Format
name: Format and lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: psf/black@stable
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- uses: pypa/hatch@install
- run: hatch fmt --check
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*.egg-info
*.pyc
build/
dist/
.coverage
coverage.xml
4 changes: 4 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
coverage:
status:
project: off
patch: off
70 changes: 59 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,59 @@
[tool.black]
line-length = 100
exclude = '''
/(
\.git
| \.github
| .*\.egg-info
| build
| dist
)/
'''
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "bin2coe"
authors = [
{ name = "Anish Athalye", email = "[email protected]" },
]
description = "A tool to convert binary files to COE files"
readme = "README.md"
requires-python = ">=3.6"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Topic :: Utilities",
]
keywords = ["xilinx", "coe", "bram"]
dynamic = ["version"]

[project.scripts]
bin2coe = "bin2coe.cli:main"

[project.urls]
homepage = "https://github.com/anishathalye/bin2coe"
repository = "https://github.com/anishathalye/bin2coe.git"
issues = "https://github.com/anishathalye/bin2coe/issues"

[tool.hatch.version]
path = "src/bin2coe/__init__.py"

[[tool.hatch.envs.hatch-test.matrix]]
python = ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.9"]

[tool.hatch.envs.types]
extra-dependencies = [
"pytest",
"mypy>=1.0.0",
]

[tool.hatch.envs.types.scripts]
check = "mypy --strict --install-types --non-interactive {args:src tests}"

[tool.hatch.envs.coverage]
detached = true
dependencies = [
"coverage",
]

[tool.hatch.envs.coverage.scripts]
html = "coverage html"
xml = "coverage xml"

[tool.ruff.lint]
ignore = [
"FA100",
]
52 changes: 0 additions & 52 deletions setup.py

This file was deleted.

45 changes: 19 additions & 26 deletions src/bin2coe/cli.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from .convert import convert
from argparse import ArgumentParser
import sys
from argparse import ArgumentParser
from typing import NoReturn


from typing import NoReturn, BinaryIO
from bin2coe.convert import convert


def main() -> None:
Expand All @@ -19,15 +18,15 @@ def main() -> None:
options = parser.parse_args()

# check radix
if not (2 <= options.radix <= 36):
if not (2 <= options.radix <= 36): # noqa: PLR2004
error("unsupported radix, must be between 2 and 36")
if options.mem and not options.radix in [2, 16]:
if options.mem and options.radix not in [2, 16]:
error("mem requires radix 2 or 16")

# check width
if not 8 <= options.width:
if not options.width >= 8: # noqa: PLR2004
error("width must be >= 8")
if not options.width & (options.width - 1) == 0:
if options.width & options.width - 1 != 0:
error("width must be a power of 2")

# if fill is specified, then depth must be specified too; otherwise, depth
Expand All @@ -41,7 +40,7 @@ def main() -> None:
try:
fill = int(options.fill, options.radix)
except ValueError:
error("invalid fill ({}) for radix ({})".format(options.fill, options.radix))
error(f"invalid fill ({options.fill}) for radix ({options.radix})")

with open(options.input, "rb") as f:
data = f.read()
Expand All @@ -54,26 +53,20 @@ def main() -> None:
if bits % options.width != 0:
extra = options.width - bits % options.width
if extra % 8 != 0:
error("cannot infer depth, {} total bits, width {}".format(bits, options.width))
error(f"cannot infer depth, {bits} total bits, width {options.width}")
extra_words = extra // 8
data = data + bytes(extra_words)
bits = 8 * len(data)
depth = bits // options.width
elif fill is None:
if bits != options.width * depth:
error(f"memory size / file size mismatch: {depth} x {options.width} bit != {bits}")
else:
# validate depth
if fill is None:
if bits != options.width * depth:
error(
"memory size / file size mismatch: {} x {} bit != {}".format(
depth, options.width, bits
)
)
else:
# make sure it fills an integer number of words
if bits % options.width != 0:
error("data must fill an integer number of words")
if bits > options.width * depth:
error("memory size too small: {} x {} bit < {}".format(depth, options.width, bits))
# make sure it fills an integer number of words
if bits % options.width != 0:
error("data must fill an integer number of words")
if bits > options.width * depth:
error(f"memory size too small: {depth} x {options.width} bit < {bits}")

with open(options.output, "wb") as f:
convert(
Expand All @@ -89,5 +82,5 @@ def main() -> None:


def error(msg: str) -> NoReturn:
print("error: {}".format(msg), file=sys.stderr)
exit(1)
print(f"error: {msg}", file=sys.stderr) # noqa: T201
sys.exit(1)
16 changes: 10 additions & 6 deletions src/bin2coe/convert.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Iterable, TypeVar, BinaryIO, List, Iterator, Optional
from typing import BinaryIO, Iterable, Iterator, List, Optional, TypeVar

T = TypeVar("T")

Expand All @@ -14,7 +14,7 @@ def chunks(it: Iterable[T], n: int) -> Iterator[List[T]]:
yield res


def word_to_int(word: List[int], little_endian: bool) -> int:
def word_to_int(word: List[int], *, little_endian: bool) -> int:
if not little_endian:
word = list(reversed(word))
value = 0
Expand All @@ -26,7 +26,8 @@ def word_to_int(word: List[int], little_endian: bool) -> int:
def format_int(num: int, base: int, pad_width: int = 0) -> str:
chars = "0123456789abcdefghijklmnopqrstuvwxyz"
if num < 0:
raise ValueError("negative numbers not supported")
msg = "negative numbers not supported"
raise ValueError(msg)
res = []
res.append(chars[num % base])
while num >= base:
Expand All @@ -44,23 +45,26 @@ def convert(
depth: int,
fill: Optional[int],
radix: int,
*,
little_endian: bool = True,
mem: bool = False,
) -> None:
pad_width = len(format_int(2**width - 1, radix))
if not mem:
output.write("memory_initialization_radix = {};\n".format(radix).encode("utf8"))
output.write(f"memory_initialization_radix = {radix};\n".encode())
output.write(b"memory_initialization_vector =\n")
rows = 0
for word in chunks(data, width // 8):
if rows > 0:
if not mem:
output.write(b",")
output.write(b"\n")
output.write(format_int(word_to_int(word, little_endian), radix, pad_width).encode("utf8"))
output.write(format_int(word_to_int(word, little_endian=little_endian), radix, pad_width).encode("utf8"))
rows += 1
if rows < depth:
assert fill is not None
if fill is None:
msg = "fill must not be 'None' if memory is not filled by values"
raise ValueError(msg)
while rows < depth:
if not mem:
output.write(b",")
Expand Down
Empty file added tests/__init__.py
Empty file.
3 changes: 1 addition & 2 deletions test/bin2coe/test_convert.py → tests/test_convert.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from bin2coe.convert import *
import io

import pytest
from bin2coe.convert import chunks, convert


def test_chunks() -> None:
Expand Down

0 comments on commit b3b1e02

Please sign in to comment.