prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  [sdk] Containerized Python Component module not found error 
  There is a bug when building a containerized Python component that happens (at least) in the case when the longest path of the import graph ending at the component involves >2 modules. 
  
  ### Environment
  KFP SDK 2.0.0-beta.6
  
  ### Steps to reproduce
  For example:
  
  ```python
  # component.py
  from module_one import one
  from kfp import dsl
  
  @dsl.component
  def comp(): ...
  ```
  
  ```python
  # module_one.py
  from module_two import two
  one = 1
  ```
  
  ```python
  # module_two.py
  two = 2
  ```
  
  Then: `kfp component build .`
  
  You get a `No module named` error.
  
  ### Expected result
  
  Should build without an error.
  
  ### Materials and Reference
  Related: https://github.com/kubeflow/pipelines/issues/8353
  
  </issue>
  <code>
  [start of sdk/python/kfp/components/utils.py]
  1 # Copyright 2021 The Kubeflow Authors
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #      http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 """Definitions of utils methods."""
  15 
  16 import importlib
  17 import os
  18 import re
  19 import sys
  20 import types
  21 from typing import List
  22 
  23 _COMPONENT_NAME_PREFIX = 'comp-'
  24 _EXECUTOR_LABEL_PREFIX = 'exec-'
  25 
  26 
  27 def load_module(module_name: str, module_directory: str) -> types.ModuleType:
  28     """Dynamically imports the Python module with the given name and package
  29     path.
  30 
  31     E.g., Assuming there is a file called `my_module.py` under
  32     `/some/directory/my_module`, we can use::
  33 
  34         load_module('my_module', '/some/directory')
  35 
  36     to effectively `import mymodule`.
  37 
  38     Args:
  39         module_name: The name of the module.
  40         package_path: The package under which the specified module resides.
  41     """
  42     module_spec = importlib.util.spec_from_file_location(
  43         name=module_name,
  44         location=os.path.join(module_directory, f'{module_name}.py'))
  45     module = importlib.util.module_from_spec(module_spec)
  46     sys.modules[module_spec.name] = module
  47     module_spec.loader.exec_module(module)
  48     return module
  49 
  50 
  51 def maybe_rename_for_k8s(name: str) -> str:
  52     """Cleans and converts a name to be k8s compatible.
  53 
  54     Args:
  55       name: The original name.
  56 
  57     Returns:
  58       A sanitized name.
  59     """
  60     return re.sub('-+', '-', re.sub('[^-0-9a-z]+', '-',
  61                                     name.lower())).lstrip('-').rstrip('-')
  62 
  63 
  64 def sanitize_input_name(name: str) -> str:
  65     """Sanitizes input name."""
  66     return re.sub('[^_0-9a-z]+', '_', name.lower()).lstrip('_').rstrip('_')
  67 
  68 
  69 def sanitize_component_name(name: str) -> str:
  70     """Sanitizes component name."""
  71     return _COMPONENT_NAME_PREFIX + maybe_rename_for_k8s(name)
  72 
  73 
  74 def sanitize_task_name(name: str) -> str:
  75     """Sanitizes task name."""
  76     return maybe_rename_for_k8s(name)
  77 
  78 
  79 def sanitize_executor_label(label: str) -> str:
  80     """Sanitizes executor label."""
  81     return _EXECUTOR_LABEL_PREFIX + maybe_rename_for_k8s(label)
  82 
  83 
  84 def make_name_unique_by_adding_index(
  85     name: str,
  86     collection: List[str],
  87     delimiter: str,
  88 ) -> str:
  89     """Makes a unique name by adding index.
  90 
  91     The index starts from 2 and increase by 1 until we find a unique name.
  92 
  93     Args:
  94         name: The original name.
  95         collection: The collection of existing names.
  96         delimiter: The delimiter to connect the original name and an index.
  97 
  98     Returns:
  99         A unique name composed of name+delimiter+next index
  100     """
  101     unique_name = name
  102     if unique_name in collection:
  103         for i in range(2, sys.maxsize**10):
  104             unique_name = name + delimiter + str(i)
  105             if unique_name not in collection:
  106                 break
  107     return unique_name
  108 
  109 
  110 def validate_pipeline_name(name: str) -> None:
  111     """Validate pipeline name.
  112 
  113     A valid pipeline name should match ^[a-z0-9][a-z0-9-]{0,127}$.
  114 
  115     Args:
  116         name: The pipeline name.
  117 
  118     Raises:
  119         ValueError if the pipeline name doesn't conform to the regular expression.
  120     """
  121     pattern = re.compile(r'^[a-z0-9][a-z0-9-]{0,127}$')
  122     if not pattern.match(name):
  123         raise ValueError(
  124             'Invalid pipeline name: %s.\n'
  125             'Please specify a pipeline name that matches the regular '
  126             'expression "^[a-z0-9][a-z0-9-]{0,127}$" using '
  127             '`dsl.pipeline(name=...)` decorator.' % name)
  128
  [end of sdk/python/kfp/components/utils.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/sdk/python/kfp/components/utils.py b/sdk/python/kfp/components/utils.py
  --- a/sdk/python/kfp/components/utils.py
  +++ b/sdk/python/kfp/components/utils.py
  @@ -44,6 +44,7 @@
           location=os.path.join(module_directory, f'{module_name}.py'))
       module = importlib.util.module_from_spec(module_spec)
       sys.modules[module_spec.name] = module
  +    sys.path.insert(0, str(module_directory))
       module_spec.loader.exec_module(module)
       return module
  
