From 44ca4eeae29608190bb391d96f569d34c3e1a32a Mon Sep 17 00:00:00 2001 From: Revital Sur Date: Tue, 11 Jun 2024 23:23:21 +0300 Subject: [PATCH] Adjust ingest_2_parquet workflow. Signed-off-by: Revital Sur --- .github/workflows/test.yml | 2 +- .../src/runtime_utils/kfp_utils.py | 3 - kind/hack/populate_minio.sh | 4 +- transforms/code/ingest_2_parquet/Makefile | 10 +- .../code/ingest_2_parquet/kfp_ray/Makefile | 44 +++++++ .../kfp_ray/{v1 => }/ingest_2_parquet_wf.py | 119 ++++++++++++------ .../code/ingest_2_parquet/kfp_ray/v1/Makefile | 25 ---- .../expected/data-processing-lib.parquet | Bin 0 -> 29995 bytes .../test-data/input/data-processing-lib.zip | Bin 0 -> 118377 bytes .../ray/test/test_ingest_to_parquet.py | 2 +- 10 files changed, 137 insertions(+), 72 deletions(-) create mode 100644 transforms/code/ingest_2_parquet/kfp_ray/Makefile rename transforms/code/ingest_2_parquet/kfp_ray/{v1 => }/ingest_2_parquet_wf.py (62%) delete mode 100644 transforms/code/ingest_2_parquet/kfp_ray/v1/Makefile create mode 100644 transforms/code/ingest_2_parquet/ray/test-data/expected/data-processing-lib.parquet create mode 100644 transforms/code/ingest_2_parquet/ray/test-data/input/data-processing-lib.zip diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9324ead7e0..e6c5a6a480 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -111,5 +111,5 @@ jobs: export DEPLOY_KUBEFLOW=1 make -C kind setup make -C kfp/kfp_support_lib test - make -C transforms/universal/noop/ workflow-build + make -C transforms workflow-build make -C transforms/universal/noop workflow-test diff --git a/kfp/kfp_support_lib/shared_workflow_support/src/runtime_utils/kfp_utils.py b/kfp/kfp_support_lib/shared_workflow_support/src/runtime_utils/kfp_utils.py index 2b5e6509bd..3b992c8ceb 100644 --- a/kfp/kfp_support_lib/shared_workflow_support/src/runtime_utils/kfp_utils.py +++ b/kfp/kfp_support_lib/shared_workflow_support/src/runtime_utils/kfp_utils.py @@ -94,9 +94,6 @@ def dict_to_req(d: dict[str, Any], executor: str = "transformer_launcher.py") -> if '"' in value: logger.warning(f"can't parse inputs with double quotation marks, please use single quotation marks instead") res += f'--{key}="{value}" ' - elif isinstance(value, bool): - if value: - res += f"--{key} " else: res += f"--{key}={value} " diff --git a/kind/hack/populate_minio.sh b/kind/hack/populate_minio.sh index c30ebea54a..3484475877 100755 --- a/kind/hack/populate_minio.sh +++ b/kind/hack/populate_minio.sh @@ -12,8 +12,8 @@ mc mb kfp/test echo "copying data" # code modules mc cp --recursive ${ROOT_DIR}/../transforms/code/code_quality/ray/test-data/input/ kfp/test/code_quality/input -mc cp --recursive ${ROOT_DIR}/../transforms/code/ingest2parquet/ray/test-data/input/ kfp/test/ingest2parquet/input -mc cp --recursive ${ROOT_DIR}/../transforms/code/ingest2parquet/ray/test-data/languages/ kfp/test/ingest2parquet/languages +mc cp --recursive ${ROOT_DIR}/../transforms/code/ingest_2_parquet/ray/test-data/input/data-processing-lib.zip kfp/test/ingest_2_parquet/input +mc cp --recursive ${ROOT_DIR}/../transforms/code/ingest_2_parquet/ray/test-data/languages/ kfp/test/ingest_2_parquet/languages mc cp --recursive ${ROOT_DIR}/../transforms/code/proglang_select/ray/test-data/input/ kfp/test/proglang_select/input mc cp --recursive ${ROOT_DIR}/../transforms/code/proglang_select/ray/test-data/languages/ kfp/test/proglang_select/languages mc cp --recursive ${ROOT_DIR}/../transforms/code/malware/ray/test-data/input/ kfp/test/malware/input diff --git a/transforms/code/ingest_2_parquet/Makefile b/transforms/code/ingest_2_parquet/Makefile index 923d291852..227d850505 100644 --- a/transforms/code/ingest_2_parquet/Makefile +++ b/transforms/code/ingest_2_parquet/Makefile @@ -43,21 +43,21 @@ load-image:: .PHONY: workflow-venv workflow-venv: - $(MAKE) -C kfp_ray/v1 workflow-venv + $(MAKE) -C kfp_ray workflow-venv .PHONY: workflow-build workflow-build: - $(MAKE) -C kfp_ray/v1 workflow-build + $(MAKE) -C kfp_ray workflow-build .PHONY: workflow-test workflow-test: - $(MAKE) -C kfp_ray/v1 workflow-test + $(MAKE) -C kfp_ray workflow-test .PHONY: workflow-upload workflow-upload: - $(MAKE) -C kfp_ray/v1 workflow-upload + $(MAKE) -C kfp_ray workflow-upload .PHONY: workflow-reconcile-requirements workflow-reconcile-requirements: - $(MAKE) -C kfp_ray/v1 workflow-reconcile-requirements + $(MAKE) -C kfp_ray workflow-reconcile-requirements diff --git a/transforms/code/ingest_2_parquet/kfp_ray/Makefile b/transforms/code/ingest_2_parquet/kfp_ray/Makefile new file mode 100644 index 0000000000..aa34444cd4 --- /dev/null +++ b/transforms/code/ingest_2_parquet/kfp_ray/Makefile @@ -0,0 +1,44 @@ +REPOROOT=${CURDIR}/../../../../ +WORKFLOW_VENV_ACTIVATE=${REPOROOT}/transforms/venv/bin/activate +include $(REPOROOT)/transforms/.make.workflows + +SRC_DIR=${CURDIR}/../ray/ + +PYTHON_WF := $(shell find ./ -name '*_wf.py') +YAML_WF := $(patsubst %.py, %.yaml, ${PYTHON_WF}) + +workflow-venv: .check_python_version ${WORKFLOW_VENV_ACTIVATE} + +venv:: + +build:: + +test:: + +test-src:: + +test-image:: + +image:: + +load-image:: + +.PHONY: workflow-build +workflow-build: workflow-venv + $(MAKE) $(YAML_WF) + +.PHONY: workflow-test +workflow-test: workflow-build + $(MAKE) .transforms_workflows.test-pipeline TRANSFORM_SRC=${SRC_DIR} PIPELINE_FILE=ingest_2_parquet_wf.yaml + +.PHONY: workflow-upload +workflow-upload: workflow-build + @for file in $(YAML_WF); do \ + $(MAKE) .transforms_workflows.upload-pipeline PIPELINE_FILE=$$file; \ + done + +.PHONY: workflow-reconcile-requirements +workflow-reconcile-requirements: + @for file in $(PYTHON_WF); do \ + $(MAKE) .transforms_workflows.reconcile-requirements PIPELINE_FILE=$$file; \ + done diff --git a/transforms/code/ingest_2_parquet/kfp_ray/v1/ingest_2_parquet_wf.py b/transforms/code/ingest_2_parquet/kfp_ray/ingest_2_parquet_wf.py similarity index 62% rename from transforms/code/ingest_2_parquet/kfp_ray/v1/ingest_2_parquet_wf.py rename to transforms/code/ingest_2_parquet/kfp_ray/ingest_2_parquet_wf.py index a3008dbfa9..6f033f4a39 100644 --- a/transforms/code/ingest_2_parquet/kfp_ray/v1/ingest_2_parquet_wf.py +++ b/transforms/code/ingest_2_parquet/kfp_ray/ingest_2_parquet_wf.py @@ -10,33 +10,85 @@ # limitations under the License. ################################################################################ +import os + +from workflow_support.compile_utils import ONE_HOUR_SEC, ONE_WEEK_SEC, ComponentUtils + import kfp.compiler as compiler import kfp.components as comp import kfp.dsl as dsl -from kfp_support.workflow_support.utils import ( - ONE_HOUR_SEC, - ONE_WEEK_SEC, - ComponentUtils, -) -from data_processing.utils import GB - # the name of the job script -EXEC_SCRIPT_NAME: str = "ingest_2_parquet_transform.py" +EXEC_SCRIPT_NAME: str = "ingest_2_parquet_transform_ray.py" + +task_image = "quay.io/dataprep1/data-prep-kit/ingest_2_parquet-ray:0.4.0.dev6" -task_image = "quay.io/dataprep1/data-prep-kit/ingest_2_parquet:0.3.0" # components base_kfp_image = "quay.io/dataprep1/data-prep-kit/kfp-data-processing:0.2.0.dev6" # path to kfp component specifications files -component_spec_path = "../../../../../kfp/kfp_ray_components/" +component_spec_path = "../../../../kfp/kfp_ray_components/" # compute execution parameters. Here different transforms might need different implementations. As # a result, instead of creating a component we are creating it in place here. -compute_exec_params_op = comp.func_to_container_op( - func=ComponentUtils.default_compute_execution_params, base_image=base_kfp_image -) +def compute_exec_params_func( + worker_options: str, + actor_options: str, + data_s3_config: str, + data_max_files: int, + data_num_samples: int, + data_files_to_use: str, + runtime_pipeline_id: str, + runtime_job_id: str, + runtime_code_location: str, + ingest_to_parquet_supported_langs_file: str, + ingest_to_parquet_domain: str, + ingest_to_parquet_snapshot: str, + ingest_to_parquet_detect_programming_lang: bool, +) -> dict: + from workflow_support.runtime_utils import KFPUtils + + return { + "data_s3_config": data_s3_config, + "data_max_files": data_max_files, + "data_num_samples": data_num_samples, + "data_files_to_use": data_files_to_use, + "runtime_num_workers": KFPUtils.default_compute_execution_params(worker_options, actor_options), + "runtime_worker_options": actor_options, + "runtime_pipeline_id": runtime_pipeline_id, + "runtime_job_id": runtime_job_id, + "runtime_code_location": runtime_code_location, + "ingest_to_parquet_supported_langs_file": ingest_to_parquet_supported_langs_file, + "ingest_to_parquet_domain": ingest_to_parquet_domain, + "ingest_to_parquet_snapshot": ingest_to_parquet_snapshot, + "ingest_to_parquet_detect_programming_lang": ingest_to_parquet_detect_programming_lang, + } + + +# KFPv1 and KFP2 uses different methods to create a component from a function. KFPv1 uses the +# `create_component_from_func` function, but it is deprecated by KFPv2 and so has a different import path. +# KFPv2 recommends using the `@dsl.component` decorator, which doesn't exist in KFPv1. Therefore, here we use +# this if/else statement and explicitly call the decorator. +if os.getenv("KFPv2", "0") == "1": + # In KFPv2 dsl.RUN_ID_PLACEHOLDER is deprecated and cannot be used since SDK 2.5.0. On another hand we cannot create + # a unique string in a component (at runtime) and pass it to the `clean_up_task` of `ExitHandler`, due to + # https://github.com/kubeflow/pipelines/issues/10187. Therefore, meantime we use a unique string created at + # compilation time. + import uuid + + compute_exec_params_op = dsl.component_decorator.component( + func=compute_exec_params_func, base_image=base_kfp_image + ) + print( + "WARNING: the ray cluster name can be non-unique at runtime, please do not execute simultaneous Runs of the " + + "same version of the same pipeline !!!") + run_id = uuid.uuid4().hex +else: + compute_exec_params_op = comp.create_component_from_func(func=compute_exec_params_func, base_image=base_kfp_image) + run_id = dsl.RUN_ID_PLACEHOLDER + + # create Ray cluster create_ray_op = comp.load_component_from_file(component_spec_path + "createRayClusterComponent.yaml") # execute job @@ -59,17 +111,17 @@ def ingest_to_parquet( '"image_pull_secret": "", "image": "' + task_image + '"}', server_url: str = "http://kuberay-apiserver-service.kuberay.svc.cluster.local:8888", # data access - data_s3_config: str = "{'input_folder': 'test/ingest2parquet/input', 'output_folder': 'test/ingest2parquet/output/'}", + data_s3_config: str = "{'input_folder': 'test/ingest_2_parquet/input', 'output_folder': 'test/ingest_2_parquet/output/'}", data_s3_access_secret: str = "s3-secret", data_max_files: int = -1, data_num_samples: int = -1, data_files_to_use: str = "['.zip']", # orchestrator - runtime_actor_options: str = f"{{'num_cpus': 0.8, 'memory': {2*GB}}}", + runtime_actor_options: str = "{'num_cpus': 0.8}", runtime_pipeline_id: str = "pipeline_id", runtime_code_location: str = "{'github': 'github', 'commit_hash': '12345', 'path': 'path'}", # Proglang match parameters - ingest_to_parquet_supported_langs_file: str = "test/ingest2parquet/languages/lang_extensions.json", + ingest_to_parquet_supported_langs_file: str = "test/ingest_2_parquet/languages/lang_extensions.json", ingest_to_parquet_detect_programming_lang: bool = True, ingest_to_parquet_domain: str = "code", ingest_to_parquet_snapshot: str = "github", @@ -118,7 +170,7 @@ def ingest_to_parquet( :return: None """ # create clean_up task - clean_up_task = cleanup_ray_op(ray_name=ray_name, run_id=dsl.RUN_ID_PLACEHOLDER, server_url=server_url) + clean_up_task = cleanup_ray_op(ray_name=ray_name, run_id=run_id, server_url=server_url) ComponentUtils.add_settings_to_component(clean_up_task, 60) # pipeline definition with dsl.ExitHandler(clean_up_task): @@ -126,12 +178,23 @@ def ingest_to_parquet( compute_exec_params = compute_exec_params_op( worker_options=ray_worker_options, actor_options=runtime_actor_options, + data_s3_config=data_s3_config, + data_max_files=data_max_files, + data_num_samples=data_num_samples, + data_files_to_use=data_files_to_use, + runtime_pipeline_id=runtime_pipeline_id, + runtime_job_id=run_id, + runtime_code_location=runtime_code_location, + ingest_to_parquet_supported_langs_file=ingest_to_parquet_supported_langs_file, + ingest_to_parquet_domain=ingest_to_parquet_domain, + ingest_to_parquet_snapshot=ingest_to_parquet_snapshot, + ingest_to_parquet_detect_programming_lang=ingest_to_parquet_detect_programming_lang, ) ComponentUtils.add_settings_to_component(compute_exec_params, ONE_HOUR_SEC * 2) # start Ray cluster ray_cluster = create_ray_op( ray_name=ray_name, - run_id=dsl.RUN_ID_PLACEHOLDER, + run_id=run_id, ray_head_options=ray_head_options, ray_worker_options=ray_worker_options, server_url=server_url, @@ -142,24 +205,10 @@ def ingest_to_parquet( # Execute job execute_job = execute_ray_jobs_op( ray_name=ray_name, - run_id=dsl.RUN_ID_PLACEHOLDER, + run_id=run_id, additional_params=additional_params, - # note that the parameters below are specific for NOOP transform - exec_params={ - "data_s3_config": data_s3_config, - "data_max_files": data_max_files, - "data_num_samples": data_num_samples, - "data_files_to_use": data_files_to_use, - "runtime_num_workers": compute_exec_params.output, - "runtime_worker_options": runtime_actor_options, - "runtime_pipeline_id": runtime_pipeline_id, - "runtime_job_id": dsl.RUN_ID_PLACEHOLDER, - "runtime_code_location": runtime_code_location, - "ingest_to_parquet_supported_langs_file": ingest_to_parquet_supported_langs_file, - "ingest_to_parquet_domain": ingest_to_parquet_domain, - "ingest_to_parquet_snapshot": ingest_to_parquet_snapshot, - "ingest_to_parquet_detect_programming_lang": ingest_to_parquet_detect_programming_lang, - }, + # note that the parameters below are specific for this transform + exec_params=compute_exec_params.output, exec_script_name=EXEC_SCRIPT_NAME, server_url=server_url, prefix=PREFIX, diff --git a/transforms/code/ingest_2_parquet/kfp_ray/v1/Makefile b/transforms/code/ingest_2_parquet/kfp_ray/v1/Makefile deleted file mode 100644 index e3cd775bf8..0000000000 --- a/transforms/code/ingest_2_parquet/kfp_ray/v1/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -REPOROOT=${CURDIR}/../../../../../ -WORKFLOW_VENV_ACTIVATE=${REPOROOT}/transforms/venv/bin/activate -include $(REPOROOT)/transforms/.make.workflows - -SRC_DIR=${CURDIR}/../../ray/ - -YAML_FILE=ingest_2_parquet_wf.yaml - -workflow-venv: .check_python_version ${WORKFLOW_VENV_ACTIVATE} - -.PHONY: workflow-build -workflow-build: workflow-venv - $(MAKE) ${YAML_FILE} - -.PHONY: workflow-test -workflow-test: workflow-build - $(MAKE) .transforms_workflows.test-pipeline TRANSFORM_SRC=${SRC_DIR} PIPELINE_FILE=${YAML_FILE} - -.PHONY: workflow-upload -workflow-upload: workflow-build - $(MAKE) .transforms_workflows.upload-pipeline PIPELINE_FILE=${YAML_FILE} - -.PHONY: workflow-reconcile-requirements -workflow-reconcile-requirements: - $(MAKE) .transforms_workflows.reconcile-requirements PIPELINE_FILE=ingest_2_parquet_wf.py diff --git a/transforms/code/ingest_2_parquet/ray/test-data/expected/data-processing-lib.parquet b/transforms/code/ingest_2_parquet/ray/test-data/expected/data-processing-lib.parquet new file mode 100644 index 0000000000000000000000000000000000000000..521116020298d603ad6c9bba5a415366f5d1934b GIT binary patch literal 29995 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 literal 0 HcmV?d00001 diff --git a/transforms/code/ingest_2_parquet/ray/test-data/input/data-processing-lib.zip b/transforms/code/ingest_2_parquet/ray/test-data/input/data-processing-lib.zip new file mode 100644 index 0000000000000000000000000000000000000000..069bc536a5acf9c122b2d071adcfcc3a51e93de4 GIT binary patch literal 118377 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�=enmm_dF>#r~*l8OS}&rGWC3*aF7Q ze=f>7+u;>El*&_^6xg|S!4p;}%?)%Ng?-=gT~2ImBj|lgRdqDQ5kKA6-9p5GjgfWiTBi!#Az3YYr+KFibtAtjK`0_+`Fsd)ky}U?lr`#Av`kWR_FmOI2Sxle z5E{_2k3v$dxfumcm6c+0cY96f7)FX8x%#ujm3NMzZz4U1^-(_fl_YWxhabQesNO11 zDLrz~05DULuYlv^&uwXhTSM>E@fOs7?-*t;gVxrJf5|-3<`6UyM8l{|JDi=J#xtzk zE=2{Yaq6x39E{e5;}!rSYe56$lBx;VSh4_T$-s(g)EcHrdwwLa@q=G(?-44t|Fqgv zKN}MGK_mRLzWS1G1_1~gKHSX{C_frzjQ%-d;S|A#FBy4r+A}-Y18N5Iz0jrjWjgtbaVi+AoY^~R(Oz{f zFKzB&Kkw?vy;Xjc43DABd_Lb-wQLR6n`rE`FY1loLEYf$2F))48Bj)uoel9SoXLe+ zmjCrKS1^OlQrKKK2}0S?La}{C3g3fAuQFUrP6YD2!kuQ$Rwz=~&aQYKnJK$Ftaa4B zF_p16Zbe*Z#nC)ID=K)ed$n63VH{q-8J~f)Gx#3KMA0eq39zo*yG=O3`3Go=c8gS_ z5t2#$GN;&FeGlR1IPqaJa%8!dI8tvL5X}o-s>i5h#3FeL6&jBo&$zbcU59Ebib{{T zTH(h%p@9{z(0`!HMNh*++tF;MAe@5}Bb1lpRHza)wW51}snT~g>}PlY0I-LBm-YQZ zq`Zq|y3S7KR*pZ2U;FBZHuJ3T9}n`_>(NPF!;?|Ec-?x-nfDb8wH1hmLNdWYGTTrH;VN6S(u_nEKGMwE&qtuV)<8VOJ3Mf0R>Xbk$m+wCY9oYRj68_@QCybL zd3E$SD{Y|z*bVpcg_ss!9JSn24T9v{!Mrq2W9TOtkp!|U&mTdDlb*jjUiLg5fAvwM zEiwjX1m6Tptlme8Fc^Y_x(gg|`SJxNIMR`OvIv2sr=N4aiik3;2-XQFTE|uh0t?Y) zOlq7nr(OuTevT4niqzC@%|KWQEm{Y0C9}hcr^|hR>5KiNDVJ$8Dc3oO{k=g7{-5+qrv1&Y>Xg5(&?UynMygBIWz^)t4ckp z!`Tur%W?sZo2D~T`igjKa&Mz*ASwRn?Yp;c-@Vz`+hNht>6qQ2ijcnPg;U zkYGU;Mc+$M@!(E&C8-29O)Mf7-3v@;vj%Rpt7IGmvsp@tYJN$j+&F5=hSkCq#kVNWH2+*0XsW&Dq$R!)l9K&zxJ% zg(`vxf=hxn0>UxP0CHJ~dcz#8lYYinqnVkabp-MXr@8~MnxRL_%0^+7aqQ@hq;ZynY;_gRvgydZqT)Ys|Dt7YU87|3hk$7EC?lRy%FYL z#3MJZy~Tf)AMK^M8}CuMJ*Xx%naWoh+M+zht8)S~qciBlX{g3fFcQnbK&B-5!X_c% z;I(0CIZgVE)6x)0M!&8#PRP7YIu|Kxj(sFuBS}#oDMA9t zq@ND<1@bI}q@Xk-1()P>eJ`__4S`$En|y24ja%Z-Ex)|Sx-5jiqIyrZ@~47=jW2cL zjBp~2N!=y`R7syouf)M|?z6*ygppexlWVS+7*CfpQW3qJFi&K+h}_s_MWEw;!|gc} zG|*ck?_vcl>g!_drdTEBTAPa73j)KqjU0}>cmSlpOXB8nUJTgh@`@DN_)3R=9A4IX z6Uo7*C{_ucm-{mCO}H?sfHbSdM3#6uS+z*$TrSfookHcA+`d`E;iTnqRbQ*DtF~oP z(gUv+fadbl+9t~_hoNOwlpz4&V0GGR4hx3YPMh-a!QAPZ&KW4^r_kMwc}JyU&d!Z0 zEF0PpZ&U4Df+>R=Ti#h0*Pp44Ciu7{x}dR-0GXbn`%;>DD6#V5sVEn|s90=Sv&F-e zZPW>WG~+{Ct4F7~XiBzNmQ;+>%DdyH$}q`UNzJhA9|Fdw+ZeAezy_LowENM5M=N&J z8CSbdF;@kX1+^CjstfZ#oAb6MhYyhx)D0kt5OGx8S+t5^%idR37bR^~rsQVNY zm^FZllGdhW1ubu2(adTP!&N#!jFVc z(C4>qK1?|Yke;i!t9Nz-fzl>h&$pG5z4b0WxM~?KbnQXgXtF*I)Gw*$MRJ_qd!TQd zbfX82I^Cg0U1|-7XjWM7In8;r;+8t@H$f%3?Mqe8K_S_;P%^12U5`fTKNoq1crUBH+Wsu_X z=@B_e%Slsdr^}rZp*h5=C3uQKFF_zd?+^8LDcSJI{)k7>+3dS zsu#H|3Jn18@E4ZnuiFeqCw(V#M<;W`AFb3SDvRNBBFL><6yd!v`Ngg^7Pk38 zot2s>EXGv$!I|Wh0mlqnAv|ltVO@=??vWohPKbG!SbLsk6i+l%cnv2Uay?|iYxY^n zhC_-)(I`%%mO6Z#N0$O>_sH?e@U=UrEvTqDy^oeieg`i>7*o%VygS$tZViG&r?nk0 z58Bbq{BrE+Ro#=zhe#3`4r1zn3hKQuh+*{bp&)>1944rKAf;o}2vQDy&&p*}3w`W^ zJ&W-t`WZt^kkdw07s7x|C=gSNhXSUjlZHt3c&GVx-a9Mwyx6T9@9VNUwiCWkc*m8H z&X9gQqGeX-s0=VbjxekeqtnTn&Rkw2a-zP0xM-&DuLakhKV$PkL?GC&LZjHBX}Z8# zL&=KisYiGA?wA|kIOu!ugPzbG13q@V+yPy@Wt!D4H(tDvxbZ+x?qU5C_NFx2ya=Yt zOVFOGh@*KYmxln^ya*_~rgM{g!I0B}VOm|NL65{=7E1LS^$Jt7Pm)e^Xc84qs!l{n z_&_^Th9%`@AQK6Q3sF*6EjcKmk6w=yjR)6Abf6|k1{TWCb*iDJ$hmMP}<6)aVP!P@aT5 zf)NL%MhKfHnF-_eAt!$5f|%r0^|T_3-FT;g$6j^Is}NZn)$}9kqm~S3fjH@t`z|-9 z;TVab1&eZT>|=?07ZZGABic>Z82su|_jC!v z2%!CuS)m_+MY{oDj8n4+ayBeH&eV8d1DjS9w#dkV6R-0y|LnahtpND7--2;RWPFML zXl-AM&3+DZ6Yw@|tZ{G}rIJcx2&!})j51NEj1T7)U?x*d7e=gQc*Z#4ctHJDSz{o~ z`PgC2VEgcsc7bUo**)_(o{#d161LqH?`x+KC{pvt_Zu`^81i;!d#+8zO(7x-WMWlB zlPTfG2T?Pe6Bk4#?2>Tm>jcc-i>|=4m`sdqubW#mdYvY@k9$+zY-q{wrE%Xrx&^kg zWO-|2#bT{Gk2R|E(XDJLUbG|cRh zY$ikUj%*e^zkvb|JBJ!s#WUX$UXixv3|u00pzBK&N?&l{4-GfkB8k-!a*|l4E!qz4 zWo&Gg2IUl;BD6(2W=4KX{W$b>3&=9m7zxND2Ui4NYx2<#veG5uTj(R=E8!Ra*fOwm z=uhb19S}z%0s!#*R!p+eceXJ!Gj{mF-l0U*+HzhD{`NqZfnAr_4w(%5tRoPrG+NHF zCHv(;Y^S%HB$YdddeOZ0BrCydys<0C8xpoEj|w9Sb4W5VqY@L7t&Idz71NbL?H2=k z=|as6e213vFc)GP z6Zs<<8swT5-c#dkvG%ELolX~glyWtDPg7!!M#at`W?b*M=d%pmqY~uR@&+kMD!G(( z^fS2tn;|(dIkSkUl7k4%DKuyU2y++JYAsD4>wRRa0t06kE$plOt{%KtUe=~l3BBU- zZ1kU9G(GpScjW;Jcke7Y=T$@o=A0N%uJNUo9RF=VKzmGYit?V9uuy;pn4fAuWCsVt;2#xRO;2S91Ca);Koxf z*m55`|! zn3J-`{nzaQ9PY+o#qWutuJif&vhmnoyclj=LyhaFPs$i$QN^wbz1Hh0jVA+tT)WS% zZCK_3oFkYQ(!#5_6$d9|?7i5y$`FM`iVdOmsHOES_C<$%3+JTunTS_YV~K;CGoU2S z;7kO;E_{2gO4{Rwp-d!r>t5{R3>-v<)oU2JkMB%9g{vNPvoTUDrUzTMkHNU$h3A0y zalmF|UCe#U_NecB^*v%P`+c?C^=;b&h1L+Hbv9JJvaa_caFbfL{jaN*s zbuvjQ3x_O8bzj8gZTfmS`guM_!y$h@N;+<)R*UrfqhU%18T(0}-NYDgm&cxpr>&XU zMkBfhwfH*h)WVC-i8ze;Saz=j)-6jBhvIkQX){?IegVwlPtu)sB7{73$br_dc8F-$ zZ6xy+ys4He+pA%loc3{KE9WIPw_6`Y(MR}a=(X`+uf)5g`jr&B@=|KR!TNRJ4*av3261kyXZ$hcZZm6R80l>9$nxpQXQbn4 zWSerVzzK&=5ZC7@1d>qeqBq}~x1}-J&83u0_2@CbsTyo*k>9LYbIB}<(rH&`i?>kU z^H)3;FM8a)eJq42Zh9_{;LNV!wX|yGY#^~86 z(FoG2-99aIZg#@NTDbZGNO-CtS*W*`e7*Td=-2RMPOBM-=q<@E#e0elHPlX`Ss>!Q z)9!l{JUXjWn3?_o!5Q-m0L?GF<_3# z9y872vneF?ZMbo_3Yj3=Q=*)q)G?(|kxa()B+O5%8u!OdR_wbyjmeuw^Cx>?=f{OJ zf+;F1dtAcYOeKi+_=0)32lVcs0Egl2ck^}a{h zV!mnCM5BwdN6^97|e8< z^e`C%_C4f9C;*L_v!45hm!l^`kK7EEgLHJ;ZbjMM{U7%uDNGRyOD7-(oFnm{LXsVo zFAGhJGO%&2;4G$X5>}h}aBx3fU|gLy*h>#4O{V@hI-J zc`!FWSF`n17=T3Lbn-@0fadeJgFvRzU_mIf!ZDkc)mnmKuaho38d8CV=>}fm@p^g+ zwGHCoZWg`TSj6;l;|ql=n%`JE>4IEZ%Di}sbZOtvm_i6-52U;<+3g3XXGUuvrhrh+ zLJ)_bSr}GG6}3Lk4Y=H2+=0Q5;YC^u5-%q_LtEBuGo@z$NiN(vz_ICIypEoKk@O@Q z!i^6@lzSQBX3$Q6mHmQyma$QgVpAwmUh-h6hPvy)Q1DvFC`cyof&U2(*_#@qR{xv^ zE%#6)nb}pC(qPTTRriby#?Cb#6AXQsO>`@8bw$V~0k?yf*APC-z`WdyT2tjDO-*#f z=0cum)eD>IT}I`3M6GplG-r@$l?)gBI}W~{$ZgkA+(Y%rT4H(aJ}RZ?_je|hhDr7)d5QlS-KluVF}#TA7g2<$~L_CImEGw_4Qy1 zR7l%mKl^jJDqC=`r?hQ>HXWu4OQ+lyZLYwD@+wAwguC@DYL&y;vZmM7c8H2q6ua*f zs55K9=Y$nawhPSlBpoS?{Md?cDs-A#WSzTIS#rFT8hP%dUiz} z+~9-c)xMcLqvh4s*`uXXa60bVdvmjA08@Z(q^#rb-jH)URYgdkpV4Iy9-b1SNY&Hf zeu4kEOs*50oHZ*W*d!@Piyu1H&MNYnFLX;23NZ0wNL==`^*JAU*5H}SL@$pRCcQSc zZ~5VfJLG|ufJHCUD=2DY6elOc`uE{>?&VW&$}NyYqe=8B<2Gh3FHl3GVxbxGw8^Sk zD8+Up!vTa58XtFLH5VsV(9m5t@L&Mc&No}QVD<8`AEFQny`PzPL=3d=QX0&*ef440 zDBs=x07EG|U!pVBJ_90FExgG%2#WhMpiXsr^KuTdTh0JE9AVuq8aJr2KF+$G)(a&f z9Crtm_Kch&5mU}^NY5$?r^^4$UWUnbe%gM!nBya=$hS-~S_9IKh96?Q0_5Rc&bKWz z^fBtN$=1Eou}>C~L+Em2leuJq+Tpj%TRQ4PaHI?2jOME|`7L)t)CPKJ7G25n-C5f&v?Xv6 z8SEH~oXdxAVNv0z#mKI=enQ~ac7xhN-)`=NF=AH#ku`c^Y*OeQjI&{Ad`W_hxOP%) zq!WDkn;7Kt71SE{+;GNyUo=&E2?3DzYCC7lqQOQ6#n{-ouNAv@VuG<`sWAX#htpcw z432WmJRM@hqJ05tn|%>q;4k!+RPb%atabXAB0yVRLnB4j%k;auf?F$EOGyicUPaU( zFY z+;*KXt!Vp`ok6IaM4M{xZ12RNOQS&Sn=|$Se@%vl)dZM*sRkM2~fsjH^ zWA?Z0Q(<#)GAKc{W)>Yg+Y#%inh|fzWwMZm{xdPgi!0Y z9|&;BOwW?cLu+Q>S()6^6bayf>KBLI6ZvJ7L~}NBvmYO2|J26_@b~7A6kvJ3V24Z zG-&}rh3`JR!OQm|-STJ>rB}VD z=f%r2+7+4zc{8bWL+k<#9!{1w?A2USWmR;xc;=!OC z>0TJcR+YN;G_RwUS3#xv(&qN;yq$fEmhMBs))+4;hY3vN$3^voDf3`z;z9BLJ#!NxjHRK_HW*aIjb?qWOfA^E?yBTN%pY91GUuX*)a@tdpkvn+7P^2W^6Gl) z)u{pr6uq?hP9$alG)U%gvrUQGcrNi^dA<@O=|;?Mkp#Mqo^BOMo4OTi2!!-ls4BDd z;k;7;_sAoDvDQujOl-@<=h^)bq?O8GRhzSBH;ytv$hGNqEFJ zV#e(75sT~MT@`I@d#$lrdO6cZCx~(dwnahfu$ibG;DO`t0>+Xro%2doy1}Tu`Cp6(#^Kbiz3Y*xPtZO9-(i$@6z}0Q?$T}bn@`|+YCq0*Q9t^yGfZjT!9)U@=3{O+(?aXt&~5RlGPr4hADg9N*4Wi7YOwO zA2z3be%90l@bZfKR$E#IM#L~XXJV%UWb(NTn22vomY^>&$4M##6TCjjtV!I}4$g}y z-{ebAfdi*UBYPc}vVuHWBOtDnA6w0>PdyS}_2771!ZWdPKQdTT6fjM6${jf%$9l-J z5;-sVP;0nyZd2=!P<2LIzOL0(aCOvCmFJ;j=15ew|Mo-u55{k9K<_^U-C$*Ie@EuU^lA1k@%1Zw$#atS7SD1oi-GCVHX*$uLlg9 z1H94UIZ$|Xrhp<=c?uZ6Jb3jx;;Kloxa_y&McCObS~6pzUe~gX6l{ont9B;1eTv&* zjr3846WrPw;H9l{vQ&7q!*oj*OB4$y;Qk%xkO)~|O+x6DsH1raI~}SM0g`}dw;WE` zD;pQCOcy8Dc~_}w66$=z67XXJ`jKY!-hQUw=ja)g?Vv)8su-q(0&4b6#kCe@$&rBp z0<_db%tXzZI+f3WO&}m7Ehp2LbxTxui>fab@@|TIUff#KH)4#~42#ia90~>WJncyX zonCj82T~*^Hh_wXuRsxlp`H|TRN>5^8lpinhYOS13o$2-dx2GSky*|qUQ^k-$NIF= zpfiU#nV&u@Y{h~d%7o`l1KegBsjFi>o=jfXF?W4JhY@5}-#O=t2hj}gc{}Z{0n&Vr zo#7%KGE0u+&9}V$9O4OjXv;C)ga-*tWrlSIk#Q5+64I!JME2|EgQ^4hb8hu0k4L_I zp~jf%IAF!%pchtqF*0AUH_*1upF|wkt6Xs{jPB*PwR{(3!k-!CM z>tVWNSl%RdQ16sHvV5Yi!~m_sP_I6U4oQ^(T%OZuTgG(>8*h7FqK?&2nv$Gc{1F&& zSiL9ht>65rw?X2@gU(fG)Ua^N>Jm)K=U0+v*!5Kr93hwWwX$8gM=;k9&) z$TBWHCnn5-+GVGN*YH?dcwg2bmlB2QIZ;iqP3zov+h}veOLz95kt_DS>!AEOmzS*< zE#b34gL(o>I~>t5|0+0JrG2*s5tKE3nzA0J_*A; z(|knU-7DaATG#EpxRZ)>oQM*}qstMavZFTLqaoWKPyV41tqzw+4ZL$BMFaoe^NJK>G3&96C=>X(Om&1g`C(^i=}LYnfyR#B)d##uMw$T`nhW*#sV?Ax36Kp~gJ zJTTX#l^t{JLAMgDEK#Bb7)kz^c8HzE_t60$zEI6Fftp$>^`nGrBlybB#rUD`5=3(x z!X}s@`6)Wf3}|OPJi?8Yt*2Y)oLFqv_zL!=)X~PN?)(5<+DF`LK82}5KdE8@Ra6OI zViC+21IU1?2&kw=u+RHLltQ=#)Fhhh3Tq8!BF{7tEKESV&6l!)^@9;nr%=(l zRvj9k{i;~xI5Bcjo?*16YPBXWHFFa^3cjS39YueAE=s|2!J+9(-Ww@4*xRf`&2J7L zEYesN0;6qVZk&3qH?ctLFA{|)X;_mSTZ>XKN9|B6&R2oRA!_ak9E}x%z>T*oW#buj zYU6NqI=M*GjHRm^kyjTT&t~Tg6R$dcSH99W8I!8h;dY7pI6+GH{3$Y-f`5@f6`WE2 zI=aCiU=zO;27_v>d~Ungu(43JV~7A^2^^I>xTVBbCqv zIq=GOsxXNUTM8SF2{CgVu3BKDIk|Cm7aojL;tBdT%Vy4W6sWw-2pUG4;X9sUuLBAs z5GPu6$}WMkddwd}J3iM(hu!9tASvi<&_Z}tSHt>l;aR$oPUw3g)-${YJgs+6c~iF< zmKl_MimuBzf?^En(F%y$E{+rDB^BG`3Lqsn5NiaKpd6nVBnzVVYt7N`VM%TAmfNE7 zHEVWDZ(Jw9R}fo2Ip}s4ml8*r!2{vyqjr3$%ZseB$x5x&E?OpJVOPFI1niSD)|LgU zEU&x^&I)Jk!(A+Pejt8DIksI4X(&YjNyNU~MDgauAVt5%#gw*c>ZO5dK}RX)LN~zh zW50s_V>fym3_zx8D3mH7;940{l%Z1L6oKjmXNw{`vei!QgTd`3i|U-=2&ytOU>7N? zX9puKRaHZ+Vql1gX+^_%a7jxczL9{Z z)<+-cbUr3M#(v*UGY5&b8??%K|K`KZEaxkJ{x^#ByBN8rmKGwtOmypL8n|$ zFp^N?+?_W5Y)b)u%#Ofm5M9=3y#g(^r;u8z8(NXqgZ({RJ;hj^-*cN(`2%o)XZ}I( zPkQjB@cRu5`A63JUpI#+8v)Twc`FGH1{Rc01POAohsN||kP}BA@uxE=qIS6_h-%ez z)I55u{Ln@dUu}k(=i=<0bQU^h{*C+87n4h{anD#oKB+FP{A^4a-j#4st7fTrldK5wzQ%m~KWt2?h{I9=6q z+BEsPuUm7v;hVdSCG5~RW4inX39pLvj?QMc@+UA)&9u!4)eDk|por?aDXrv`9%N5K zT1!j9>6R-yNjj#{yom-neW5H$xZ&L~%2b`9$HKLqtl=NhEeBdNP$=IDx4icTRkbc> z9$;2}l`}clDpH~otI#vM?=@+G=JI^<6vo4rr>85kf}$#*&}&JWsbJjdL5hu_S&aJe z`5yZQ^U_C}2Q@D}r?JZbMT7RBaI)33W^V!Op+A^F-y+S_tbQb4N||<3l@7v~BO#=5 zKtMUCm;h>SS%Q3ur^)SOD-$pOp2-ZFXij?i6?!k*IJ(GqWAy@dB1J4N9;j{6aYV!* z-Z&0dEa%*YbF7xn0%zl<9=JTbM4>%LSse^<-(=@oFb?u1!}zGF7DHABy0f1Xn06i*Kv6Tm6cSCaGJ3^HwO168;&IORL9ioR2_Y$T!L*Wcdn+T&dqs-p4iy9|^AQU4h&RgA?_2WpS6gae|SIbeimz3ig%Yy_TTNJVg6nM6@>YPq=jj%jsC4{ z$XKyMX7R3U=!#0k11%Dtr6k9a*jOzl7jYUrwW$gAzFD?-;m4-B^Lgk%Lfcp&Cq zyra)1%X+50DlHI(!`{tN#=P~~#3byEDLQqVNlb|W2Em3tJ}PK378chEwqZsbuHb6< zQM=1y?j7NPcMYX^=7sOl9hA}pb{!Gd`>6v|#`H|hj>P;Kz4N9na{$MRBLOTxTD6y_ z>e47rwV(LZ7O_+elZgdE?PX-KK8UsHmiOc?DAbU(z=1~Z+qS3aTDQM53<1Jz0iTt4ATC$us2iUAXf zA8_;#=iTBjg?H+QUS(a}oz=hJZh_zg5TS|9A~E(C;>*JWn-9S%SrL7bIk+E^kA=3o z2AhQ$y`+a5f*w#5DhW?{tAZ2aJzU{IoT^Xh7>;Vv5bpd+0-B_$Zo`+3`XD`P#nR<% zS#NV+XcwYi{xXxq*K zr9;t+`K2CHzpH`eI@RemRFbg9s$Awd5wUx4HZD!TNiaeX7!+ z`C9cyV`XkY>tSy9*PPSnF)?wv`+TSTIY~euT;Tup|L-0+ z{q+MLV4wff7oS@L1pqex@6Du~B9m_g}*MGTz^vPxr_BXhbHF?@n=u3+U;0Z}Ct6@)MiCig5ob zQT@#57pPF+X7JJ8xt{P{rG&seD$RGM`gJP5YZ7U#fl8CR0b0M4g!10wVR9$P`gIgmc$^Qv9005uDqAupw zzR`Sgu-|eb+`qYgZZq${+Wd#-{uTz|J&cb(#4yq~`7IpsdpMd{|Fq9P`|=6ruh)D0 z78>jb`eb;`dH_zFw+;LPkpWZNu>V=UA!NI>AHW^#ZQj?J8Kl#mkxe1W#~`ge9At43+(=6-TQg4 zpBcdKyCd_x{wenSj2-{#-)BfiX9FX1haYtI>(m($r_0W{%QcVhG7J7M$e*T8$8REk zO80)!SH9Btb`7}it*gDiYJk61p`T>%{UMbKi)CX-~V+c*2Yfy zpE4C%3rAa#9!|JdFywV zh5cX#e!t)MJul!_AwPHe|CImTX8_Lhi=F<=;3u=8pRqxR(r+>N$>{Ty!TtN{KA#iFNG@Lx4H zKWB;idfjhntfu`Ajqj*;e~!p~t>L#sO0#~R$WI5EudZ-kyZ0^dboS2!|8FJV&vpO4 z?CDz;g!w list[tuple]: input_dir = os.path.join(basedir, "input") input_files = get_files_in_folder(input_dir, ".zip") input_files = [(name, binary) for name, binary in input_files.items()] - expected_metadata_list = [{'number of rows': 2}, {'number of rows': 52}, {}] + expected_metadata_list = [{'number of rows': 2}, {'number of rows': 20}, {'number of rows': 52}, {}] config = { ingest_supported_langs_file_key: lang_supported_file, ingest_detect_programming_lang_key: True,