From 7ae7df87d3396c579c3f4c1d3e692d183690a5d7 Mon Sep 17 00:00:00 2001 From: darknao Date: Mar 01 2021 14:27:20 +0000 Subject: [PATCH 1/4] extended logging configuration Rename logging.yml.example to logging.yml to enable custom logging configuration. In this example, each logger has is own settings, and log in separate files in ./log/ (you have to create this directory manually). --- diff --git a/build.py b/build.py index 2aa471a..a1a73b5 100755 --- a/build.py +++ b/build.py @@ -16,7 +16,9 @@ import tempfile import time import datetime as dt import re +import yaml import logging +import logging.config import threading import concurrent.futures @@ -65,11 +67,19 @@ def main(): ) args = parser.parse_args() - loglevel = logging.INFO - if args.verbose: - loglevel = logging.DEBUG - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=loglevel) + try: + with open("logging.yml", 'r') as f: + config = yaml.safe_load(f.read()) + logging.config.dictConfig(config) + print("logging config loaded") + except Exception: + logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) + log = logging.getLogger("srpmParser") + if args.verbose: + log.setLevel(logging.DEBUG) + for h in log.parent.handlers: + h.setLevel(logging.DEBUG) srpm_regex = None if args.filter: diff --git a/build_language_list.py b/build_language_list.py index d503c58..f2234e0 100755 --- a/build_language_list.py +++ b/build_language_list.py @@ -7,7 +7,9 @@ import json import os import polib import re +import yaml import logging +import logging.config from shutil import rmtree from weblate_language_data import aliases, languages, language_codes, countries @@ -52,11 +54,20 @@ def main(): ) args = parser.parse_args() - loglevel = logging.INFO - if args.verbose: - loglevel = logging.DEBUG - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=loglevel) + + try: + with open("logging.yml", 'r') as f: + config = yaml.safe_load(f.read()) + logging.config.dictConfig(config) + print("logging config loaded") + except Exception: + logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) + log = logging.getLogger("buildLanguageList") + if args.verbose: + log.setLevel(logging.DEBUG) + for h in log.parent.handlers: + h.setLevel(logging.DEBUG) results_folder = "./results/{v}/".format(v=args.results) lang_folder = os.path.join(results_folder, "languages/") diff --git a/build_map.py b/build_map.py index 42997ac..f118d54 100755 --- a/build_map.py +++ b/build_map.py @@ -6,7 +6,9 @@ import pandas import geopandas import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable +import yaml import logging +import logging.config RESULT_FOLDER = "" @@ -45,11 +47,19 @@ def main(): help="Add verbosity") args = parser.parse_args() - loglevel = logging.INFO - if args.verbose: - loglevel = logging.DEBUG - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=loglevel) + try: + with open("logging.yml", 'r') as f: + config = yaml.safe_load(f.read()) + logging.config.dictConfig(config) + print("logging config loaded") + except Exception: + logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) + log = logging.getLogger("buildMap") + if args.verbose: + log.setLevel(logging.DEBUG) + for h in log.parent.handlers: + h.setLevel(logging.DEBUG) RESULT_FOLDER = "./results/{r}/stats/".format(r=args.results) diff --git a/build_stats.py b/build_stats.py index bc4dffe..4f26376 100755 --- a/build_stats.py +++ b/build_stats.py @@ -9,7 +9,9 @@ import shutil import subprocess import polib +import yaml import logging +import logging.config from translate.tools.pocount import calcstats @@ -36,11 +38,19 @@ def main(): args = parser.parse_args() - loglevel = logging.INFO - if args.verbose: - loglevel = logging.DEBUG - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=loglevel) + try: + with open("logging.yml", 'r') as f: + config = yaml.safe_load(f.read()) + logging.config.dictConfig(config) + print("logging config loaded") + except Exception: + logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) + log = logging.getLogger("buildStats") + if args.verbose: + log.setLevel(logging.DEBUG) + for h in log.parent.handlers: + h.setLevel(logging.DEBUG) results_folder = "./results/{v}/".format(v=args.results) packages_folder = "./results/{v}/packages/".format(v=args.results) diff --git a/build_tm.py b/build_tm.py index a427254..4ee22e7 100755 --- a/build_tm.py +++ b/build_tm.py @@ -8,7 +8,9 @@ import os import subprocess import shutil import tempfile +import yaml import logging +import logging.config def main(): @@ -34,11 +36,19 @@ def main(): help="Add verbosity") args = parser.parse_args() - loglevel = logging.INFO - if args.verbose: - loglevel = logging.DEBUG - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=loglevel) + try: + with open("logging.yml", 'r') as f: + config = yaml.safe_load(f.read()) + logging.config.dictConfig(config) + print("logging config loaded") + except Exception: + logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) + log = logging.getLogger("buildTm") + if args.verbose: + log.setLevel(logging.DEBUG) + for h in log.parent.handlers: + h.setLevel(logging.DEBUG) results_folder = "./results/{v}/".format(v=args.results) lang_path = os.path.join(results_folder, "languages/") diff --git a/build_website.py b/build_website.py index 2625102..d84f997 100755 --- a/build_website.py +++ b/build_website.py @@ -10,8 +10,9 @@ import langtable import os import pandas as pd import shutil +import yaml import logging - +import logging.config def main(): """Handle params""" @@ -34,15 +35,19 @@ def main(): ) args = parser.parse_args() - loglevel = logging.INFO - if args.verbose: - loglevel = logging.DEBUG - logging.basicConfig( - format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", - level=loglevel, - force=True, - ) + try: + with open("logging.yml", 'r') as f: + config = yaml.safe_load(f.read()) + logging.config.dictConfig(config) + print("logging config loaded") + except Exception: + logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) + log = logging.getLogger("buildWebsite") + if args.verbose: + log.setLevel(logging.DEBUG) + for h in log.parent.handlers: + h.setLevel(logging.DEBUG) results_folder = "./results/{v}/".format(v=args.results) langs_log = os.path.join(results_folder, "build_language_list.log") diff --git a/logging.yml.example b/logging.yml.example new file mode 100644 index 0000000..ef5d8fb --- /dev/null +++ b/logging.yml.example @@ -0,0 +1,111 @@ +version: 1 +formatters: + simple: + format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' +handlers: + console: + class: logging.StreamHandler + level: INFO + formatter: simple + stream: ext://sys.stdout + + general_log: + class: logging.handlers.TimedRotatingFileHandler + level: DEBUG + formatter: simple + filename: log/general.log + when: D + interval: 1 + backupCount: 3 + encoding: utf8 + + srpm_log: + class: logging.handlers.TimedRotatingFileHandler + level: DEBUG + formatter: simple + filename: log/srpm.log + when: D + interval: 1 + backupCount: 3 + encoding: utf8 + + buildLanguageList_log: + class: logging.handlers.TimedRotatingFileHandler + level: DEBUG + formatter: simple + filename: log/buildLanguageList.log + when: D + interval: 1 + backupCount: 3 + encoding: utf8 + + buildMap_log: + class: logging.handlers.TimedRotatingFileHandler + level: DEBUG + formatter: simple + filename: log/buildMap.log + when: D + interval: 1 + backupCount: 3 + encoding: utf8 + + buildStats_log: + class: logging.handlers.TimedRotatingFileHandler + level: DEBUG + formatter: simple + filename: log/buildStats.log + when: D + interval: 1 + backupCount: 3 + encoding: utf8 + + buildTm_log: + class: logging.handlers.TimedRotatingFileHandler + level: DEBUG + formatter: simple + filename: log/buildTm.log + when: D + interval: 1 + backupCount: 3 + encoding: utf8 + + buildWebsite_log: + class: logging.handlers.TimedRotatingFileHandler + level: DEBUG + formatter: simple + filename: log/buildWebsite.log + when: D + interval: 1 + backupCount: 3 + encoding: utf8 + +loggers: + srpmParser: + level: DEBUG + handlers: [srpm_log] + propagate: yes + buildLanguageList: + level: DEBUG + handlers: [buildLanguageList_log] + propagate: yes + buildMap: + level: DEBUG + handlers: [buildMap_log] + propagate: yes + buildStats: + level: DEBUG + handlers: [buildStats_log] + propagate: yes + buildTm: + level: DEBUG + handlers: [buildTm_log] + propagate: yes + buildWebsite: + level: DEBUG + handlers: [buildWebsite_log] + propagate: yes + +root: + level: DEBUG + handlers: + - console diff --git a/requirements.txt b/requirements.txt index 354fd5d..e5941dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ pandas jinja2 +pyyaml polib weblate-language-data langtable -translate-toolkit \ No newline at end of file +translate-toolkit From 6fca6485b8183b2a6dbfc61ed8f0f604b929c9e9 Mon Sep 17 00:00:00 2001 From: darknao Date: Mar 01 2021 14:27:25 +0000 Subject: [PATCH 2/4] logging: 'release' variable processing in handler.filename --- diff --git a/build.py b/build.py index a1a73b5..e8e0a28 100755 --- a/build.py +++ b/build.py @@ -16,11 +16,10 @@ import tempfile import time import datetime as dt import re -import yaml import logging -import logging.config import threading import concurrent.futures +import utils from shutil import copyfile from translation_finder import discover @@ -67,19 +66,9 @@ def main(): ) args = parser.parse_args() - try: - with open("logging.yml", 'r') as f: - config = yaml.safe_load(f.read()) - logging.config.dictConfig(config) - print("logging config loaded") - except Exception: - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) + utils.set_logging(args.verbose, args.results) log = logging.getLogger("srpmParser") - if args.verbose: - log.setLevel(logging.DEBUG) - for h in log.parent.handlers: - h.setLevel(logging.DEBUG) srpm_regex = None if args.filter: diff --git a/build_language_list.py b/build_language_list.py index f2234e0..458cf8c 100755 --- a/build_language_list.py +++ b/build_language_list.py @@ -7,9 +7,8 @@ import json import os import polib import re -import yaml import logging -import logging.config +import utils from shutil import rmtree from weblate_language_data import aliases, languages, language_codes, countries @@ -55,19 +54,8 @@ def main(): args = parser.parse_args() - try: - with open("logging.yml", 'r') as f: - config = yaml.safe_load(f.read()) - logging.config.dictConfig(config) - print("logging config loaded") - except Exception: - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) - + utils.set_logging(args.verbose, args.results) log = logging.getLogger("buildLanguageList") - if args.verbose: - log.setLevel(logging.DEBUG) - for h in log.parent.handlers: - h.setLevel(logging.DEBUG) results_folder = "./results/{v}/".format(v=args.results) lang_folder = os.path.join(results_folder, "languages/") diff --git a/build_map.py b/build_map.py index f118d54..185c5be 100755 --- a/build_map.py +++ b/build_map.py @@ -6,9 +6,8 @@ import pandas import geopandas import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable -import yaml import logging -import logging.config +import utils RESULT_FOLDER = "" @@ -47,19 +46,8 @@ def main(): help="Add verbosity") args = parser.parse_args() - try: - with open("logging.yml", 'r') as f: - config = yaml.safe_load(f.read()) - logging.config.dictConfig(config) - print("logging config loaded") - except Exception: - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) - + utils.set_logging(args.verbose, args.results) log = logging.getLogger("buildMap") - if args.verbose: - log.setLevel(logging.DEBUG) - for h in log.parent.handlers: - h.setLevel(logging.DEBUG) RESULT_FOLDER = "./results/{r}/stats/".format(r=args.results) diff --git a/build_stats.py b/build_stats.py index 4f26376..a7e9185 100755 --- a/build_stats.py +++ b/build_stats.py @@ -9,9 +9,8 @@ import shutil import subprocess import polib -import yaml import logging -import logging.config +import utils from translate.tools.pocount import calcstats @@ -38,19 +37,8 @@ def main(): args = parser.parse_args() - try: - with open("logging.yml", 'r') as f: - config = yaml.safe_load(f.read()) - logging.config.dictConfig(config) - print("logging config loaded") - except Exception: - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) - + utils.set_logging(args.verbose, args.results) log = logging.getLogger("buildStats") - if args.verbose: - log.setLevel(logging.DEBUG) - for h in log.parent.handlers: - h.setLevel(logging.DEBUG) results_folder = "./results/{v}/".format(v=args.results) packages_folder = "./results/{v}/packages/".format(v=args.results) diff --git a/build_tm.py b/build_tm.py index 4ee22e7..9a04e0c 100755 --- a/build_tm.py +++ b/build_tm.py @@ -8,9 +8,8 @@ import os import subprocess import shutil import tempfile -import yaml import logging -import logging.config +import utils def main(): @@ -36,19 +35,8 @@ def main(): help="Add verbosity") args = parser.parse_args() - try: - with open("logging.yml", 'r') as f: - config = yaml.safe_load(f.read()) - logging.config.dictConfig(config) - print("logging config loaded") - except Exception: - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) - + utils.set_logging(args.verbose, args.results) log = logging.getLogger("buildTm") - if args.verbose: - log.setLevel(logging.DEBUG) - for h in log.parent.handlers: - h.setLevel(logging.DEBUG) results_folder = "./results/{v}/".format(v=args.results) lang_path = os.path.join(results_folder, "languages/") diff --git a/build_website.py b/build_website.py index d84f997..c50d3e5 100755 --- a/build_website.py +++ b/build_website.py @@ -10,9 +10,8 @@ import langtable import os import pandas as pd import shutil -import yaml import logging -import logging.config +import utils def main(): """Handle params""" @@ -35,19 +34,8 @@ def main(): ) args = parser.parse_args() - try: - with open("logging.yml", 'r') as f: - config = yaml.safe_load(f.read()) - logging.config.dictConfig(config) - print("logging config loaded") - except Exception: - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) - + utils.set_logging(args.verbose, args.results) log = logging.getLogger("buildWebsite") - if args.verbose: - log.setLevel(logging.DEBUG) - for h in log.parent.handlers: - h.setLevel(logging.DEBUG) results_folder = "./results/{v}/".format(v=args.results) langs_log = os.path.join(results_folder, "build_language_list.log") diff --git a/logging.yml.example b/logging.yml.example index ef5d8fb..7b0d654 100644 --- a/logging.yml.example +++ b/logging.yml.example @@ -13,7 +13,7 @@ handlers: class: logging.handlers.TimedRotatingFileHandler level: DEBUG formatter: simple - filename: log/general.log + filename: "results/{release}/log/general.log" when: D interval: 1 backupCount: 3 @@ -23,7 +23,7 @@ handlers: class: logging.handlers.TimedRotatingFileHandler level: DEBUG formatter: simple - filename: log/srpm.log + filename: "results/{release}/log/srpm.log" when: D interval: 1 backupCount: 3 @@ -33,7 +33,7 @@ handlers: class: logging.handlers.TimedRotatingFileHandler level: DEBUG formatter: simple - filename: log/buildLanguageList.log + filename: "results/{release}/log/buildLanguageList.log" when: D interval: 1 backupCount: 3 @@ -43,7 +43,7 @@ handlers: class: logging.handlers.TimedRotatingFileHandler level: DEBUG formatter: simple - filename: log/buildMap.log + filename: "results/{release}/log/buildMap.log" when: D interval: 1 backupCount: 3 @@ -53,7 +53,7 @@ handlers: class: logging.handlers.TimedRotatingFileHandler level: DEBUG formatter: simple - filename: log/buildStats.log + filename: "results/{release}/log/buildStats.log" when: D interval: 1 backupCount: 3 @@ -63,7 +63,7 @@ handlers: class: logging.handlers.TimedRotatingFileHandler level: DEBUG formatter: simple - filename: log/buildTm.log + filename: "results/{release}/log/buildTm.log" when: D interval: 1 backupCount: 3 @@ -73,7 +73,7 @@ handlers: class: logging.handlers.TimedRotatingFileHandler level: DEBUG formatter: simple - filename: log/buildWebsite.log + filename: "results/{release}/log/buildWebsite.log" when: D interval: 1 backupCount: 3 diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..089111b --- /dev/null +++ b/utils.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +import logging +import logging.config +import yaml +import os +import sys + +def set_logging(verbose=False, release=None): + try: + with open("logging.yml", 'r') as f: + config = yaml.safe_load(f.read()) + for _,handlers in config['handlers'].items(): + if 'filename' in handlers: + if release: + handlers['filename'] = handlers['filename'].format(release=release) + os.makedirs(os.path.dirname(handlers['filename']), exist_ok=True) + if verbose: + config['handlers']['console']['level'] = DEBUG + logging.config.dictConfig(config) + print("logging config loaded") + except FileNotFoundError: + logging.basicConfig( + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + level=logging.DEBUG if verbose else logging.INFO, + force=True) + except Exception as e: + logging.exception(e) + sys.exit(1) From 6c48a9947f4f9b2273e88da2fa2064a5d8243efc Mon Sep 17 00:00:00 2001 From: darknao Date: Mar 01 2021 14:43:45 +0000 Subject: [PATCH 3/4] Revert "add rubygem-asciidoctor as requirement" This reverts commit 373319399d6f821ca75db131506cc141b99bb1fe. --- diff --git a/docker/Dockerfile.29 b/docker/Dockerfile.29 index ee9594c..785ba0b 100644 --- a/docker/Dockerfile.29 +++ b/docker/Dockerfile.29 @@ -7,7 +7,6 @@ RUN pip3 install --no-cache -r /src/requirements.txt RUN pip3 install --upgrade https://github.com/WeblateOrg/language-data/archive/master.zip RUN pip3 install charamel RUN pip3 install git+https://github.com/WeblateOrg/translation-finder.git -RUN dnf install rubygem-asciidoctor VOLUME /src WORKDIR /src diff --git a/docker/Dockerfile.30 b/docker/Dockerfile.30 index c74ebc7..1540841 100644 --- a/docker/Dockerfile.30 +++ b/docker/Dockerfile.30 @@ -7,7 +7,6 @@ RUN pip3 install --no-cache -r /src/requirements.txt RUN pip3 install --upgrade https://github.com/WeblateOrg/language-data/archive/master.zip RUN pip3 install charamel RUN pip3 install git+https://github.com/WeblateOrg/translation-finder.git -RUN dnf install rubygem-asciidoctor VOLUME /src WORKDIR /src diff --git a/docker/Dockerfile.31 b/docker/Dockerfile.31 index 349e139..f4f8efe 100644 --- a/docker/Dockerfile.31 +++ b/docker/Dockerfile.31 @@ -7,7 +7,6 @@ RUN pip install --no-cache -r /src/requirements.txt RUN pip install --upgrade https://github.com/WeblateOrg/language-data/archive/master.zip RUN pip install charamel RUN pip install git+https://github.com/WeblateOrg/translation-finder.git -RUN dnf install rubygem-asciidoctor VOLUME /src WORKDIR /src diff --git a/docker/Dockerfile.32 b/docker/Dockerfile.32 index 19ea84b..b6f5622 100644 --- a/docker/Dockerfile.32 +++ b/docker/Dockerfile.32 @@ -7,7 +7,6 @@ RUN pip install --no-cache -r /src/requirements.txt RUN pip install --upgrade https://github.com/WeblateOrg/language-data/archive/master.zip RUN pip install charamel RUN pip install git+https://github.com/WeblateOrg/translation-finder.git -RUN dnf install rubygem-asciidoctor VOLUME /src WORKDIR /src diff --git a/docker/Dockerfile.33 b/docker/Dockerfile.33 index c33d9b6..5736959 100644 --- a/docker/Dockerfile.33 +++ b/docker/Dockerfile.33 @@ -7,7 +7,6 @@ RUN pip install --no-cache -r /src/requirements.txt RUN pip install --upgrade https://github.com/WeblateOrg/language-data/archive/master.zip RUN pip install charamel RUN pip install git+https://github.com/WeblateOrg/translation-finder.git -RUN dnf install rubygem-asciidoctor RUN mkdir -p /src/results /srpms; chmod g+rwX /srpms; chmod -R 1777 /tmp WORKDIR /src diff --git a/docker/Dockerfile.34 b/docker/Dockerfile.34 deleted file mode 100644 index f016a19..0000000 --- a/docker/Dockerfile.34 +++ /dev/null @@ -1,19 +0,0 @@ -FROM registry.fedoraproject.org/fedora:34 as builder - -RUN dnf install -y lbzip2 unzip xz cpio dnf-plugins-core rsync python3-pip hugo gettext git -COPY requirements.txt /src/requirements.txt - -RUN pip install --no-cache -r /src/requirements.txt -RUN pip install --upgrade https://github.com/WeblateOrg/language-data/archive/master.zip -RUN pip install charamel -RUN pip install git+https://github.com/WeblateOrg/translation-finder.git -RUN dnf install rubygem-asciidoctor -RUN mkdir -p /src/results /srpms; chmod g+rwX /srpms; chmod -R 1777 /tmp -WORKDIR /src - -COPY *.py *.sh /src/ -COPY website /src/website/ -RUN chmod -R g+rwX /src/website -COPY templates /src/templates/ -VOLUME /src/results -ENV VERS f34 diff --git a/docker/Dockerfile.latest b/docker/Dockerfile.latest new file mode 100644 index 0000000..9f73dec --- /dev/null +++ b/docker/Dockerfile.latest @@ -0,0 +1,18 @@ +FROM registry.fedoraproject.org/fedora:34 as builder + +RUN dnf install -y lbzip2 unzip xz cpio dnf-plugins-core rsync python3-pip hugo gettext git +COPY requirements.txt /src/requirements.txt + +RUN pip install --no-cache -r /src/requirements.txt +RUN pip install --upgrade https://github.com/WeblateOrg/language-data/archive/master.zip +RUN pip install charamel +RUN pip install git+https://github.com/WeblateOrg/translation-finder.git +RUN mkdir -p /src/results /srpms; chmod g+rwX /srpms; chmod -R 1777 /tmp +WORKDIR /src + +COPY *.py *.sh /src/ +COPY website /src/website/ +RUN chmod -R g+rwX /src/website +COPY templates /src/templates/ +VOLUME /src/results +ENV VERS f34 From de682975c5b10ed328c1ef28ffde29cca7e9bb74 Mon Sep 17 00:00:00 2001 From: darknao Date: Mar 01 2021 14:45:10 +0000 Subject: [PATCH 4/4] add rubygem-asciidoctor to dockerfile --- diff --git a/docker/Dockerfile.latest b/docker/Dockerfile.latest index 9f73dec..40b1b5a 100644 --- a/docker/Dockerfile.latest +++ b/docker/Dockerfile.latest @@ -1,6 +1,6 @@ FROM registry.fedoraproject.org/fedora:34 as builder -RUN dnf install -y lbzip2 unzip xz cpio dnf-plugins-core rsync python3-pip hugo gettext git +RUN dnf install -y lbzip2 unzip xz cpio dnf-plugins-core rsync python3-pip hugo gettext git rubygem-asciidoctor COPY requirements.txt /src/requirements.txt RUN pip install --no-cache -r /src/requirements.txt