verification_info: {"golden_diff": "diff --git a/sdk/python/kfp/components/utils.py b/sdk/python/kfp/components/utils.py\n--- a/sdk/python/kfp/components/utils.py\n+++ b/sdk/python/kfp/components/utils.py\n@@ -44,6 +44,7 @@\n         location=os.path.join(module_directory, f'{module_name}.py'))\n     module = importlib.util.module_from_spec(module_spec)\n     sys.modules[module_spec.name] = module\n+    sys.path.insert(0, str(module_directory))\n     module_spec.loader.exec_module(module)\n     return module\n", "issue": "[sdk] Containerized Python Component module not found error \nThere is a bug when building a containerized Python component that happens (at least) in the case when the longest path of the import graph ending at the component involves >2 modules. \r\n\r\n### Environment\r\nKFP SDK 2.0.0-beta.6\r\n\r\n### Steps to reproduce\r\nFor example:\r\n\r\n```python\r\n# component.py\r\nfrom module_one import one\r\nfrom kfp import dsl\r\n\r\n@dsl.component\r\ndef comp(): ...\r\n```\r\n\r\n```python\r\n# module_one.py\r\nfrom module_two import two\r\none = 1\r\n```\r\n\r\n```python\r\n# module_two.py\r\ntwo = 2\r\n```\r\n\r\nThen: `kfp component build .`\r\n\r\nYou get a `No module named` error.\r\n\r\n### Expected result\r\n\r\nShould build without an error.\r\n\r\n### Materials and Reference\r\nRelated: https://github.com/kubeflow/pipelines/issues/8353\n", "before_files": [{"content": "# Copyright 2021 The Kubeflow Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Definitions of utils methods.\"\"\"\n\nimport importlib\nimport os\nimport re\nimport sys\nimport types\nfrom typing import List\n\n_COMPONENT_NAME_PREFIX = 'comp-'\n_EXECUTOR_LABEL_PREFIX = 'exec-'\n\n\ndef load_module(module_name: str, module_directory: str) -> types.ModuleType:\n    \"\"\"Dynamically imports the Python module with the given name and package\n    path.\n\n    E.g., Assuming there is a file called `my_module.py` under\n    `/some/directory/my_module`, we can use::\n\n        load_module('my_module', '/some/directory')\n\n    to effectively `import mymodule`.\n\n    Args:\n        module_name: The name of the module.\n        package_path: The package under which the specified module resides.\n    \"\"\"\n    module_spec = importlib.util.spec_from_file_location(\n        name=module_name,\n        location=os.path.join(module_directory, f'{module_name}.py'))\n    module = importlib.util.module_from_spec(module_spec)\n    sys.modules[module_spec.name] = module\n    module_spec.loader.exec_module(module)\n    return module\n\n\ndef maybe_rename_for_k8s(name: str) -> str:\n    \"\"\"Cleans and converts a name to be k8s compatible.\n\n    Args:\n      name: The original name.\n\n    Returns:\n      A sanitized name.\n    \"\"\"\n    return re.sub('-+', '-', re.sub('[^-0-9a-z]+', '-',\n                                    name.lower())).lstrip('-').rstrip('-')\n\n\ndef sanitize_input_name(name: str) -> str:\n    \"\"\"Sanitizes input name.\"\"\"\n    return re.sub('[^_0-9a-z]+', '_', name.lower()).lstrip('_').rstrip('_')\n\n\ndef sanitize_component_name(name: str) -> str:\n    \"\"\"Sanitizes component name.\"\"\"\n    return _COMPONENT_NAME_PREFIX + maybe_rename_for_k8s(name)\n\n\ndef sanitize_task_name(name: str) -> str:\n    \"\"\"Sanitizes task name.\"\"\"\n    return maybe_rename_for_k8s(name)\n\n\ndef sanitize_executor_label(label: str) -> str:\n    \"\"\"Sanitizes executor label.\"\"\"\n    return _EXECUTOR_LABEL_PREFIX + maybe_rename_for_k8s(label)\n\n\ndef make_name_unique_by_adding_index(\n    name: str,\n    collection: List[str],\n    delimiter: str,\n) -> str:\n    \"\"\"Makes a unique name by adding index.\n\n    The index starts from 2 and increase by 1 until we find a unique name.\n\n    Args:\n        name: The original name.\n        collection: The collection of existing names.\n        delimiter: The delimiter to connect the original name and an index.\n\n    Returns:\n        A unique name composed of name+delimiter+next index\n    \"\"\"\n    unique_name = name\n    if unique_name in collection:\n        for i in range(2, sys.maxsize**10):\n            unique_name = name + delimiter + str(i)\n            if unique_name not in collection:\n                break\n    return unique_name\n\n\ndef validate_pipeline_name(name: str) -> None:\n    \"\"\"Validate pipeline name.\n\n    A valid pipeline name should match ^[a-z0-9][a-z0-9-]{0,127}$.\n\n    Args:\n        name: The pipeline name.\n\n    Raises:\n        ValueError if the pipeline name doesn't conform to the regular expression.\n    \"\"\"\n    pattern = re.compile(r'^[a-z0-9][a-z0-9-]{0,127}$')\n    if not pattern.match(name):\n        raise ValueError(\n            'Invalid pipeline name: %s.\\n'\n            'Please specify a pipeline name that matches the regular '\n            'expression \"^[a-z0-9][a-z0-9-]{0,127}$\" using '\n            '`dsl.pipeline(name=...)` decorator.' % name)\n", "path": "sdk/python/kfp/components/utils.py"}]}