Skip to content

Commit

Permalink
Merge c9d458b into a02edc4
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergiy committed Apr 15, 2020
2 parents a02edc4 + c9d458b commit a658452
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 40 deletions.
72 changes: 72 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
[MASTER]

# Use multiple processes to speed up Pylint.
jobs=1

# Pickle collected data for later comparisons.
persistent=no

# Activate the evaluation score.
score=no

[MESSAGES CONTROL]

# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=

# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
enable=all,
python3
disable=I,
R, # refactoring checks
arguments-differ, # nice to have
bad-continuation, # pep8
bad-whitespace, # pep8, nice to have
import-outside-toplevel,
invalid-name,
missing-class-docstring,
missing-function-docstring,
no-self-use,
protected-access,
redefined-outer-name,
too-many-lines,
wrong-import-order,
wrong-import-position


[REPORTS]

# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
msg-template='{path}:{line}: [{msg_id}({symbol}), {obj}] {msg})'

# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio).You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=colorized

[TYPECHECK]

# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=requests.structures.LookupDict

# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=requests.packages,
responses,
docker,
http.client,
six.moves
10 changes: 10 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ env:
OS_VERSION=31
PYTHON_VERSION=3
ENGINE=docker
- ACTION=pylint
OS=fedora
OS_VERSION=29
PYTHON_VERSION=2
ENGINE=docker
- ACTION=pylint
OS=fedora
OS_VERSION=31
PYTHON_VERSION=3
ENGINE=docker
- OS=centos
OS_VERSION=7
PYTHON_VERSION=2
Expand Down
1 change: 1 addition & 0 deletions dockerfile_parse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# This file is generated from template: rel-eng/version_init.template
#

from __future__ import absolute_import
from .parser import DockerfileParser

__version__ = "0.0.16"
2 changes: 1 addition & 1 deletion dockerfile_parse/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
This software may be modified and distributed under the terms
of the BSD license. See the LICENSE file for details.
"""
from __future__ import unicode_literals
from __future__ import unicode_literals, absolute_import

from sys import version_info

Expand Down
22 changes: 13 additions & 9 deletions dockerfile_parse/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
of the BSD license. See the LICENSE file for details.
"""

from __future__ import print_function, unicode_literals
from __future__ import print_function, unicode_literals, absolute_import

import json
import logging
Expand Down Expand Up @@ -228,13 +228,13 @@ def _create_instruction_dict(instruction=None, value=None):
'instruction': instruction,
'startline': lineno,
'endline': lineno,
'content': line,
'content': line, # pylint: disable=undefined-loop-variable
'value': value
}

def _clean_comment_line(line):
line = re.sub('^\s*#\s*', '', line)
line = re.sub('\n', '', line)
line = re.sub(r'^\s*#\s*', '', line)
line = re.sub(r'\n', '', line)
return line


Expand All @@ -243,7 +243,7 @@ def _clean_comment_line(line):
insnre = re.compile(r'^\s*(\S+)\s+(.*)$') # matched group is insn
contre = re.compile(r'^.*\\\s*$') # line continues?
commentre = re.compile(r'^\s*#') # line is a comment?

in_continuation = False
current_instruction = None

Expand All @@ -265,15 +265,17 @@ def _clean_comment_line(line):
if not m:
continue
current_instruction = _create_instruction_dict(
instruction=m.groups()[0].upper(),
instruction=m.groups()[0].upper(),
value=_rstrip_backslash(m.groups()[1])
)
else:
current_instruction['content'] += line
current_instruction['endline'] = lineno
if current_instruction['value']:
# pylint: disable=unsupported-assignment-operation
current_instruction['value'] += _rstrip_backslash(line)
else:
# pylint: disable=unsupported-assignment-operation
current_instruction['value'] = _rstrip_backslash(line.lstrip())

