From d02aa0ebed8a6c0a0a2baee4fb5bdc853c90c461 Mon Sep 17 00:00:00 2001 From: Ethan Paul Date: Thu, 28 Sep 2023 13:52:10 -0400 Subject: [PATCH 1/4] Add support for passing pathlib.Path objects to DockerfileParser(path=) Add new attribute 'dockerfile' to the DockerfileParser class which exposes the path to the dockerfile as a PathLib object Add new property 'dockerfile_path' to the DockerfileParser class which exposes the 'dockerfile' attribute as a string for backwards compatibility Signed-off-by: Ethan Paul --- dockerfile_parse/parser.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/dockerfile_parse/parser.py b/dockerfile_parse/parser.py index 1fe07f0..45a8342 100644 --- a/dockerfile_parse/parser.py +++ b/dockerfile_parse/parser.py @@ -9,8 +9,8 @@ import json import logging -import os import re +from pathlib import Path from contextlib import contextmanager from shlex import quote @@ -100,6 +100,7 @@ def __init__(self, path=None, """ self.fileobj = fileobj + self.dockerfile = None if self.fileobj is not None: if path is not None: @@ -107,11 +108,11 @@ def __init__(self, path=None, else: self.fileobj.seek(0) else: - path = path or '.' - if path.endswith(DOCKERFILE_FILENAME): - self.dockerfile_path = path + path = Path(path) or Path.cwd() + if path.name.endswith(DOCKERFILE_FILENAME): + self.dockerfile = path else: - self.dockerfile_path = os.path.join(path, DOCKERFILE_FILENAME) + self.dockerfile = path / DOCKERFILE_FILENAME self.cache_content = cache_content self.cached_content = '' # unicode string @@ -149,9 +150,20 @@ def _open_dockerfile(self, mode): yield self.fileobj self.fileobj.seek(0) else: - with open(self.dockerfile_path, mode) as dockerfile: + with self.dockerfile.open(mode) as dockerfile: yield dockerfile + @property + def dockerfile_path(self): + """ + :return: Path to the Dockerfile as a string, or None if using fileobj + """ + return str(self.dockerfile) if self.dockerfile else None + + @dockerfile_path.setter + def dockerfile_path(self, value): + self.dockerfile = Path(value) if value else None + @property def lines(self): """ From 2a0910b2c5b585a8dc7b29bb4286c4ed24325a03 Mon Sep 17 00:00:00 2001 From: Ethan Paul Date: Thu, 28 Sep 2023 14:02:52 -0400 Subject: [PATCH 2/4] Add support for specifying alternative dockerfile names to the parser Signed-off-by: Ethan Paul --- dockerfile_parse/parser.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dockerfile_parse/parser.py b/dockerfile_parse/parser.py index 45a8342..e66de97 100644 --- a/dockerfile_parse/parser.py +++ b/dockerfile_parse/parser.py @@ -85,7 +85,8 @@ def __init__(self, path=None, env_replace=True, parent_env=None, fileobj=None, - build_args=None): + build_args=None, + dockerfile_filename=DOCKERFILE_FILENAME): """ Initialize source of Dockerfile :param path: path to (directory with) Dockerfile; if not provided, @@ -97,6 +98,8 @@ def __init__(self, path=None, :param fileobj: seekable file-like object containing Dockerfile content as bytes (will be truncated on write) :param build_args: python dict of build args used when building image + :param dockerfile_filename: name of the dockerfile to discover or create + in the path (default: Dockerfile) """ self.fileobj = fileobj @@ -109,10 +112,10 @@ def __init__(self, path=None, self.fileobj.seek(0) else: path = Path(path) or Path.cwd() - if path.name.endswith(DOCKERFILE_FILENAME): + if path.name.endswith(dockerfile_filename): self.dockerfile = path else: - self.dockerfile = path / DOCKERFILE_FILENAME + self.dockerfile = path / dockerfile_filename self.cache_content = cache_content self.cached_content = '' # unicode string From 0fc3fc3b6db0e82e671d75d71210894e726b6dd9 Mon Sep 17 00:00:00 2001 From: Ethan Paul Date: Thu, 28 Sep 2023 14:13:15 -0400 Subject: [PATCH 3/4] Add tests for loading from alternative dockerfile names Signed-off-by: Ethan Paul --- tests/test_parser.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_parser.py b/tests/test_parser.py index cc9b010..a66cf50 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -1509,3 +1509,15 @@ def test_escape_directive_ignore_after_comment(self, dfparser): 'value': 'touch foo; touch bar' } ] + + def test_alt_dockerfile_names(self, tmpdir): + tmpdir = Path(tmpdir) + content = "FROM fedora:38" + out = DockerfileParser(path=tmpdir, dockerfile_filename="Containerfile") + out.content = content + + assert out.dockerfile == tmpdir / "Containerfile" + assert out.dockerfile.is_file() + + validate = DockerfileParser(path=tmpdir, dockerfile_filename="Containerfile") + assert validate.baseimage == out.baseimage From c6585448589d690d019776d0754688a738919edc Mon Sep 17 00:00:00 2001 From: Ethan Paul Date: Thu, 28 Sep 2023 14:26:56 -0400 Subject: [PATCH 4/4] Add tests for dockerfile paths to ensure backwards compatibility Signed-off-by: Ethan Paul --- tests/test_parser.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_parser.py b/tests/test_parser.py index a66cf50..2fd8915 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -14,6 +14,7 @@ import pytest import re import sys +from pathlib import Path from textwrap import dedent from dockerfile_parse import DockerfileParser @@ -1521,3 +1522,18 @@ def test_alt_dockerfile_names(self, tmpdir): validate = DockerfileParser(path=tmpdir, dockerfile_filename="Containerfile") assert validate.baseimage == out.baseimage + + def test_dockerfile_path_compatibility(self, tmpdir): + tmpdir = Path(tmpdir) + parser = DockerfileParser(path=tmpdir) + assert str(parser.dockerfile) == parser.dockerfile_path + assert parser.dockerfile == tmpdir / "Dockerfile" + + with (tmpdir / "nothing").open("w+") as testfile: + nullparser = DockerfileParser(fileobj=testfile) + assert nullparser.dockerfile is None + assert nullparser.dockerfile_path is None + + newfile = tmpdir / "nowhere" + parser.dockerfile_path = str(newfile) + assert parser.dockerfile == newfile