diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a1b2f8d78..eb23efe86 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,13 +8,38 @@ on: branches: [main] jobs: - build: + pre-commit: runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 19.x + cache: "npm" + + - name: Install Node dependencies + run: | + npm install + + - name: Run pre-commit + uses: pre-commit/action@v3.0.1 + with: + extra_args: --all-files --verbose --show-diff-on-failure + + build: + runs-on: ${{ matrix.os }} + strategy: matrix: + os: [windows-latest, ubuntu-latest] python-version: ["3.10", "3.12"] node-version: [19.x] + exclude: + - os: windows-latest + python-version: "3.10" steps: - uses: actions/checkout@v4 @@ -42,11 +67,6 @@ jobs: # run: | # npm install - - name: Run pre-commit - uses: pre-commit/action@v3.0.1 - with: - extra_args: --all-files --verbose --show-diff-on-failure - - name: Run Python tests with pytest run: | pytest -vv diff --git a/src/fontra/backends/filenames.py b/src/fontra/backends/filenames.py index e96d7bc39..a52ca3c4b 100644 --- a/src/fontra/backends/filenames.py +++ b/src/fontra/backends/filenames.py @@ -55,6 +55,10 @@ def stringToFileName(string: str) -> str: ) if fileName[0] == ".": fileName = "%2E" + fileName[1:] + elif "." in fileName: + base, rest = fileName.split(".", 1) + if base.lower() in reservedFileNames: + fileName = base + "%2E" + rest if not codeDigits and fileName.lower() in reservedFileNames: codeDigits = [0] if codeDigits: diff --git a/src/fontra/backends/fontra.py b/src/fontra/backends/fontra.py index bf5c0147d..d706c0e71 100644 --- a/src/fontra/backends/fontra.py +++ b/src/fontra/backends/fontra.py @@ -189,7 +189,7 @@ async def putCustomData(self, customData: dict[str, Any]) -> None: self._scheduler.schedule(self._writeFontData) def _readGlyphInfo(self) -> None: - with self.glyphInfoPath.open("r", encoding="utf-8") as file: + with self.glyphInfoPath.open("r", encoding="utf-8", newline="") as file: reader = csv.reader(file, delimiter=";") header = next(reader) assert header[:2] == ["glyph name", "code points"] @@ -202,7 +202,7 @@ def _readGlyphInfo(self) -> None: self.glyphMap[glyphName] = codePoints def _writeGlyphInfo(self) -> None: - with self.glyphInfoPath.open("w", encoding="utf-8") as file: + with self.glyphInfoPath.open("w", encoding="utf-8", newline="") as file: writer = csv.writer(file, delimiter=";") writer.writerow(["glyph name", "code points"]) for glyphName, codePoints in sorted(self.glyphMap.items()): @@ -312,7 +312,7 @@ def serialize(data: list | dict) -> str: def writeKerningFile(path: pathlib.Path, kerning: dict[str, Kerning]) -> None: - with path.open("w", encoding="utf-8") as file: + with path.open("w", encoding="utf-8", newline="") as file: writer = csv.writer(file, delimiter=";") isFirst = True @@ -346,7 +346,7 @@ class KerningParseError(Exception): def readKerningFile(path: pathlib.Path) -> dict[str, Kerning]: kerning = {} - with path.open("r", encoding="utf-8") as file: + with path.open("r", encoding="utf-8", newline="") as file: reader = csv.reader(file, delimiter=";") rowIter = iter(enumerate(reader, 1)) diff --git a/test-py/test_backends_designspace.py b/test-py/test_backends_designspace.py index 69b766ba1..9b1b1400f 100644 --- a/test-py/test_backends_designspace.py +++ b/test-py/test_backends_designspace.py @@ -76,7 +76,7 @@ def writableTestFontSingleUFO(tmpdir): def readGLIFData(glyphName, ufoLayers): glyphSets = {layer.fontraLayerName: layer.glyphSet for layer in ufoLayers} return { - layerName: glyphSet.getGLIF(glyphName).decode("utf-8") + layerName: glyphSet.getGLIF(glyphName).decode("utf-8").replace("\r\n", "\n") for layerName, glyphSet in glyphSets.items() if glyphName in glyphSet } diff --git a/test-py/test_backends_filenames.py b/test-py/test_backends_filenames.py index 99d768824..f4361efe9 100644 --- a/test-py/test_backends_filenames.py +++ b/test-py/test_backends_filenames.py @@ -18,7 +18,12 @@ ("CON", "CON^7"), ("con", "con^0"), ("aux", "aux^0"), - ("con.alt", "con.alt"), + ("con.alt", "con%2Ealt"), + ("conalt", "conalt"), + ("con.bbb.alt", "con%2Ebbb.alt"), + ("nul.alt", "nul%2Ealt"), + ("aux.alt", "aux%2Ealt"), + ("com1.alt", "com1%2Ealt"), ("a:", "a%3A"), ("A:", "A%3A^1"), ("a/", "a%2F"), diff --git a/test-py/test_unicode_usedby_table.py b/test-py/test_unicode_usedby_table.py index 708cbc502..932c3e598 100644 --- a/test-py/test_unicode_usedby_table.py +++ b/test-py/test_unicode_usedby_table.py @@ -7,6 +7,6 @@ def test_unicode_usedBy_needs_update(): try: - subprocess.run([scriptPath, "--check"], check=True) + subprocess.run(f"python {scriptPath} --check", check=True, shell=True) except subprocess.CalledProcessError: assert 0, f"unicode-utils.js is stale, please run ./scripts/{scriptPath.name}"