in_continuation = contre.match(line)
Expand Down Expand Up @@ -420,7 +422,9 @@ def _instruction_getter(self, name, env_replace):
:return: Labels instance or Envs instance
"""
if name != 'LABEL' and name != 'ENV':
raise ValueError("Unsupported instruction '%s'", name)
msg = "Unsupported instruction \'%s\'", name
raise ValueError(msg)

instructions = {}
envs = {}

Expand Down Expand Up @@ -628,7 +632,7 @@ def add_lines(self, *lines, **kwargs):
all_stages = kwargs.pop('all_stages', False)
at_start = kwargs.pop('at_start', False)
skip_scratch = kwargs.pop('skip_scratch', False)
assert not kwargs, "Unknown keyword argument(s): {0}".format(kwargs.keys())
assert not kwargs, "Unknown keyword argument(s): {0}".format(list(kwargs.keys()))

froms = [
instr for instr in self.structure
Expand Down Expand Up @@ -667,7 +671,7 @@ def add_lines_at(self, anchor, *lines, **kwargs):
replace = kwargs.pop('replace', False)
after = kwargs.pop('after', False)
assert not (after and replace)
assert not kwargs, "Unknown keyword argument(s): {0}".format(kwargs.keys())
assert not kwargs, "Unknown keyword argument(s): {0}".format(list(kwargs.keys()))

# find the line number for the insertion
df_lines = self.lines
Expand Down
9 changes: 5 additions & 4 deletions dockerfile_parse/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
of the BSD license. See the LICENSE file for details.
"""

from __future__ import print_function, unicode_literals
from __future__ import print_function, unicode_literals, absolute_import

import shlex
from io import StringIO

from .constants import PY2
Expand All @@ -25,8 +24,10 @@ def b2u(string):

def u2b(string):
""" unicode to bytes"""
if ((PY2 and isinstance(string, unicode)) or
((not PY2) and isinstance(string, str))):
if not PY2:
unicode = str

if isinstance(string, unicode):
return string.encode('utf-8')
return string

Expand Down
9 changes: 8 additions & 1 deletion test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ if [[ $($ENGINE ps -qa -f name="$CONTAINER_NAME" | wc -l) -eq 0 ]]; then
elif [[ $($ENGINE ps -q -f name="$CONTAINER_NAME" | wc -l) -eq 0 ]]; then
echo found stopped existing container, restarting. volume mounts cannot be updated.
$ENGINE container start "$CONTAINER_NAME"
fi
fi

