Skip to content
Snippets Groups Projects
Commit ae2cef217ff9 authored by Vincent Hatakeyama's avatar Vincent Hatakeyama
Browse files

:sparkles: handy prettier entrypoint

parent ef1ff60532b7
No related branches found
No related tags found
1 merge request!91✨ handy prettier entrypoint
......@@ -13,6 +13,8 @@
Add populate options to docker_dev_start.
Add docker_prettier.
15.0.0
------
......
......@@ -30,6 +30,13 @@
This is part of the docker section.
docker_prettier
---------------
Run dockerized prettier on provided directory. prettier must be present in the project image.
This is part of the docker section.
conf2reST.py
------------
......
"""Class that encapslulate the docker client"""
import atexit
import logging
import os
import re
import tarfile
......@@ -1,9 +2,9 @@
import atexit
import logging
import os
import re
import tarfile
from typing import Any, Dict, List, Optional, Tuple
from typing import Any, Dict, List, Mapping, Optional, Pattern, Tuple
import docker
import dockerpty
......@@ -34,12 +35,11 @@
if volumes:
_logger.debug("Volume %s already exists", volume_name)
return volumes[0]
else:
_logger.debug("Creating volume %s", volume_name)
labels = dict(odoo_scripts="")
if extra_labels:
labels.update(extra_labels)
return cls.client.volumes.create(name=volume_name, labels=labels)
_logger.debug("Creating volume %s", volume_name)
labels = dict(odoo_scripts="")
if extra_labels:
labels.update(extra_labels)
return cls.client.volumes.create(name=volume_name, labels=labels)
@staticmethod
def put_file(src, container, dst):
......@@ -43,7 +43,8 @@
@staticmethod
def put_file(src, container, dst):
# copied from https://stackoverflow.com/questions/46390309/how-to-copy-a-file-from-host-to-container-using-docker-py-docker-sdk # noqa: E501
"""put a file into a container"""
# copied from https://stackoverflow.com/questions/46390309/how-to-copy-a-file-from-host-to-container-using-docker-py-docker-sdk # noqa: E501 # pylint: disable=line-too-long
os.chdir(os.path.dirname(src))
srcname = os.path.basename(src)
# TODO put that in a temporary directory
......@@ -82,6 +83,14 @@
print(run_result.output.decode())
return result
@staticmethod
def _replace_then_print(replaces: List[Tuple[Pattern[str], str]], log_line: str):
# apply all the replacement of the path inside the image to the real path
for pattern, value in replaces:
log_line = pattern.sub(value, log_line)
# print to play nicely with pycharm that will linkify the result
print(log_line)
@classmethod
def run(
cls,
......@@ -89,6 +98,6 @@
tag: str,
run_kwargs: Dict[str, Any],
pull: bool = True,
target_source_dict: Optional[Dict[str, str]] = None,
target_source_dict: Optional[Mapping[str, str]] = None,
):
"""Run a container with the provided args"""
......@@ -93,6 +102,6 @@
):
"""Run a container with the provided args"""
replaces = (
replaces: List[Tuple[Pattern[str], str]] = (
[(re.compile(key), value) for key, value in target_source_dict.items()]
if target_source_dict
else []
......@@ -139,8 +148,7 @@
# split create and start so in case of SIGTERM, container has fewer chances
# of being None
kwargs = run_kwargs.copy()
kwargs["detach"] = True
kwargs = dict(run_kwargs, detach=True)
_logger.debug("Create container with image %s", image)
container = cls.client.containers.create(image, **kwargs)
_logger.debug("Created container %s", container.name)
......@@ -149,13 +157,25 @@
atexit.unregister(stop_remove)
atexit.register(remove)
for log in container.logs(stream=True, follow=True):
log = log.decode().rstrip()
# apply all the replacement of the path inside the image to the real path
for pattern, value in replaces:
log = pattern.sub(value, log)
# print to play nicely with pycharm that will linkify the result
print(log)
if kwargs.get("tty", False):
line = b""
for log in container.logs(stream=True, follow=True):
# if there is a tty, send byte by byte, so add them together before
# printing
# works correctly because prettier sends \r\n on each line
if log == b"\r":
cls._replace_then_print(replaces, line.decode())
line = b""
elif log == b"\n":
pass
else:
line += log
if line:
cls._replace_then_print(replaces, line.decode())
else:
for log in container.logs(stream=True, follow=True):
log = log.decode().rstrip()
cls._replace_then_print(replaces, log)
_logger.debug("Waiting for container %s", container.name)
result = container.wait()
......
......@@ -7,7 +7,7 @@
import os
import sys
from .config import ODOO_15, Config
from .config import ODOO_13, ODOO_15, Config
from .docker_client import DockerClient
from .parsing import apply, basic_parser
......@@ -109,7 +109,7 @@
tag = "15.0"
# append the directory, needed with isort≥5.0.0
command.append(".")
elif odoo_type == "odoo13":
elif odoo_type == ODOO_13:
tag = "13.0"
else:
repository = "xcgd/isort"
......
#!/usr/bin/env python3
# vim: set shiftwidth=4 softtabstop=4:
"""Run isort in a docker
"""Run prettier in a docker
"""
......@@ -4,6 +4,5 @@
"""
import argparse
import logging
import os
import sys
......@@ -6,8 +5,9 @@
import logging
import os
import sys
from .config import ODOO_15, Config
from .config import Config
from .docker_build import add_build_options, build_local_image, get_build_options
from .docker_client import DockerClient
from .parsing import apply, basic_parser
......@@ -11,8 +11,8 @@
from .docker_client import DockerClient
from .parsing import apply, basic_parser
__version__ = "2.1.0"
__date__ = "2020-09-10"
__updated__ = "2022-01-27"
__version__ = "1.0.0"
__date__ = "2022-02-17"
__updated__ = "2022-02-17"
_logger = logging.getLogger(__name__)
......@@ -17,12 +17,7 @@
_logger = logging.getLogger(__name__)
_ISORT_DEST = "isort"
"""Name of destination variable used for isort in parsing"""
CHECK_MODE = "check"
"""Run isort to check"""
DIFF_MODE = "diff"
"""Run isort to show differences"""
_PRETTIER_DEST = "prettier"
"""Name of destination variable used for prettier in parsing"""
def __parser():
......@@ -33,5 +28,5 @@
program_build_date,
)
program_shortdesc = __doc__.split(".", maxsplit=1)[0]
program_license = """%s
program_license = f"""{program_shortdesc}
......@@ -37,6 +32,6 @@
Created by Vincent Hatakeyama on %s.
Copyright 2020, 2022 XCG Consulting. All rights reserved.
Created by Vincent Hatakeyama on {__date__}.
Copyright 2022 XCG Consulting. All rights reserved.
Licensed under the MIT License
......@@ -44,8 +39,5 @@
or conditions of any kind, either express or implied.
USAGE
""" % (
program_shortdesc,
str(__date__),
)
"""
parser = basic_parser(program_license, program_version_message)
......@@ -51,4 +43,2 @@
parser = basic_parser(program_license, program_version_message)
return parser
......@@ -54,12 +44,6 @@
def parser_add_isort_group(parser: argparse.ArgumentParser):
"""Add isort option (--isort/--no-isort) to the given parser.
Defaults to not using isort."""
isort_group = parser.add_mutually_exclusive_group()
isort_group.add_argument(
"--isort-check",
help="Run isort (check only)",
action="store_const",
dest=_ISORT_DEST,
const=CHECK_MODE,
parser.add_argument(
help="Run pylint on given directory (relative path, for example "
"github.com/OCA/server-auth)",
dest=_PRETTIER_DEST,
)
......@@ -65,16 +49,7 @@
)
isort_group.add_argument(
"--isort-diff",
help="Run isort (check only)",
action="store_const",
dest=_ISORT_DEST,
const=DIFF_MODE,
)
isort_group.add_argument(
"--no-isort",
help="Do not run isort [default]",
action="store_const",
dest=_ISORT_DEST,
const=None,
parser.add_argument(
"--write",
help="Write changes",
action="store_true",
)
......@@ -79,13 +54,8 @@
)
def apply_isort(namespace: argparse.Namespace, odoo_type: str):
"""Run isort if the option was set."""
if _ISORT_DEST in namespace and getattr(namespace, _ISORT_DEST):
return isort(getattr(namespace, _ISORT_DEST), odoo_type)
return 0
return parser
def main(argv=None):
"""Copy modules for a build, callable version that parses arguments"""
parser = __parser()
......@@ -87,7 +57,8 @@
def main(argv=None):
"""Copy modules for a build, callable version that parses arguments"""
parser = __parser()
add_build_options(parser)
nmspc = parser.parse_args(argv)
apply(nmspc)
......@@ -92,7 +63,7 @@
nmspc = parser.parse_args(argv)
apply(nmspc)
c = Config()
odoo_type = c.odoo_type
return isort(DIFF_MODE, odoo_type)
return prettier(
getattr(nmspc, _PRETTIER_DEST), nmspc.write, get_build_options(nmspc)
)
......@@ -97,9 +68,8 @@
def isort(mode: str, odoo_type: str, pull: bool = True):
"""Run isort"""
if mode == CHECK_MODE:
command = ["--check"]
if mode == DIFF_MODE:
command = ["--check", "--diff"]
def prettier(directory: str, write: bool, build_options, pull: bool = True):
"""Run prettier"""
config = Config()
build_local_image(build_options)
......@@ -105,13 +75,18 @@
# determine image to use based on odoo version
repository = "quay.orus.io/odoo/odoo"
if odoo_type == ODOO_15:
tag = "15.0"
# append the directory, needed with isort≥5.0.0
command.append(".")
elif odoo_type == "odoo13":
tag = "13.0"
else:
repository = "xcgd/isort"
tag = "odoo"
pwd = os.environ["PWD"]
path = os.path.abspath(os.path.join(pwd, directory))
volumes = {
pwd: {
"bind": pwd,
"mode": "rw" if write and os.path.samefile(pwd, path) else "ro",
}
}
# also bind any symbolic link, but only for the given directory or its parent.
# all symbolic link could be scanned for but that might take too much time
for potential_link in (path, os.path.dirname(path)):
if os.path.islink(potential_link):
volumes[potential_link] = {
"bind": os.path.realpath(potential_link),
"mode": "rw" if write else "ro",
}
......@@ -117,4 +92,7 @@
_logger.info("Running isort")
pwd = os.environ["PWD"]
command = ["."]
if write:
command.append("--write")
_logger.info("Running prettier in %s", path)
return DockerClient.run(
......@@ -120,4 +98,4 @@
return DockerClient.run(
repository,
tag,
config.local_image,
config.local_tag,
{
......@@ -123,4 +101,4 @@
{
"entrypoint": "isort",
"user": "root",
"entrypoint": "prettier",
"user": os.getuid(),
"command": command,
......@@ -126,10 +104,6 @@
"command": command,
"volumes": {
pwd: {
"bind": "/mnt",
"mode": "ro" if mode in (CHECK_MODE, DIFF_MODE) else "rw",
}
},
"working_dir": "/mnt",
"volumes": volumes,
"working_dir": path,
"tty": True,
},
pull,
......@@ -134,6 +108,5 @@
},
pull,
{"/mnt": pwd},
)
......
......@@ -43,6 +43,7 @@
"docker_flake8=odoo_scripts.docker_flake8:main [docker]",
"docker_isort=odoo_scripts.docker_isort:main [docker]",
"docker_pg=odoo_scripts.docker_postgresql:main [docker]",
"docker_prettier=odoo_scripts.docker_prettier:main [docker]",
"docker_pylint=odoo_scripts.docker_pylint:main [docker]",
"conf2reST=odoo_scripts.conf2reST:main [conf2reST]",
"list_modules=odoo_scripts.list_modules:main",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment