Skip to content

Commit e5b6dba

Browse files
committed
use packages_to_install for kfp spec
Signed-off-by: Humair Khan <[email protected]>
1 parent c92c2a6 commit e5b6dba

17 files changed

+143
-113
lines changed

samples/v2/sample_test.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,7 @@ def get_package_path(subdir: str) -> str:
4848

4949
# Set the component configuration BEFORE importing any pipeline modules
5050
dsl.component = functools.partial(
51-
dsl.component, kfp_package_path=get_kfp_package_path())
52-
53-
# Ensure that we are installing pipeline-spec from source during pipeline execution.
54-
if 'KFP_PIPELINE_SPEC_PACKAGE_PATH' not in os.environ:
55-
os.environ['KFP_PIPELINE_SPEC_PACKAGE_PATH'] = get_kfp_pipeline_spec_path()
51+
dsl.component, kfp_package_path=get_kfp_package_path(), packages_to_install=[get_kfp_pipeline_spec_path()])
5652

5753
# Now import the pipeline modules, this way we can leverage the kfp_package and pipeline
5854
# spec defined above

sdk/python/kfp/dsl/component_factory.py

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import dataclasses
1515
import inspect
1616
import itertools
17-
import os
1817
import pathlib
1918
import re
2019
import textwrap
@@ -144,8 +143,6 @@ def make_pip_install_command(
144143
. "$tmp/venv/bin/activate"
145144
'''
146145

147-
_KFP_PIPELINE_SPEC_PACKAGE_PATH = "KFP_PIPELINE_SPEC_PACKAGE_PATH"
148-
149146
def _get_packages_to_install_command(
150147
kfp_package_path: Optional[str] = None,
151148
pip_index_urls: Optional[List[str]] = None,
@@ -167,17 +164,17 @@ def _get_packages_to_install_command(
167164
index_url_options = make_index_url_options(pip_index_urls,
168165
pip_trusted_hosts)
169166

170-
# Setting pipeline spec path is not intended to be public api and
171-
# is largely intended for testing and development purposes to
172-
# allow pipeline runtime execution to install pipeline spec from
173-
# development branches and pull request CIs.
174-
pipeline_spec_path = os.getenv(_KFP_PIPELINE_SPEC_PACKAGE_PATH)
175-
if pipeline_spec_path:
176-
kfp_pipeline_spec_install_command = make_pip_install_command(
177-
install_parts=[pipeline_spec_path],
178-
index_url_options=index_url_options
167+
# Install packages before KFP. This allows us to
168+
# control where we source kfp-pipeline-spec.
169+
# This is particularly useful for development and
170+
# CI use-case when you want to install the spec
171+
# from source.
172+
if packages_to_install:
173+
user_packages_pip_install_command = make_pip_install_command(
174+
install_parts=packages_to_install,
175+
index_url_options=index_url_options,
179176
)
180-
pip_install_strings.append(kfp_pipeline_spec_install_command)
177+
pip_install_strings.append(user_packages_pip_install_command)
181178
if inject_kfp_install:
182179
pip_install_strings.append(' && ')
183180

@@ -200,16 +197,6 @@ def _get_packages_to_install_command(
200197
)
201198
pip_install_strings.append(kfp_pip_install_command)
202199

203-
if packages_to_install:
204-
pip_install_strings.append(' && ')
205-
206-
if packages_to_install:
207-
user_packages_pip_install_command = make_pip_install_command(
208-
install_parts=packages_to_install,
209-
index_url_options=index_url_options,
210-
)
211-
pip_install_strings.append(user_packages_pip_install_command)
212-
213200
return [
214201
'sh', '-c',
215202
_install_python_packages_script_template.format(

sdk/python/kfp/dsl/component_factory_test.py

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,18 @@ def test_with_user_packages_to_install_and_no_pip_index_url(self):
132132
self.assertEqual(
133133
strip_kfp_version(command),
134134
strip_kfp_version([
135-
'sh', '-c',
136-
'\nif ! [ -x "$(command -v pip)" ]; then\n python3 -m ensurepip || python3 -m ensurepip --user || apt-get install python3-pip\nfi\n\nPIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location \'kfp==2.1.3\' \'--no-deps\' \'typing-extensions>=3.7.4,<5; python_version<"3.9"\' && python3 -m pip install --quiet --no-warn-script-location \'package1\' \'package2\' && "$0" "$@"\n'
135+
'sh',
136+
'-c',
137+
'\n'
138+
'if ! [ -x "$(command -v pip)" ]; then\n'
139+
' python3 -m ensurepip || python3 -m ensurepip --user || apt-get install '
140+
'python3-pip\n'
141+
'fi\n'
142+
'\n'
143+
'PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet '
144+
"--no-warn-script-location 'package1' 'package2' && python3 -m pip install "
145+
"--quiet --no-warn-script-location kfp '--no-deps' "
146+
'\'typing-extensions>=3.7.4,<5; python_version<"3.9"\' && "$0" "$@"\n'
137147
]))
138148

139149
def test_with_packages_to_install_with_pip_index_url(self):
@@ -148,8 +158,21 @@ def test_with_packages_to_install_with_pip_index_url(self):
148158
self.assertEqual(
149159
strip_kfp_version(command),
150160
strip_kfp_version([
151-
'sh', '-c',
152-
'\nif ! [ -x "$(command -v pip)" ]; then\n python3 -m ensurepip || python3 -m ensurepip --user || apt-get install python3-pip\nfi\n\nPIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location --index-url https://myurl.org/simple --trusted-host https://myurl.org/simple \'kfp==2.1.3\' \'--no-deps\' \'typing-extensions>=3.7.4,<5; python_version<"3.9"\' && python3 -m pip install --quiet --no-warn-script-location --index-url https://myurl.org/simple --trusted-host https://myurl.org/simple \'package1\' \'package2\' && "$0" "$@"\n'
161+
'sh',
162+
'-c',
163+
'\n'
164+
'if ! [ -x "$(command -v pip)" ]; then\n'
165+
' python3 -m ensurepip || python3 -m ensurepip --user || apt-get install '
166+
'python3-pip\n'
167+
'fi\n'
168+
'\n'
169+
'PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet '
170+
'--no-warn-script-location --index-url https://myurl.org/simple '
171+
"--trusted-host https://myurl.org/simple 'package1' 'package2' && python3 "
172+
'-m pip install --quiet --no-warn-script-location --index-url '
173+
'https://myurl.org/simple --trusted-host https://myurl.org/simple kfp '
174+
'\'--no-deps\' \'typing-extensions>=3.7.4,<5; python_version<"3.9"\' && "$0" '
175+
'"$@"\n'
153176
]))
154177

155178
def test_with_packages_to_install_with_pip_index_url_and_trusted_host(self):
@@ -166,8 +189,20 @@ def test_with_packages_to_install_with_pip_index_url_and_trusted_host(self):
166189
self.assertEqual(
167190
strip_kfp_version(command),
168191
strip_kfp_version([
169-
'sh', '-c',
170-
'\nif ! [ -x "$(command -v pip)" ]; then\n python3 -m ensurepip || python3 -m ensurepip --user || apt-get install python3-pip\nfi\n\nPIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location --index-url https://myurl.org/simple --trusted-host myurl.org \'kfp==2.1.3\' \'--no-deps\' \'typing-extensions>=3.7.4,<5; python_version<"3.9"\' && python3 -m pip install --quiet --no-warn-script-location --index-url https://myurl.org/simple --trusted-host myurl.org \'package1\' \'package2\' && "$0" "$@"\n'
192+
'sh',
193+
'-c',
194+
'\n'
195+
'if ! [ -x "$(command -v pip)" ]; then\n'
196+
' python3 -m ensurepip || python3 -m ensurepip --user || apt-get install '
197+
'python3-pip\n'
198+
'fi\n'
199+
'\n'
200+
'PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet '
201+
'--no-warn-script-location --index-url https://myurl.org/simple '
202+
"--trusted-host myurl.org 'package1' 'package2' && python3 -m pip install "
203+
'--quiet --no-warn-script-location --index-url https://myurl.org/simple '
204+
"--trusted-host myurl.org kfp '--no-deps' 'typing-extensions>=3.7.4,<5; "
205+
'python_version<"3.9"\' && "$0" "$@"\n'
171206
]))
172207

173208
def test_with_packages_to_install_with_pip_index_url_and_empty_trusted_host(
@@ -183,10 +218,23 @@ def test_with_packages_to_install_with_pip_index_url_and_empty_trusted_host(
183218

184219
self.assertEqual(
185220
strip_kfp_version(command),
186-
strip_kfp_version([
187-
'sh', '-c',
188-
'\nif ! [ -x "$(command -v pip)" ]; then\n python3 -m ensurepip || python3 -m ensurepip --user || apt-get install python3-pip\nfi\n\nPIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location --index-url https://myurl.org/simple \'kfp==2.1.3\' \'--no-deps\' \'typing-extensions>=3.7.4,<5; python_version<"3.9"\' && python3 -m pip install --quiet --no-warn-script-location --index-url https://myurl.org/simple \'package1\' \'package2\' && "$0" "$@"\n'
189-
]))
221+
strip_kfp_version(
222+
[
223+
'sh',
224+
'-c',
225+
'\n'
226+
'if ! [ -x "$(command -v pip)" ]; then\n'
227+
' python3 -m ensurepip || python3 -m ensurepip --user || apt-get install '
228+
'python3-pip\n'
229+
'fi\n'
230+
'\n'
231+
'PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet '
232+
"--no-warn-script-location --index-url https://myurl.org/simple 'package1' "
233+
"'package2' && python3 -m pip install --quiet --no-warn-script-location "
234+
"--index-url https://myurl.org/simple kfp '--no-deps' "
235+
'\'typing-extensions>=3.7.4,<5; python_version<"3.9"\' && "$0" "$@"\n'
236+
]
237+
))
190238

191239

192240
class TestInvalidParameterName(unittest.TestCase):

sdk/python/kfp/local/pipeline_orchestrator_test.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
"""Tests for pipeline_orchestrator.py."""
15-
15+
import functools
1616
import io as stdlib_io
1717
import os
1818
from typing import NamedTuple
@@ -31,16 +31,11 @@
3131
from kfp.local import testing_utilities
3232

3333
ROOT_FOR_TESTING = './testing_root'
34+
CURRENT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
35+
kfp_pipeline_spec_path = os.path.join(CURRENT_DIR, 'api', 'v2alpha1', 'python')
3436

35-
@pytest.fixture(autouse=True)
36-
def set_env_for_test_classes(monkeypatch, request):
37-
root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
38-
# Only apply to specific classes
39-
if request.cls.__name__ in {
40-
"TestRunLocalPipeline",
41-
"TestFstringContainerComponent",
42-
}:
43-
monkeypatch.setenv("KFP_PIPELINE_SPEC_PACKAGE_PATH", os.path.join(root, 'api', 'v2alpha1', 'python'))
37+
dsl.component = functools.partial(
38+
dsl.component, packages_to_install=[kfp_pipeline_spec_path])
4439

4540

4641
class TestRunLocalPipeline(testing_utilities.LocalRunnerEnvironmentTestCase):
@@ -88,7 +83,7 @@ def my_pipeline():
8883
def test_no_io(self):
8984
local.init(local.SubprocessRunner(), pipeline_root=ROOT_FOR_TESTING)
9085

91-
@dsl.component
86+
@dsl.component()
9287
def pass_op():
9388
pass
9489

@@ -721,5 +716,6 @@ def my_pipeline(string: str = 'baz') -> str:
721716
task = my_pipeline()
722717
self.assertEqual(task.output, 'foo-bar-baz')
723718

719+
724720
if __name__ == '__main__':
725721
unittest.main()

sdk/python/kfp/local/subprocess_task_handler_test.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
# limitations under the License.
1414
"""Tests for subprocess_local_task_handler.py."""
1515
import contextlib
16+
import functools
1617
import io
1718
import os
1819
from typing import NamedTuple, Optional
1920
import unittest
2021
from unittest import mock
2122

22-
import pytest
2323
from absl.testing import parameterized
2424
from kfp import dsl
2525
from kfp import local
@@ -36,18 +36,11 @@
3636
# impact of such an error we should not install into the main test process'
3737
# environment.
3838

39-
@pytest.fixture(autouse=True)
40-
def set_env_for_test_classes(monkeypatch, request):
41-
root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
42-
# Only apply to specific classes
43-
if request.cls.__name__ in {
44-
"TestSubprocessRunner",
45-
"TestRunLocalSubproces",
46-
"TestUseCurrentPythonExecutable",
47-
"TestUseVenv",
48-
"TestLightweightPythonComponentLogic"
49-
}:
50-
monkeypatch.setenv("KFP_PIPELINE_SPEC_PACKAGE_PATH", os.path.join(root, 'api', 'v2alpha1', 'python'))
39+
CURRENT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
40+
kfp_pipeline_spec_path = os.path.join(CURRENT_DIR, 'api', 'v2alpha1', 'python')
41+
42+
dsl.component = functools.partial(
43+
dsl.component, packages_to_install=[kfp_pipeline_spec_path])
5144

5245
class TestSubprocessRunner(testing_utilities.LocalRunnerEnvironmentTestCase):
5346

@@ -99,7 +92,7 @@ def comp():
9992
def test_cannot_run_containerized_python_component(self):
10093
local.init(runner=local.SubprocessRunner(use_venv=True))
10194

102-
@dsl.component(target_image='foo')
95+
@dsl.component(target_image='foo', packages_to_install=[])
10396
def comp():
10497
pass
10598

@@ -152,7 +145,7 @@ class TestUseVenv(testing_utilities.LocalRunnerEnvironmentTestCase):
152145
def test_use_venv_true(self, **kwargs):
153146
local.init(**kwargs)
154147

155-
@dsl.component(packages_to_install=['cloudpickle'])
148+
@dsl.component(packages_to_install=[kfp_pipeline_spec_path, 'cloudpickle'])
156149
def installer_component():
157150
import cloudpickle
158151
print('Cloudpickle is installed:', cloudpickle)

sdk/python/kfp/local/task_dispatcher_test.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
irrespective of the runner. While there will inevitably some overlap, we
2020
should seek to minimize it.
2121
"""
22+
import functools
2223
import io
2324
import os
2425
import re
2526
import unittest
2627
from unittest import mock
2728

28-
import pytest
2929
from absl.testing import parameterized
3030
from kfp import dsl
3131
from kfp import local
@@ -42,18 +42,11 @@
4242
# impact of such an error we should not install into the main test process'
4343
# environment.
4444

45-
@pytest.fixture(autouse=True)
46-
def set_env_for_test_classes(monkeypatch, request):
47-
root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
48-
# Only apply to specific classes
49-
if request.cls.__name__ in {
50-
"TestLocalExecutionValidation",
51-
"TestSupportOfComponentTypes",
52-
"TestSupportOfComponentTypes",
53-
"TestExceptionHandlingAndLogging",
54-
"TestPipelineRootPaths"
55-
}:
56-
monkeypatch.setenv("KFP_PIPELINE_SPEC_PACKAGE_PATH", os.path.join(root, 'api', 'v2alpha1', 'python'))
45+
CURRENT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
46+
kfp_pipeline_spec_path = os.path.join(CURRENT_DIR, 'api', 'v2alpha1', 'python')
47+
48+
dsl.component = functools.partial(
49+
dsl.component, packages_to_install=[kfp_pipeline_spec_path])
5750

5851
class TestLocalExecutionValidation(
5952
testing_utilities.LocalRunnerEnvironmentTestCase):

sdk/python/test_data/components/component_with_pip_install.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
import os
15+
1416
from kfp.dsl import component
1517

1618

19+
PACKAGES_TO_INSTALL=['yapf']
20+
if 'KFP_PIPELINE_SPEC_PACKAGE_PATH' in os.environ:
21+
PACKAGES_TO_INSTALL.append(os.environ['KFP_PIPELINE_SPEC_PACKAGE_PATH'])
22+
1723
@component(
18-
pip_index_urls=['https://pypi.org/simple'], packages_to_install=['yapf'])
24+
pip_index_urls=['https://pypi.org/simple'], packages_to_install=PACKAGES_TO_INSTALL)
1925
def component_with_pip_install():
2026
import yapf
2127
print(dir(yapf))

sdk/python/test_data/components/component_with_pip_install.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ deploymentSpec:
1818
- "\nif ! [ -x \"$(command -v pip)\" ]; then\n python3 -m ensurepip ||\
1919
\ python3 -m ensurepip --user || apt-get install python3-pip\nfi\n\nPIP_DISABLE_PIP_VERSION_CHECK=1\
2020
\ python3 -m pip install --quiet --no-warn-script-location --index-url https://pypi.org/simple\
21-
\ --trusted-host https://pypi.org/simple 'kfp==2.13.0' '--no-deps' 'typing-extensions>=3.7.4,<5;\
22-
\ python_version<\"3.9\"' && python3 -m pip install --quiet --no-warn-script-location\
23-
\ --index-url https://pypi.org/simple --trusted-host https://pypi.org/simple\
24-
\ 'yapf' && \"$0\" \"$@\"\n"
21+
\ --trusted-host https://pypi.org/simple 'yapf' && python3 -m pip install\
22+
\ --quiet --no-warn-script-location --index-url https://pypi.org/simple\
23+
\ --trusted-host https://pypi.org/simple 'kfp==2.14.0' '--no-deps' 'typing-extensions>=3.7.4,<5;\
24+
\ python_version<\"3.9\"' && \"$0\" \"$@\"\n"
2525
- sh
2626
- -ec
2727
- 'program_path=$(mktemp -d)
@@ -50,4 +50,4 @@ root:
5050
name: component-with-pip-install
5151
taskName: component-with-pip-install
5252
schemaVersion: 2.1.0
53-
sdkVersion: kfp-2.13.0
53+
sdkVersion: kfp-2.14.0

sdk/python/test_data/components/component_with_pip_install_in_venv.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
import os
15+
1416
from kfp.dsl import component
1517

1618

19+
PACKAGES_TO_INSTALL=['yapf']
20+
if 'KFP_PIPELINE_SPEC_PACKAGE_PATH' in os.environ:
21+
PACKAGES_TO_INSTALL.append(os.environ['KFP_PIPELINE_SPEC_PACKAGE_PATH'])
22+
1723
@component(
1824
pip_index_urls=["https://pypi.org/simple"],
19-
packages_to_install=["yapf"],
25+
packages_to_install=[PACKAGES_TO_INSTALL],
2026
use_venv=True,
2127
)
2228
def component_with_pip_install():

sdk/python/test_data/pipelines/component_with_pip_index_urls.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,18 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
import os
1415

1516
from kfp import compiler
1617
from kfp import dsl
1718
from kfp.dsl import component
1819

20+
PACKAGES_TO_INSTALL=['yapf']
21+
if 'KFP_PIPELINE_SPEC_PACKAGE_PATH' in os.environ:
22+
PACKAGES_TO_INSTALL.append(os.environ['KFP_PIPELINE_SPEC_PACKAGE_PATH'])
1923

2024
@component(
21-
pip_index_urls=['https://pypi.org/simple'], packages_to_install=['yapf'])
25+
pip_index_urls=['https://pypi.org/simple'], packages_to_install=PACKAGES_TO_INSTALL)
2226
def component_op():
2327
import yapf
2428
print(dir(yapf))

0 commit comments

Comments
 (0)