From 61bebc5f990247ec56cc574bfa1205acabf914cb Mon Sep 17 00:00:00 2001 From: Francois Andrieu Date: Feb 01 2021 20:38:28 +0000 Subject: [PATCH 1/3] use multithreads --- diff --git a/build.py b/build.py index 1f10d01..e1b00c1 100755 --- a/build.py +++ b/build.py @@ -16,6 +16,9 @@ import tempfile import time import datetime as dt import re +import logging +import threading +import concurrent.futures from shutil import copyfile from translation_finder import discover @@ -52,6 +55,7 @@ def main(): ) args = parser.parse_args() + logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG) srpm_regex = None if args.filter: srpm_regex = re.compile("^{}$".format(args.filter)) @@ -70,113 +74,132 @@ def main(): list_file_stats = os.stat(srpm_list_file) last_mod = dt.datetime.fromtimestamp(list_file_stats.st_mtime) if dt.datetime.now() - last_mod < dt.timedelta(hours=24): + logging.debug("loading srpm list") with open(srpm_list_file) as f: url_list = f.readlines() if not url_list: - print("Fetching SRPMs url list") + logging.info("Fetching SRPMs url list") p = subprocess.Popen( "dnf download --source --skip-broken --url '*' | grep src.rpm", stdout=subprocess.PIPE, - shell=True, - ) + shell=True) urls = str(p.stdout.read(), "utf-8") + logging.debug("saving srpm list") with open(srpm_list_file, "w") as f: f.write(urls) url_list = urls.splitlines() # Load processing data, if any try: + logging.debug("loading previous data") with open(data_file) as f: data = json.load(f) + logging.debug("previous data loaded") except BaseException: data = {} count = 0 total_urls = len(url_list) - with tempfile.TemporaryDirectory(prefix="l10n-stats") as tmp: - for line in url_list: - count += 1 - url = urlparse(line.strip()) - if not url.scheme: - continue - srpm_filename = os.path.basename(url.path) - srpm_data = dnf.subject.Subject(srpm_filename) - package = srpm_data.get_nevra_possibilities(forms=1)[0] - - if srpm_regex and not srpm_regex.match(package.name): - continue - - if package.name in data and not args.force: - # Compare version - known_package = dnf.subject.Subject( - data[package.name]["srpm"] - ).get_nevra_possibilities(forms=1)[0] - if ( - rpm.labelCompare( - (package.epoch, package.version, package.release), - ( - known_package.epoch, - known_package.version, - known_package.release, - ), - ) - <= 0 - ): - print( - " {c}/{t} skipping already processed {n}".format( - c=count, t=total_urls, n=package.name - ) - ) - continue - - print( - " {c}/{t} processing {n}".format(c=count, t=total_urls, n=package.name) - ) + lock = threading.Lock() + max_conn = threading.Semaphore(3) + max_ext = threading.Semaphore(3) + with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: + for line in url_list: + count += 1 + url = urlparse(line.strip()) + if not url.scheme: + continue + executor.submit(process_srpm, url, srpms_path, packages_folder, srpm_regex, lock, data, data_file, force=args.force, keep=args.keep, max_conn=max_conn, max_ext=max_ext) + + #thr = threading.Thread(target=process_srpm, args=(package.name,)) + - srpm_path = os.path.join(srpms_path, srpm_filename) - if not os.path.isfile(srpm_path): - if url.scheme == "rsync": - dl = subprocess.run( + +def process_srpm(url, srpms_path, packages_folder, srpm_regex=None, lock=None, data={}, data_file=None, force=False, keep=False, max_conn=None, max_ext=None): + try: + srpm_filename = os.path.basename(url.path) + srpm_data = dnf.subject.Subject(srpm_filename) + package = srpm_data.get_nevra_possibilities(forms=1)[0] + + if srpm_regex and not srpm_regex.match(package.name): + return + + already_processed = False + with lock: + logging.debug("%s: taking lock", package.name) + + if package.name in data and not force: + # Compare version + known_package = dnf.subject.Subject( + data[package.name]["srpm"]).get_nevra_possibilities(forms=1)[0] + if rpm.labelCompare( + (package.epoch, + package.version, + package.release), + (known_package.epoch, + known_package.version, + known_package.release)) <= 0: + already_processed = True + logging.debug("%s: releasing lock", package.name) + + if already_processed: + logging.info("%s: Already processed, skipping", package.name) + return + + logging.info("%s: Processing", package.name) + srpm_path = os.path.join(srpms_path, srpm_filename) + if not os.path.isfile(srpm_path): + with max_conn: + logging.info("%s: Downloading", package.name) + if url.scheme == "rsync": + dl = subprocess.run( ["rsync", url.geturl(), srpms_path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - else: - dl = subprocess.run( + stderr=subprocess.STDOUT) + else: + dl = subprocess.run( ["curl", "-L", "--remote-name", url.geturl()], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - cwd=srpms_path, - ) - - if dl.returncode: - print("error downloading srpm:") - print(dl.stdout) - continue - - extract_srpm(tmp, srpm_path, packages_folder) - (tsearch, tcopy, results) = discover_translations( - tmp, package.name, packages_folder - ) - - if not args.keep: - os.unlink(srpm_path) - - # save processed srpm name & version - data[package.name] = { - "srpm": srpm_filename, - "tsearch": tsearch, - "tcopy": tcopy, - "results": results, - } - - with open(data_file, "w") as f: - json.dump(data, f, indent=2) + cwd=srpms_path) + + if dl.returncode: + logging.error("%s: error downloading srpm:", package.name) + logging.error(dl.stdout) + return + + with tempfile.TemporaryDirectory(prefix="l10n-stats") as tmp: + with max_ext: + logging.info("%s: Extracting", package.name) + extract_srpm(tmp, srpm_path, packages_folder) + logging.info("%s: Discovering", package.name) + (tsearch, tcopy, results) = discover_translations( + tmp, package.name, packages_folder) + + if not keep: + os.unlink(srpm_path) + + with lock: + logging.debug("%s: taking lock", package.name) + # save processed srpm name & version + data[package.name] = { + "srpm": srpm_filename, + "tsearch": tsearch, + "tcopy": tcopy, + "results": results} + + with open(data_file, "w") as f: + json.dump(data, f, indent=2) + logging.debug("%s: releasing lock", package.name) + + logging.info("%s: Completed", package.name) + except Exception as e: + logging.exception(e) def extract_srpm(tmp, name, dest_folder): diff --git a/docker/Dockerfile.33 b/docker/Dockerfile.33 index 1fae1cb..b2c8d10 100644 --- a/docker/Dockerfile.33 +++ b/docker/Dockerfile.33 @@ -9,4 +9,5 @@ RUN pip install charamel RUN pip install git+https://github.com/WeblateOrg/translation-finder.git VOLUME /src +VOLUME /srpms WORKDIR /src From 40987e6c3898b45280068cf938c248f0d7ac089c Mon Sep 17 00:00:00 2001 From: Francois Andrieu Date: Feb 01 2021 20:38:37 +0000 Subject: [PATCH 2/3] add jinja2 requirement --- diff --git a/requirements.txt b/requirements.txt index 6f584b3..354fd5d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ pandas +jinja2 polib weblate-language-data langtable From 0baa533da4eaeaf9f434db92a81055fc422b0655 Mon Sep 17 00:00:00 2001 From: Francois Andrieu Date: Feb 01 2021 20:38:41 +0000 Subject: [PATCH 3/3] Use logging in build scripts added -v flag for additional verbosity --- diff --git a/build.py b/build.py index e1b00c1..72201bd 100755 --- a/build.py +++ b/build.py @@ -53,9 +53,21 @@ def main(): dest="force", help="Ignore past progression state", ) + parser.add_argument( + "-v", + default=False, + action="store_true", + dest="verbose", + help="Add verbosity" + ) args = parser.parse_args() - logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG) + loglevel = logging.INFO + if args.verbose: + loglevel = logging.DEBUG + logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=loglevel) + log = logging.getLogger("srpmParser") + srpm_regex = None if args.filter: srpm_regex = re.compile("^{}$".format(args.filter)) @@ -74,29 +86,29 @@ def main(): list_file_stats = os.stat(srpm_list_file) last_mod = dt.datetime.fromtimestamp(list_file_stats.st_mtime) if dt.datetime.now() - last_mod < dt.timedelta(hours=24): - logging.debug("loading srpm list") + log.debug("loading srpm list") with open(srpm_list_file) as f: url_list = f.readlines() if not url_list: - logging.info("Fetching SRPMs url list") + log.info("Fetching SRPMs url list") p = subprocess.Popen( "dnf download --source --skip-broken --url '*' | grep src.rpm", stdout=subprocess.PIPE, shell=True) urls = str(p.stdout.read(), "utf-8") - logging.debug("saving srpm list") + log.debug("saving srpm list") with open(srpm_list_file, "w") as f: f.write(urls) url_list = urls.splitlines() # Load processing data, if any try: - logging.debug("loading previous data") + log.debug("loading previous data") with open(data_file) as f: data = json.load(f) - logging.debug("previous data loaded") + log.debug("previous data loaded") except BaseException: data = {} @@ -119,6 +131,7 @@ def main(): def process_srpm(url, srpms_path, packages_folder, srpm_regex=None, lock=None, data={}, data_file=None, force=False, keep=False, max_conn=None, max_ext=None): + log = logging.getLogger("srpmParser.process_srpm") try: srpm_filename = os.path.basename(url.path) srpm_data = dnf.subject.Subject(srpm_filename) @@ -129,7 +142,7 @@ def process_srpm(url, srpms_path, packages_folder, srpm_regex=None, lock=None, d already_processed = False with lock: - logging.debug("%s: taking lock", package.name) + log.debug("%s: taking lock", package.name) if package.name in data and not force: # Compare version @@ -143,17 +156,17 @@ def process_srpm(url, srpms_path, packages_folder, srpm_regex=None, lock=None, d known_package.version, known_package.release)) <= 0: already_processed = True - logging.debug("%s: releasing lock", package.name) + log.debug("%s: releasing lock", package.name) if already_processed: - logging.info("%s: Already processed, skipping", package.name) + log.info("%s: Already processed, skipping", package.name) return - logging.info("%s: Processing", package.name) + log.info("%s: Processing", package.name) srpm_path = os.path.join(srpms_path, srpm_filename) if not os.path.isfile(srpm_path): with max_conn: - logging.info("%s: Downloading", package.name) + log.info("%s: Downloading", package.name) if url.scheme == "rsync": dl = subprocess.run( ["rsync", url.geturl(), srpms_path], @@ -169,15 +182,15 @@ def process_srpm(url, srpms_path, packages_folder, srpm_regex=None, lock=None, d cwd=srpms_path) if dl.returncode: - logging.error("%s: error downloading srpm:", package.name) - logging.error(dl.stdout) + log.error("%s: error downloading srpm:", package.name) + log.error(dl.stdout) return with tempfile.TemporaryDirectory(prefix="l10n-stats") as tmp: with max_ext: - logging.info("%s: Extracting", package.name) + log.info("%s: Extracting", package.name) extract_srpm(tmp, srpm_path, packages_folder) - logging.info("%s: Discovering", package.name) + log.info("%s: Discovering", package.name) (tsearch, tcopy, results) = discover_translations( tmp, package.name, packages_folder) @@ -185,7 +198,7 @@ def process_srpm(url, srpms_path, packages_folder, srpm_regex=None, lock=None, d os.unlink(srpm_path) with lock: - logging.debug("%s: taking lock", package.name) + log.debug("%s: taking lock", package.name) # save processed srpm name & version data[package.name] = { "srpm": srpm_filename, @@ -195,15 +208,16 @@ def process_srpm(url, srpms_path, packages_folder, srpm_regex=None, lock=None, d with open(data_file, "w") as f: json.dump(data, f, indent=2) - logging.debug("%s: releasing lock", package.name) + log.debug("%s: releasing lock", package.name) - logging.info("%s: Completed", package.name) + log.info("%s: Completed", package.name) except Exception as e: - logging.exception(e) + log.exception(e) def extract_srpm(tmp, name, dest_folder): """extract srpm page""" + log = logging.getLogger("srpmParser.extract_srpm") srpm_log_file = os.path.join(dest_folder, "..", "extract_srpm.log") srpm_error_file = os.path.join(dest_folder, "..", "extract_srpm_error.log") @@ -217,6 +231,7 @@ def extract_srpm(tmp, name, dest_folder): def discover_translations(tmp, pkg_name, dest_folder): """find po file""" + log = logging.getLogger("srpmParser.discover_translations") translation_files = [] tsearch = 0 @@ -254,6 +269,7 @@ def discover_translations(tmp, pkg_name, dest_folder): def copy_translations(tmp, translation, pkg_name, dest_folder): + log = logging.getLogger("srpmParser.copy_translations") filemask = translation["filemask"] if translation["file_format"] in ["po", "json", "json-nested"]: diff --git a/build_language_list.py b/build_language_list.py index 1b9bb80..be6c896 100755 --- a/build_language_list.py +++ b/build_language_list.py @@ -7,6 +7,7 @@ import json import os import polib import re +import logging from shutil import rmtree from weblate_language_data import aliases, languages, language_codes, countries @@ -41,7 +42,20 @@ def main(): help="Produce an analyze file for all languages", ) + parser.add_argument( + "-v", + default=False, + action="store_true", + dest="verbose", + 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) + log = logging.getLogger("buildLanguageList") results_folder = "./results/{v}/".format(v=args.results) lang_folder = os.path.join(results_folder, "languages/") @@ -49,11 +63,11 @@ def main(): lang_analyze_folder = os.path.join(results_folder, "languages-analyses/") if args.describe: - print("Describing detecting languages") + log.info("Describing detecting languages") describe(lang_folder) elif args.analyzealllangs: - print("Provide more data to analyze errors") + log.info("Provide more data to analyze errors") rmtree(lang_analyze_folder, ignore_errors=True) os.mkdir(lang_analyze_folder) @@ -69,7 +83,7 @@ def main(): f.write(json.dumps(analyze, indent=2)) elif args.analyzelang: - print("Provide more data to analyze errors") + log.info("Provide more data to analyze errors") if not os.path.exists(lang_analyze_folder): os.makedirs(lang_analyze_folder) @@ -80,7 +94,7 @@ def main(): f.write(json.dumps(analyze, indent=2)) elif args.refresh: - print("Refreshing the list of languages") + log.info("Refreshing the list of languages") rmtree(lang_folder, ignore_errors=True) os.mkdir(lang_folder) @@ -93,14 +107,13 @@ def main(): def analyze_lang(lang_folder, analized_lang): """ Analyze one lang """ + log = logging.getLogger("buildLanguageList.analyze_lang") files = [] results = dict() with open(os.path.join(lang_folder, analized_lang + ".json"), "r") as read_file: files = json.load(read_file)["po"] - print( - " Analysing language {l}, with {c} files".format(l=analized_lang, c=len(files)) - ) + log.info(" Analysing language {l}, with {c} files".format(l=analized_lang, c=len(files))) for file in files: metadata = dict() @@ -147,6 +160,7 @@ def analyze_lang(lang_folder, analized_lang): def describe(lang_folder): """ Provide the number of files per language """ + log = logging.getLogger("buildLanguageList.describe") langs = [ f for f in os.listdir(lang_folder) @@ -157,13 +171,14 @@ def describe(lang_folder): with open(os.path.join(lang_folder, lang), "r") as read_file: files = json.load(read_file) - print(" {l}:{c}".format(l=lang[: -len(".json")], c=len(files))) + log.info(" {l}:{c}".format(l=lang[:-len('.json')], c=len(files))) def detect_languages(package_folder, results_folder): """ For each po file, detect metadatas and deduct the language """ """ Requires: a file hierarchy with po files """ """ Returns: a dictionary of lists, key=lang code, value=file list """ + log = logging.getLogger("buildLanguageList.detect_languages") langs = {} packages = [ f @@ -230,6 +245,7 @@ def choose_lang(filename, metadata, error): """ From a po file and its medata, choose the most likely language code """ """ By priority: the Language medata """ """ Returns: a language code """ + log = logging.getLogger("buildLanguageList.choose_lang") lang = "noresult" decision = 0 diff --git a/build_map.py b/build_map.py index e518635..a5bd416 100755 --- a/build_map.py +++ b/build_map.py @@ -6,6 +6,7 @@ import pandas import geopandas import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable +import logging RESULT_FOLDER = "" @@ -36,8 +37,17 @@ def main(): help="Include non official languages?", ) + parser.add_argument("-v", default=False, + action="store_true", dest="verbose", + 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) + log = logging.getLogger("buildMap") + RESULT_FOLDER = "./results/{r}/stats/".format(r=args.results) file = RESULT_FOLDER + "/3.result.csv" @@ -46,6 +56,7 @@ def main(): def parse(file, include_english, include_nonofficial): """Call all cleaning functions""" + log = logging.getLogger("buildMap.parse") # load statistics data = load_results(file) info(data, "CSV loaded") @@ -87,6 +98,7 @@ def parse(file, include_english, include_nonofficial): def load_results(file): """ load previously computed statistics """ + log = logging.getLogger("buildMap.load_results") data = pandas.read_csv(file) data.columns = [ "src", @@ -129,6 +141,7 @@ def load_results(file): def clean_lpopulation(row): """ converts every numbers as percentage """ + log = logging.getLogger("buildMap.clean_lpopulation") val = row.LPopulation if "%" in row.LPopulation: @@ -141,6 +154,7 @@ def clean_lpopulation(row): def load_cldr(include_english, include_nonofficial): """ Load population + language statistics per territory """ + log = logging.getLogger("buildMap.load_cldr") cldr_data = pandas.read_csv( "CLDR-raw/country_language_population_raw.txt", sep="\t" ) @@ -220,6 +234,7 @@ def load_cldr(include_english, include_nonofficial): def get_per_lang_numbers(data): """ agregate statistics per language """ + log = logging.getLogger("buildMap.get_per_lang_numbers") total_source_messages = data.groupby(["src", "dirname"])["totalMessage"].max().sum() total_source_words = ( @@ -255,6 +270,7 @@ def get_per_lang_numbers(data): def add_ISO3(data): + log = logging.getLogger("buildMap.add_ISO3") country_codes = pandas.read_csv("geo_data/country-codes.csv") country_codes["ISO3166-1-Alpha-2"] = country_codes["ISO3166-1-Alpha-2"].str.lower() @@ -270,6 +286,7 @@ def add_ISO3(data): def get_maps(cldr_data, per_lang_numbers): """ merge each """ + log = logging.getLogger("buildMap.get_maps") # language merge: maps = pandas.merge( cldr_data, @@ -317,6 +334,7 @@ def get_maps(cldr_data, per_lang_numbers): def get_data_per_territory(data): """ group result per territory """ + log = logging.getLogger("buildMap.get_data_per_territory") data["message_coverage"] = ( data["language_population"] * data["message_progress_percentage"] @@ -346,6 +364,7 @@ def get_data_per_territory(data): def add_geojson(miaw): """ merge result data with geojson data """ + log = logging.getLogger("buildMap.add_geojson") world = geopandas.read_file("geo_data/countries.geojson") country_codes = pandas.read_csv("geo_data/country-codes.csv") @@ -363,6 +382,7 @@ def add_geojson(miaw): def draw_map(world, column, title, filename, cmap): """ s """ + log = logging.getLogger("buildMap.draw_map") fig, axes = plt.subplots(1, 1, figsize=(20, 12)) divider = make_axes_locatable(axes) @@ -379,7 +399,8 @@ def draw_map(world, column, title, filename, cmap): def info(dataset, step): """Print basic informations about current dataset""" - print(" * " + step + " → we now have " + str(len(dataset)) + " rows") + log = logging.getLogger("buildMap.info") + log.info(" * "+step+" → we now have "+str(len(dataset))+" rows") def store(dataset, name): diff --git a/build_stats.py b/build_stats.py index 27807f7..eff6b73 100755 --- a/build_stats.py +++ b/build_stats.py @@ -7,6 +7,7 @@ import json import os import shutil import polib +import logging from translate.tools.pocount import calcstats @@ -23,9 +24,21 @@ def main(): parser.add_argument( "--refresh", action="store_true", help="Clear results before computing" ) + parser.add_argument( + "-v", + default=False, + action="store_true", + dest="verbose", + 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) + log = logging.getLogger("buildStats") + packages_folder = "./results/{v}/packages/".format(v=args.results) packages_stats_folder = "./results/{v}/packages-stats/".format(v=args.results) languages_folder = "./results/{v}/languages/".format(v=args.results) @@ -42,7 +55,7 @@ def main(): if args.refresh and os.path.isdir(folder): shutil.rmtree(folder) - print("Computing packages stats") + log.info("Computing packages stats") packages = [ f for f in os.listdir(packages_folder) @@ -56,7 +69,7 @@ def main(): for package in sorted(packages): count += 1 - print(" {c}/{t} - {p}".format(c=count, t=len(packages), p=package)) + log.info(" {c}/{t} - {p}".format(c=count, t=len(packages), p=package)) with open(os.path.join(packages_folder, package, "discover.json"), "r") as f: discoveries = json.load(f) @@ -82,7 +95,7 @@ def main(): with open(stats_file, "w") as f: json.dump(results, f, indent=2) - print("Storing distribution stats") + log.info("Storing distribution stats") if not os.path.exists(distribution_stats_folder): os.makedirs(distribution_stats_folder) @@ -90,7 +103,7 @@ def main(): with open(stats_file, "w") as f: json.dump(distribution_stats, f, indent=2) - print("Computing language stats") + log.info("Computing language stats") languages = [f for f in os.listdir(languages_folder)] count = 0 @@ -102,7 +115,7 @@ def main(): count += 1 lang = language[:-5] - print(" {c}/{t} - {l}".format(c=count, t=len(languages), l=lang)) + log.info(" {c}/{t} - {l}".format(c=count, t=len(languages), l=lang)) with open(os.path.join(languages_folder, language), "r") as f: discoveries = json.load(f) @@ -119,17 +132,14 @@ def main(): def get_po_translation_level(files, stats_file): """ Compute results """ + log = logging.getLogger("buildStats.get_po_translation_level") stats = dict() for file in files: try: stat = calcstats(file) except Exception as e: - print( - " {f} triggered an {t} exception: {e}".format( - f=file, t=type(e).__name__, e=e - ) - ) + log.error(" {f} triggered an {t} exception: {e}".format(f=file, t=type(e).__name__, e=e)) continue keys = [ @@ -153,6 +163,7 @@ def get_po_translation_level(files, stats_file): def get_language_team(file): + log = logging.getLogger("buildStats.get_language_team") metadata = dict() try: metadata = polib.pofile(file).metadata @@ -167,11 +178,12 @@ def get_language_team(file): try: team = metadata["Language-Team"] except KeyError: - print("The file {f} have no Language team? Here are the metadata: {m}".format(f=file, m=metadata)) + log.error("The file {f} have no Language team? Here are the metadata: {m}".format(f=file, m=metadata)) return team def extract_release_stats(results, files_stats): + log = logging.getLogger("buildStats.extract_release_stats") number_of_packages = results.get("nb_packages", 0) number_of_packages += 1 number_of_files = results.get("nb_files", 0) diff --git a/build_tm.py b/build_tm.py index b38504b..aa49eb8 100755 --- a/build_tm.py +++ b/build_tm.py @@ -8,6 +8,7 @@ import os import subprocess import shutil import tempfile +import logging from io import BytesIO from translate.convert import po2tmx @@ -30,8 +31,17 @@ def main(): parser.add_argument("--compress", action="store_true", help="Compress output files") + parser.add_argument("-v", default=False, + action="store_true", dest="verbose", + 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) + log = logging.getLogger("buildTm") + results_folder = "./results/{v}/".format(v=args.results) lang_path = os.path.join(results_folder, "languages/") tm_folder = os.path.join(results_folder, "languages-tm/") @@ -44,7 +54,7 @@ def main(): if not os.path.exists(tm_folder): os.makedirs(tm_folder) - print("Building the translation memory for every languages") + log.info("Building the translation memory for every languages") langs = [ f for f in os.listdir(lang_path) if os.path.isfile(os.path.join(lang_path, f)) @@ -53,7 +63,7 @@ def main(): for lang in sorted(langs): lang_code = lang[: -len(".json")] - print(" {l}".format(l=lang_code)) + log.info(" {l}".format(l=lang_code)) with open(os.path.join(lang_path, lang), "r") as read_file: files = json.load(read_file)["po"] @@ -66,7 +76,7 @@ def main(): try: process_compendium(files, compendium_file) except Exception as e: - print( + log.error( " Compendium generation triggered an {t} exception: {e}".format( t=type(e).__name__, e=e ) @@ -77,7 +87,7 @@ def main(): try: process_tmx(lang_code, compendium_file, tmx_file) except Exception as e: - print( + log.error( " TMX generation triggered an {t} exception: {e}".format( t=type(e).__name__, e=e ) @@ -88,23 +98,24 @@ def main(): try: process_terminology(compendium_file, terminology_file) except Exception as e: - print( + log.error( " Terminology generation triggered an {t} exception: {e}".format( t=type(e).__name__, e=e ) ) - print("Detecting missing files") + log.info("Detecting missing files") for lang in sorted(langs): check_lang(lang[: -len(".json")], tm_folder) if args.compress: - print("Compressing files") + log.info("Compressing files") compress(tm_folder) def process_compendium(langfiles, dest): """ Generate a compendium (a concatenation of all po files) """ + log = logging.getLogger("buildTm.process_compendium") pofiles = [ os.path.join(os.path.dirname(os.path.abspath(__file__)), f) for f in langfiles @@ -135,7 +146,7 @@ def process_compendium(langfiles, dest): ] subprocess.run(command, check=True, cwd=tmp, capture_output=True) except subprocess.CalledProcessError as e: - print("Error with msguniq {i}, error: {e}".format(i=i, e=e)) + log.error("Error with msguniq {i}, error: {e}".format(i=i, e=e)) count += 1 @@ -151,7 +162,7 @@ def process_compendium(langfiles, dest): try: subprocess.run(command, check=True, cwd=tmp, capture_output=True) except subprocess.CalledProcessError: - print(" msgcat exception...") + log.error(" msgcat exception...") def process_tmx(lang, source, dest): @@ -203,23 +214,25 @@ def process_terminology(source, dest): def check_lang(lang, tm_folder): """ Check if expected files were generated """ + log = logging.getLogger("buildTm.check_lang") compendium_file = os.path.join(tm_folder, lang + ".po") tmx_file = os.path.join(tm_folder, lang + ".tmx") terminology_file = os.path.join(tm_folder, lang + ".terminology.po") if not os.path.isfile(compendium_file): - print(" {l}-compendium is missing".format(l=lang)) + log.warning(" {l}-compendium is missing".format(l=lang)) if not os.path.isfile(tmx_file): - print(" {l}-tmx is missing".format(l=lang)) + log.warning(" {l}-tmx is missing".format(l=lang)) if not os.path.isfile(terminology_file): - print(" {l}-terminology is missing".format(l=lang)) + log.warning(" {l}-terminology is missing".format(l=lang)) def compress(folder): """ Compress files uzing gzip """ + log = logging.getLogger("buildTm.compress") files = [f for f in os.listdir(folder) if os.path.isfile(os.path.join(folder, f))] diff --git a/build_website.py b/build_website.py index b340094..09fdd60 100755 --- a/build_website.py +++ b/build_website.py @@ -9,6 +9,7 @@ import langtable import os import pandas as pd import shutil +import logging def main(): @@ -22,8 +23,17 @@ def main(): parser.add_argument("--refresh", action="store_true", help="Force refresh of files") + parser.add_argument("-v", default=False, + action="store_true", dest="verbose", + 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, force=True) + log = logging.getLogger("buildWebsite") + results_folder = "./results/{v}/".format(v=args.results) langs_log = os.path.join(results_folder, "build_language_list.log") langs_stats = os.path.join(results_folder, "languages-stats") @@ -53,12 +63,12 @@ def main(): os.makedirs(folder, exist_ok=True) - print("Get distribution stats") + log.info("Get distribution stats") distribution_stats = json.load( open(os.path.join(distribution_folder, "release.json")) ) - print("Prepare json files for packages") + log.info("Prepare json files for packages") packages = [ d for d in os.listdir(packages_stats) @@ -82,7 +92,7 @@ def main(): val.append({"name": name, "progress": lang["progress"], "translated": lang["translated"], "team": lang["team"]}) packages_langs_results[lang["lang_code"]] = val - print("Prepare json files for languages") + log.info("Prepare json files for languages") languages = [ f for f in os.listdir(langs_stats) @@ -103,7 +113,7 @@ def main(): store_json_file(results, dest_file) # generate static content for languages - print("Generate static content for languages") + log.info("Generate static content for languages") languages = [ f for f in os.listdir(data_langs_folder) @@ -121,7 +131,7 @@ def main(): generate_static_pages_langs(args.results, code, content, dest_file) - print("Generate static content for packages") + log.info("Generate static content for packages") packages = [ f for f in os.listdir(data_pkgs_folder) @@ -139,7 +149,7 @@ def main(): generate_static_pages_packages(args.results, code, content, dest_file) - print("Copy translation memories") + log.info("Copy translation memories") languages = [ f for f in os.listdir(tm_folder) if os.path.isfile(os.path.join(tm_folder, f)) ] @@ -152,6 +162,7 @@ def main(): def consolidate_language_stats(stats_file, distribution_stats): """ From a CSV file, return key indicators """ + log = logging.getLogger("buildWebsite.consolidate_language_stats") results = dict() total_words_distrib = distribution_stats.get("totalsourcewords", 0) @@ -198,6 +209,7 @@ def consolidate_language_stats(stats_file, distribution_stats): def consolidate_package_stats(stats_file, log_files): """ From a CSV file, return key indicators """ + log = logging.getLogger("buildWebsite.consolidate_package_stats") results = dict() fieldnames = { @@ -224,7 +236,7 @@ def consolidate_package_stats(stats_file, log_files): # sometimes, no file were found, which means no stats can be used if len(tmp_df) == 0: - print(" The template {t} for {f} is empty".format(t=template, f=stats_file)) + log.warning(" The template {t} for {f} is empty".format(t=template, f=stats_file)) continue tmp_df["totalsourcewords"] = ( @@ -239,7 +251,7 @@ def consolidate_package_stats(stats_file, log_files): if len(dfs) > 1: stats_df = pd.concat(dfs) elif len(dfs) == 0: - print("There is no stats for {f}".format(f=stats_file)) + log.warning("There is no stats for {f}".format(f=stats_file)) return results else: stats_df = dfs[0] @@ -267,7 +279,7 @@ def consolidate_package_stats(stats_file, log_files): line["translated"] = line["translatedsourcewords"] if total_source_words == 0: - print( + log.info( " File {f} for file has translatedsourcewords = 0 in line {l}".format( f=stats_file, l=line ) @@ -277,7 +289,7 @@ def consolidate_package_stats(stats_file, log_files): try: line["progress"] = round((int(line["translatedsourcewords"]) / total_source_words) * 100) except OverflowError: - print( + log.info( " File {f} has Translated={t} and Source={tot}".format( f=stats_file, t=line["translatedsourcewords"], @@ -298,6 +310,7 @@ def consolidate_package_stats(stats_file, log_files): def generate_static_pages_langs(results, code, content, dest_file): + log = logging.getLogger("buildWebsite.generate_static_pages_langs") data = content data["lang_name_en"] = langtable.language_name( languageId=code, languageIdQuery="en" @@ -319,6 +332,7 @@ def generate_static_pages_langs(results, code, content, dest_file): def generate_static_pages_packages(results, code, content, dest_file): + log = logging.getLogger("buildWebsite.generate_static_pages_packages") data = content data["results"] = results data["package"] = code