Skip to content

Commit e1909ff

Browse files
authored
fix: layer extractor should match python metadata files on windows [c… (#770)
fix: layer extractor should match python metadata files on windows [cn-874]
1 parent c06267f commit e1909ff

File tree

2 files changed

+85
-6
lines changed

2 files changed

+85
-6
lines changed

lib/inputs/python/static.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import { basename } from "path";
1+
import { basename, sep } from "path";
22

33
import { ExtractAction } from "../../extractor/types";
44
import { streamToString } from "../../stream-utils";
55

66
const poetryManifestFiles = ["pyproject.toml", "poetry.lock"];
77
const pipManifestFiles = ["requirements.txt"];
8+
// Match both forward slashes (POSIX/macOS/Linux) and backslashes (Windows)
89
const pythonMetadataFilesRegex =
9-
/\/lib\/python.*?\/(?:dist|site)-packages\/.*?\.dist-info\/METADATA/;
10+
/[\/\\]lib[\/\\]python.*?[\/\\](?:dist|site)-packages[\/\\].*?\.dist-info[\/\\]METADATA/;
1011
const deletedPoetryAppFiles = poetryManifestFiles.map((file) => ".wh." + file);
1112
const deletedPipAppFiles = pipManifestFiles.map((file) => ".wh." + file);
1213
const pythonApplicationFileSuffixes = [".py", "requirements.txt", "Pipfile"];
@@ -42,10 +43,9 @@ export const getPipAppFileContentAction: ExtractAction = {
4243

4344
function pythonApplicationFilePathMatches(filePath: string): boolean {
4445
return (
45-
!filePath.includes("/site-packages/") &&
46-
!filePath.includes("/dist-packages/") &&
47-
// "/usr/" should not include 1st party code
48-
!filePath.startsWith("/usr/") &&
46+
!filePath.includes(`${sep}site-packages${sep}`) &&
47+
!filePath.includes(`${sep}dist-packages${sep}`) &&
48+
!filePath.startsWith(`${sep}usr${sep}`) &&
4949
pythonApplicationFileSuffixes.some((suffix) => filePath.endsWith(suffix))
5050
);
5151
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { sep } from "path";
2+
import {
3+
getPipAppFileContentAction,
4+
getPythonAppFileContentAction,
5+
} from "../../../../lib/inputs/python/static";
6+
7+
describe("Python pip file path matching", () => {
8+
const { filePathMatches } = getPipAppFileContentAction;
9+
10+
describe("requirements.txt matching", () => {
11+
it("should match requirements.txt", () => {
12+
expect(filePathMatches("/app/requirements.txt")).toBe(true);
13+
});
14+
});
15+
16+
describe("METADATA file matching", () => {
17+
it("should match METADATA files with forward slashes", () => {
18+
expect(
19+
filePathMatches(
20+
"/usr/lib/python3.9/dist-packages/Django-4.1.2.dist-info/METADATA",
21+
),
22+
).toBe(true);
23+
expect(
24+
filePathMatches(
25+
"/usr/lib/python3.9/site-packages/requests-2.28.0.dist-info/METADATA",
26+
),
27+
).toBe(true);
28+
});
29+
30+
it("should match METADATA files with backslashes (Windows)", () => {
31+
expect(
32+
filePathMatches(
33+
"\\usr\\lib\\python3.9\\dist-packages\\Django-4.1.2.dist-info\\METADATA",
34+
),
35+
).toBe(true);
36+
expect(
37+
filePathMatches(
38+
"\\usr\\lib\\python3.9\\site-packages\\requests-2.28.0.dist-info\\METADATA",
39+
),
40+
).toBe(true);
41+
});
42+
43+
it("should not match non-METADATA files in dist-info", () => {
44+
expect(
45+
filePathMatches(
46+
"/usr/lib/python3.9/dist-packages/Django-4.1.2.dist-info/RECORD",
47+
),
48+
).toBe(false);
49+
});
50+
51+
it("should not match METADATA files outside of site/dist-packages", () => {
52+
expect(filePathMatches("/app/METADATA")).toBe(false);
53+
expect(filePathMatches("/usr/lib/METADATA")).toBe(false);
54+
});
55+
});
56+
});
57+
58+
describe("Python application file path matching", () => {
59+
const { filePathMatches } = getPythonAppFileContentAction;
60+
61+
it("should match .py, Pipfile and requirements.txt files", () => {
62+
expect(filePathMatches(`${sep}app${sep}main.py`)).toBe(true);
63+
expect(filePathMatches(`${sep}app${sep}Pipfile`)).toBe(true);
64+
expect(filePathMatches(`${sep}app${sep}requirements.txt`)).toBe(true);
65+
});
66+
67+
it("should exclude files in site-packages and dist-packages", () => {
68+
expect(filePathMatches(`${sep}lib${sep}site-packages${sep}foo.py`)).toBe(
69+
false,
70+
);
71+
expect(filePathMatches(`${sep}lib${sep}dist-packages${sep}bar.py`)).toBe(
72+
false,
73+
);
74+
});
75+
76+
it("should exclude files under /usr/", () => {
77+
expect(filePathMatches(`${sep}usr${sep}lib${sep}script.py`)).toBe(false);
78+
});
79+
});

0 commit comments

Comments
 (0)