# Install dependencies
$RUN $PKG install -y $PKG_EXTRA
Expand Down Expand Up @@ -84,6 +84,13 @@ case ${ACTION} in
$RUN $PIP install bandit
TEST_CMD="bandit-baseline -r dockerfile_parse -ll -ii"
;;
"pylint")
# This can run only at fedora because pylint is not packaged in centos
# use distro pylint to not get too new pylint version
$RUN $PKG install -y "${PYTHON}-pylint"
PACKAGES='dockerfile_parse tests'
TEST_CMD="${PYTHON} -m pylint ${PACKAGES}"
;;
*)
echo "Unknown action: ${ACTION}"
exit 2
Expand Down
7 changes: 5 additions & 2 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
of the BSD license. See the LICENSE file for details.
"""

from __future__ import unicode_literals
from __future__ import unicode_literals, absolute_import

import pytest
import six

from dockerfile_parse import DockerfileParser


@pytest.fixture(params=[(use_fileobj, cache_content) for use_fileobj in [True, False] for cache_content in [True, False]])
@pytest.fixture(
params=[(use_fileobj, cache_content)
for use_fileobj in [True, False]
for cache_content in [True, False]])
def dfparser(tmpdir, request):
"""
Expand Down
49 changes: 26 additions & 23 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
of the BSD license. See the LICENSE file for details.
"""

from __future__ import unicode_literals
from __future__ import unicode_literals, absolute_import

import inspect
import json
Expand All @@ -25,8 +25,8 @@

NON_ASCII = "žluťoučký"
# flake8 does not understand fixtures:
dfparser = dfparser
instruction = instruction
dfparser = dfparser # pylint: disable=self-assigning-variable
instruction = instruction # pylint: disable=self-assigning-variable


class TestDockerfileParser(object):
Expand Down Expand Up @@ -96,14 +96,14 @@ def test_dockerfile_structure(self, dfparser):
"# comment \\\n", # extra ws
"# with \\ \n", # extra ws with a space
"# backslashes \\\\ \n", # two backslashes
"#no space after hash\n",
"# comment # with hash inside\n",
"#no space after hash\n",
"# comment # with hash inside\n",
"RUN command1\n",
"RUN command2 && \\\n",
" command3\n",
"RUN command4 && \\\n",
"# interrupt RUN\n", # comment interrupting multi-line RUN
" command5\n",
" command5\n",
]

assert dfparser.structure == [
Expand Down Expand Up @@ -309,8 +309,9 @@ def test_get_parent_env_from_scratch(self, tmpdir):
('"name9"="asd \\ \\n qwe"', {'name9': 'asd \\ \\n qwe'}),
('"name10"="{0}"'.format(NON_ASCII), {'name10': NON_ASCII}),
('"name1 1"=1', {'name1 1': '1'}),
('"name12"=12 \ \n "name13"=13', {'name12': '12', 'name13': '13'}),
('name14=1\ 4', {'name14': '1 4'}),
('"name12"=12 \ \n "name13"=13',
{'name12': '12', 'name13': '13'}), # pylint: disable=anomalous-backslash-in-string
('name14=1\ 4', {'name14': '1 4'}), # pylint: disable=anomalous-backslash-in-string
('name15="with = in value"', {'name15': 'with = in value'}),
('name16=❤', {'name16': '❤'}),
('name❤=❤', {'name❤': '❤'}),
Expand All @@ -321,7 +322,7 @@ def test_get_parent_env_from_scratch(self, tmpdir):
('name104 "1" 04', {'name104': '1 04'}),
('name105 1 \'05\'', {'name105': '1 05'}),
('name106 1 \'0\' 6', {'name106': '1 0 6'}),
('name107 1 0\ 7', {'name107': '1 0 7'}),
('name107 1 0\ 7', {'name107': '1 0 7'}), # pylint: disable=anomalous-backslash-in-string
('name108 "with = in value"', {'name108': 'with = in value'}),
('name109 "\\"quoted\\""', {'name109': '"quoted"'}),
('name110 ❤', {'name110': '❤'}),
Expand Down Expand Up @@ -630,7 +631,8 @@ def test_setter(self, dfparser, instruction, existing, new, expected):
# Simple case, '=' but no quotes
('Release=1', 'Release', '6', 'Release=6'),
# '=' and quotes, with space in the value
('"Name"=\'alpha alpha\' Version=1', 'Name', 'beta delta', '"Name"=\'beta delta\' Version=1'),
('"Name"=\'alpha alpha\' Version=1',
'Name', 'beta delta', '"Name"=\'beta delta\' Version=1'),
('Name=foo', 'Name', 'new value', "Name='new value'"),
# ' ' and quotes
('"Name" alpha alpha', 'Name', 'beta delta', "\"Name\" 'beta delta'"),
Expand Down Expand Up @@ -733,7 +735,7 @@ def test_env_invalid(self, dfparser, label):
"LABEL TEST={0}\n".format(label)]
try:
dfparser.labels['TEST']
except:
except KeyError:
pass

def test_env_multistage(self, dfparser):
Expand Down Expand Up @@ -896,16 +898,17 @@ def test_context_structure(self, dfparser, instruction):
"version": "1.0.❤"
}

assert c[6].get_values(context_type=instruction) == {"multi.label❤1": "value❤1",
"multi.label❤2": "value❤2",
"other": "othervalue3",
"2multi.label1": "othervalue1",
"2multi.label2": "othervalue2",
"com.example.vendor": "ACME Incorporated",
"com.example.label-with-value": "foo",
"version": "1.0.❤",
"description": "This text illustrates that label-values can span multiple lines."
}
assert c[6].get_values(context_type=instruction) == {
"multi.label❤1": "value❤1",
"multi.label❤2": "value❤2",
"other": "othervalue3",
"2multi.label1": "othervalue1",
"2multi.label2": "othervalue2",
"com.example.vendor": "ACME Incorporated",
"com.example.label-with-value": "foo",
"version": "1.0.❤",
"description": "This text illustrates that label-values can span multiple lines."
}

def test_context_structure_mixed(self, dfparser, instruction):
dfparser.content = dedent("""\
Expand Down Expand Up @@ -987,7 +990,7 @@ def test_label_invalid(self, dfparser, label_value, bad_keyval, envs, action):
]
with pytest.raises(ValueError) as exc_info:
if action == 'get':
dfparser.labels
dfparser.labels # pylint: disable=pointless-statement
elif action == 'set':
dfparser.labels = {}
if six.PY2:
Expand Down Expand Up @@ -1147,7 +1150,7 @@ def test_add_lines_at_edge(self, dfparser):
LABEL a=b c=d e=❤""") # no newline
dfparser.add_lines_at(2, "# something new ❤", after=True)
assert "d#" not in dfparser.content
assert 4 == len(dfparser.lines)
assert len(dfparser.lines) == 4
assert "something new ❤" in dfparser.lines[3]

def test_add_lines_after_continuation(self, dfparser):
Expand Down

0 comments on commit a658452

Please sign in to comment.