outerbounds 0.3.55rc3__py3-none-any.whl → 0.3.133__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- outerbounds/_vendor/PyYAML.LICENSE +20 -0
- outerbounds/_vendor/__init__.py +0 -0
- outerbounds/_vendor/_yaml/__init__.py +34 -0
- outerbounds/_vendor/click/__init__.py +73 -0
- outerbounds/_vendor/click/_compat.py +626 -0
- outerbounds/_vendor/click/_termui_impl.py +717 -0
- outerbounds/_vendor/click/_textwrap.py +49 -0
- outerbounds/_vendor/click/_winconsole.py +279 -0
- outerbounds/_vendor/click/core.py +2998 -0
- outerbounds/_vendor/click/decorators.py +497 -0
- outerbounds/_vendor/click/exceptions.py +287 -0
- outerbounds/_vendor/click/formatting.py +301 -0
- outerbounds/_vendor/click/globals.py +68 -0
- outerbounds/_vendor/click/parser.py +529 -0
- outerbounds/_vendor/click/py.typed +0 -0
- outerbounds/_vendor/click/shell_completion.py +580 -0
- outerbounds/_vendor/click/termui.py +787 -0
- outerbounds/_vendor/click/testing.py +479 -0
- outerbounds/_vendor/click/types.py +1073 -0
- outerbounds/_vendor/click/utils.py +580 -0
- outerbounds/_vendor/click.LICENSE +28 -0
- outerbounds/_vendor/vendor_any.txt +2 -0
- outerbounds/_vendor/yaml/__init__.py +471 -0
- outerbounds/_vendor/yaml/_yaml.cpython-311-darwin.so +0 -0
- outerbounds/_vendor/yaml/composer.py +146 -0
- outerbounds/_vendor/yaml/constructor.py +862 -0
- outerbounds/_vendor/yaml/cyaml.py +177 -0
- outerbounds/_vendor/yaml/dumper.py +138 -0
- outerbounds/_vendor/yaml/emitter.py +1239 -0
- outerbounds/_vendor/yaml/error.py +94 -0
- outerbounds/_vendor/yaml/events.py +104 -0
- outerbounds/_vendor/yaml/loader.py +62 -0
- outerbounds/_vendor/yaml/nodes.py +51 -0
- outerbounds/_vendor/yaml/parser.py +629 -0
- outerbounds/_vendor/yaml/reader.py +208 -0
- outerbounds/_vendor/yaml/representer.py +378 -0
- outerbounds/_vendor/yaml/resolver.py +245 -0
- outerbounds/_vendor/yaml/scanner.py +1555 -0
- outerbounds/_vendor/yaml/serializer.py +127 -0
- outerbounds/_vendor/yaml/tokens.py +129 -0
- outerbounds/command_groups/apps_cli.py +450 -0
- outerbounds/command_groups/cli.py +9 -5
- outerbounds/command_groups/local_setup_cli.py +249 -33
- outerbounds/command_groups/perimeters_cli.py +231 -33
- outerbounds/command_groups/tutorials_cli.py +111 -0
- outerbounds/command_groups/workstations_cli.py +88 -15
- outerbounds/utils/kubeconfig.py +2 -2
- outerbounds/utils/metaflowconfig.py +111 -21
- outerbounds/utils/schema.py +8 -2
- outerbounds/utils/utils.py +19 -0
- outerbounds/vendor.py +159 -0
- {outerbounds-0.3.55rc3.dist-info → outerbounds-0.3.133.dist-info}/METADATA +17 -6
- outerbounds-0.3.133.dist-info/RECORD +59 -0
- {outerbounds-0.3.55rc3.dist-info → outerbounds-0.3.133.dist-info}/WHEEL +1 -1
- outerbounds-0.3.55rc3.dist-info/RECORD +0 -15
- {outerbounds-0.3.55rc3.dist-info → outerbounds-0.3.133.dist-info}/entry_points.txt +0 -0
@@ -1,17 +1,66 @@
|
|
1
|
+
from outerbounds._vendor import click
|
1
2
|
import json
|
2
3
|
import os
|
3
4
|
import requests
|
4
5
|
from os import path
|
5
|
-
import
|
6
|
+
from typing import Dict, Union
|
7
|
+
import sys
|
8
|
+
|
9
|
+
"""
|
10
|
+
key: perimeter specific URL to fetch the remote metaflow config from
|
11
|
+
value: the remote metaflow config
|
12
|
+
"""
|
13
|
+
CACHED_REMOTE_METAFLOW_CONFIG: Dict[str, Dict[str, str]] = {}
|
14
|
+
|
15
|
+
|
16
|
+
CURRENT_PERIMETER_KEY = "OB_CURRENT_PERIMETER"
|
17
|
+
CURRENT_PERIMETER_URL = "OB_CURRENT_PERIMETER_MF_CONFIG_URL"
|
18
|
+
CURRENT_PERIMETER_URL_LEGACY_KEY = (
|
19
|
+
"OB_CURRENT_PERIMETER_URL" # For backwards compatibility with workstations.
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
def init_config(config_dir, profile) -> Dict[str, str]:
|
24
|
+
global CACHED_REMOTE_METAFLOW_CONFIG
|
25
|
+
config = read_metaflow_config_from_filesystem(config_dir, profile)
|
26
|
+
|
27
|
+
# Either user has an ob_config.json file with the perimeter URL
|
28
|
+
# or the default config on the filesystem has the config URL in it.
|
29
|
+
perimeter_specifc_url = get_perimeter_config_url_if_set_in_ob_config(
|
30
|
+
config_dir, profile
|
31
|
+
) or config.get("OBP_METAFLOW_CONFIG_URL", "")
|
32
|
+
|
33
|
+
if perimeter_specifc_url != "":
|
34
|
+
if perimeter_specifc_url in CACHED_REMOTE_METAFLOW_CONFIG:
|
35
|
+
return CACHED_REMOTE_METAFLOW_CONFIG[perimeter_specifc_url]
|
36
|
+
|
37
|
+
remote_config = init_config_from_url(config_dir, profile, perimeter_specifc_url)
|
38
|
+
remote_config["OBP_METAFLOW_CONFIG_URL"] = perimeter_specifc_url
|
6
39
|
|
40
|
+
CACHED_REMOTE_METAFLOW_CONFIG[perimeter_specifc_url] = remote_config
|
41
|
+
return remote_config
|
42
|
+
|
43
|
+
return config
|
44
|
+
|
45
|
+
|
46
|
+
def init_config_from_url(config_dir, profile, url) -> Dict[str, str]:
|
47
|
+
config = read_metaflow_config_from_filesystem(config_dir, profile)
|
7
48
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
49
|
+
if config is None or "METAFLOW_SERVICE_AUTH_KEY" not in config:
|
50
|
+
raise Exception("METAFLOW_SERVICE_AUTH_KEY not found in config file")
|
51
|
+
|
52
|
+
config_response = requests.get(
|
53
|
+
url,
|
54
|
+
headers={"x-api-key": f'{config["METAFLOW_SERVICE_AUTH_KEY"]}'},
|
12
55
|
)
|
56
|
+
config_response.raise_for_status()
|
57
|
+
remote_config = config_response.json()["config"]
|
58
|
+
return remote_config
|
59
|
+
|
13
60
|
|
61
|
+
def read_metaflow_config_from_filesystem(config_dir, profile) -> Dict[str, str]:
|
14
62
|
config_filename = f"config_{profile}.json" if profile else "config.json"
|
63
|
+
|
15
64
|
path_to_config = os.path.join(config_dir, config_filename)
|
16
65
|
|
17
66
|
if os.path.exists(path_to_config):
|
@@ -19,22 +68,6 @@ def init_config(config_dir="", profile="") -> dict:
|
|
19
68
|
config = json.load(json_file)
|
20
69
|
else:
|
21
70
|
raise Exception("Unable to locate metaflow config at '%s')" % (path_to_config))
|
22
|
-
|
23
|
-
# This is new remote-metaflow config; fetch it from the URL
|
24
|
-
if "OBP_METAFLOW_CONFIG_URL" in config:
|
25
|
-
if config is None or "METAFLOW_SERVICE_AUTH_KEY" not in config:
|
26
|
-
raise Exception("METAFLOW_SERVICE_AUTH_KEY not found in config file")
|
27
|
-
|
28
|
-
config_response = requests.get(
|
29
|
-
config["OBP_METAFLOW_CONFIG_URL"],
|
30
|
-
headers={"x-api-key": f'{config["METAFLOW_SERVICE_AUTH_KEY"]}'},
|
31
|
-
)
|
32
|
-
config_response.raise_for_status()
|
33
|
-
remote_config = config_response.json()["config"]
|
34
|
-
remote_config["METAFLOW_SERVICE_AUTH_KEY"] = config["METAFLOW_SERVICE_AUTH_KEY"]
|
35
|
-
return remote_config
|
36
|
-
|
37
|
-
# Legacy config, use from filesystem
|
38
71
|
return config
|
39
72
|
|
40
73
|
|
@@ -70,3 +103,60 @@ def get_sanitized_url_from_config(config_dir: str, profile: str, key: str) -> st
|
|
70
103
|
|
71
104
|
url_in_config = url_in_config.rstrip("/")
|
72
105
|
return url_in_config
|
106
|
+
|
107
|
+
|
108
|
+
def get_remote_metaflow_config_for_perimeter(
|
109
|
+
origin_token: str, perimeter: str, api_server: str
|
110
|
+
):
|
111
|
+
try:
|
112
|
+
response = requests.get(
|
113
|
+
f"{api_server}/v1/perimeters/{perimeter}/metaflowconfigs/default",
|
114
|
+
headers={"x-api-key": origin_token},
|
115
|
+
)
|
116
|
+
response.raise_for_status()
|
117
|
+
config = response.json()["config"]
|
118
|
+
config["METAFLOW_SERVICE_AUTH_KEY"] = origin_token
|
119
|
+
return config
|
120
|
+
except Exception as e:
|
121
|
+
click.secho(
|
122
|
+
f"Failed to get metaflow config from {api_server}. Error: {str(e)}",
|
123
|
+
fg="red",
|
124
|
+
)
|
125
|
+
sys.exit(1)
|
126
|
+
|
127
|
+
|
128
|
+
def get_ob_config_file_path(config_dir: str, profile: str) -> str:
|
129
|
+
# If OBP_CONFIG_DIR is set, use that, otherwise use METAFLOW_HOME
|
130
|
+
# If neither are set, use ~/.metaflowconfig
|
131
|
+
obp_config_dir = path.expanduser(os.environ.get("OBP_CONFIG_DIR", config_dir))
|
132
|
+
|
133
|
+
ob_config_filename = f"ob_config_{profile}.json" if profile else "ob_config.json"
|
134
|
+
return os.path.expanduser(os.path.join(obp_config_dir, ob_config_filename))
|
135
|
+
|
136
|
+
|
137
|
+
def get_perimeter_config_url_if_set_in_ob_config(
|
138
|
+
config_dir: str, profile: str
|
139
|
+
) -> Union[str, None]:
|
140
|
+
file_path = get_ob_config_file_path(config_dir, profile)
|
141
|
+
|
142
|
+
if os.path.exists(file_path):
|
143
|
+
with open(file_path, "r") as f:
|
144
|
+
ob_config = json.loads(f.read())
|
145
|
+
|
146
|
+
if CURRENT_PERIMETER_URL in ob_config:
|
147
|
+
return ob_config[CURRENT_PERIMETER_URL]
|
148
|
+
elif CURRENT_PERIMETER_URL_LEGACY_KEY in ob_config:
|
149
|
+
return ob_config[CURRENT_PERIMETER_URL_LEGACY_KEY]
|
150
|
+
else:
|
151
|
+
raise ValueError(
|
152
|
+
"{} does not contain the key {}".format(
|
153
|
+
file_path, CURRENT_PERIMETER_KEY
|
154
|
+
)
|
155
|
+
)
|
156
|
+
elif "OBP_CONFIG_DIR" in os.environ:
|
157
|
+
raise FileNotFoundError(
|
158
|
+
"Environment variable OBP_CONFIG_DIR is set to {} but this directory does not contain an ob_config.json file.".format(
|
159
|
+
os.environ["OBP_CONFIG_DIR"]
|
160
|
+
)
|
161
|
+
)
|
162
|
+
return None
|
outerbounds/utils/schema.py
CHANGED
@@ -5,6 +5,7 @@ class OuterboundsCommandStatus(Enum):
|
|
5
5
|
OK = "OK"
|
6
6
|
FAIL = "FAIL"
|
7
7
|
WARN = "WARN"
|
8
|
+
NOT_SUPPORTED = "NOT_SUPPORTED"
|
8
9
|
|
9
10
|
|
10
11
|
class CommandStatus:
|
@@ -39,6 +40,11 @@ class OuterboundsCommandResponse:
|
|
39
40
|
self.metadata = {}
|
40
41
|
self._data = {}
|
41
42
|
|
43
|
+
def update(self, status, code, message):
|
44
|
+
self.status = status
|
45
|
+
self._code = code
|
46
|
+
self._message = message
|
47
|
+
|
42
48
|
def add_or_update_metadata(self, key, value):
|
43
49
|
self.metadata[key] = value
|
44
50
|
|
@@ -53,14 +59,14 @@ class OuterboundsCommandResponse:
|
|
53
59
|
if step.status == OuterboundsCommandStatus.FAIL:
|
54
60
|
self.status = OuterboundsCommandStatus.FAIL
|
55
61
|
self._code = 500
|
56
|
-
self._message = "
|
62
|
+
self._message = "Encountered an error when trying to run command."
|
57
63
|
elif (
|
58
64
|
step.status == OuterboundsCommandStatus.WARN
|
59
65
|
and self.status != OuterboundsCommandStatus.FAIL
|
60
66
|
):
|
61
67
|
self.status = OuterboundsCommandStatus.WARN
|
62
68
|
self._code = 200
|
63
|
-
self._message = "
|
69
|
+
self._message = "Encountered one or more warnings when running the command."
|
64
70
|
|
65
71
|
def as_dict(self):
|
66
72
|
self._data["steps"] = [step.as_dict() for step in self._steps]
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import tempfile
|
2
|
+
import os
|
3
|
+
|
4
|
+
"""
|
5
|
+
Writes the given data to file_loc. Ensures that the directory exists
|
6
|
+
and uses a temporary file to ensure that the file is written atomically.
|
7
|
+
"""
|
8
|
+
|
9
|
+
|
10
|
+
def safe_write_to_disk(file_loc, data):
|
11
|
+
# Ensure the directory exists
|
12
|
+
os.makedirs(os.path.dirname(file_loc), exist_ok=True)
|
13
|
+
|
14
|
+
with tempfile.NamedTemporaryFile(
|
15
|
+
"w", dir=os.path.dirname(file_loc), delete=False
|
16
|
+
) as f:
|
17
|
+
f.write(data)
|
18
|
+
tmp_file = f.name
|
19
|
+
os.rename(tmp_file, file_loc)
|
outerbounds/vendor.py
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
import glob
|
2
|
+
import shutil
|
3
|
+
import subprocess
|
4
|
+
import re
|
5
|
+
|
6
|
+
from functools import partial
|
7
|
+
from itertools import chain
|
8
|
+
from pathlib import Path
|
9
|
+
|
10
|
+
WHITELIST = {
|
11
|
+
"README.txt",
|
12
|
+
"__init__.py",
|
13
|
+
"vendor_any.txt",
|
14
|
+
"pip.LICENSE",
|
15
|
+
}
|
16
|
+
|
17
|
+
# Borrowed from https://github.com/pypa/pip/tree/main/src/pip/_vendor
|
18
|
+
|
19
|
+
VENDOR_SUBDIR = re.compile(r"^_vendor/vendor_([a-zA-Z0-9_]+).txt$")
|
20
|
+
|
21
|
+
|
22
|
+
def delete_all(*paths, whitelist=frozenset()):
|
23
|
+
for item in paths:
|
24
|
+
if item.is_dir():
|
25
|
+
shutil.rmtree(item, ignore_errors=True)
|
26
|
+
elif item.is_file() and item.name not in whitelist:
|
27
|
+
item.unlink()
|
28
|
+
|
29
|
+
|
30
|
+
def iter_subtree(path):
|
31
|
+
"""Recursively yield all files in a subtree, depth-first"""
|
32
|
+
if not path.is_dir():
|
33
|
+
if path.is_file():
|
34
|
+
yield path
|
35
|
+
return
|
36
|
+
for item in path.iterdir():
|
37
|
+
if item.is_dir():
|
38
|
+
yield from iter_subtree(item)
|
39
|
+
elif item.is_file():
|
40
|
+
yield item
|
41
|
+
|
42
|
+
|
43
|
+
def patch_vendor_imports(file, replacements):
|
44
|
+
text = file.read_text("utf8")
|
45
|
+
for replacement in replacements:
|
46
|
+
text = replacement(text)
|
47
|
+
file.write_text(text, "utf8")
|
48
|
+
|
49
|
+
|
50
|
+
def find_vendored_libs(vendor_dir, whitelist, whitelist_dirs):
|
51
|
+
vendored_libs = []
|
52
|
+
paths = []
|
53
|
+
for item in vendor_dir.iterdir():
|
54
|
+
if item.is_dir() and item not in whitelist_dirs:
|
55
|
+
vendored_libs.append(item.name)
|
56
|
+
elif item.is_file() and item.name not in whitelist:
|
57
|
+
vendored_libs.append(item.stem) # without extension
|
58
|
+
else: # not a dir or a file not in the whitelist
|
59
|
+
continue
|
60
|
+
paths.append(item)
|
61
|
+
return vendored_libs, paths
|
62
|
+
|
63
|
+
|
64
|
+
def fetch_licenses(*info_dir, vendor_dir):
|
65
|
+
for file in chain.from_iterable(map(iter_subtree, info_dir)):
|
66
|
+
if "LICENSE" in file.name:
|
67
|
+
library = file.parent.name.split("-")[0]
|
68
|
+
shutil.copy(file, vendor_dir / ("%s.LICENSE" % library))
|
69
|
+
else:
|
70
|
+
continue
|
71
|
+
|
72
|
+
|
73
|
+
def vendor(vendor_dir):
|
74
|
+
# remove everything
|
75
|
+
delete_all(*vendor_dir.iterdir(), whitelist=WHITELIST)
|
76
|
+
|
77
|
+
exclude_subdirs = []
|
78
|
+
# Iterate on the vendor*.txt files
|
79
|
+
for vendor_file in glob.glob(f"{vendor_dir.name}/vendor*.txt"):
|
80
|
+
# We extract the subdirectory we are going to extract into
|
81
|
+
subdir = VENDOR_SUBDIR.match(vendor_file).group(1)
|
82
|
+
# Includes "any" but it doesn't really matter unless you install "any"
|
83
|
+
exclude_subdirs.append(subdir)
|
84
|
+
|
85
|
+
for subdir in exclude_subdirs:
|
86
|
+
create_init_file = False
|
87
|
+
if subdir == "any":
|
88
|
+
vendor_subdir = vendor_dir
|
89
|
+
# target package is <parent>.<vendor_dir>; foo/_vendor -> foo._vendor
|
90
|
+
pkgname = f"{vendor_dir.parent.name}.{vendor_dir.name}"
|
91
|
+
else:
|
92
|
+
create_init_file = True
|
93
|
+
vendor_subdir = vendor_dir / subdir
|
94
|
+
# target package is <parent>.<vendor_dir>; foo/_vendor -> foo._vendor
|
95
|
+
pkgname = f"{vendor_dir.parent.name}.{vendor_dir.name}.{vendor_subdir.name}"
|
96
|
+
|
97
|
+
# install with pip
|
98
|
+
subprocess.run(
|
99
|
+
[
|
100
|
+
"python3",
|
101
|
+
"-m",
|
102
|
+
"pip",
|
103
|
+
"install",
|
104
|
+
"-t",
|
105
|
+
str(vendor_subdir),
|
106
|
+
"-r",
|
107
|
+
"_vendor/vendor_%s.txt" % subdir,
|
108
|
+
"--no-compile",
|
109
|
+
]
|
110
|
+
)
|
111
|
+
|
112
|
+
# fetch licenses
|
113
|
+
fetch_licenses(*vendor_subdir.glob("*.dist-info"), vendor_dir=vendor_subdir)
|
114
|
+
|
115
|
+
# delete stuff that's not needed
|
116
|
+
delete_all(
|
117
|
+
*vendor_subdir.glob("*.dist-info"),
|
118
|
+
*vendor_subdir.glob("*.egg-info"),
|
119
|
+
vendor_subdir / "bin",
|
120
|
+
)
|
121
|
+
|
122
|
+
# Touch a __init__.py file
|
123
|
+
if create_init_file:
|
124
|
+
with open(
|
125
|
+
"%s/__init__.py" % str(vendor_subdir), "w+", encoding="utf-8"
|
126
|
+
) as f:
|
127
|
+
f.write("# Empty file")
|
128
|
+
|
129
|
+
vendored_libs, paths = find_vendored_libs(
|
130
|
+
vendor_subdir, WHITELIST, exclude_subdirs
|
131
|
+
)
|
132
|
+
|
133
|
+
replacements = []
|
134
|
+
for lib in vendored_libs:
|
135
|
+
replacements += (
|
136
|
+
partial( # import bar -> import foo._vendor.bar
|
137
|
+
re.compile(r"(^\s*)import {}\n".format(lib), flags=re.M).sub,
|
138
|
+
r"\1from {} import {}\n".format(pkgname, lib),
|
139
|
+
),
|
140
|
+
partial( # from bar -> from foo._vendor.bar
|
141
|
+
re.compile(r"(^\s*)from {}(\.|\s+)".format(lib), flags=re.M).sub,
|
142
|
+
r"\1from {}.{}\2".format(pkgname, lib),
|
143
|
+
),
|
144
|
+
)
|
145
|
+
|
146
|
+
for file in chain.from_iterable(map(iter_subtree, paths)):
|
147
|
+
if file.suffix == ".py":
|
148
|
+
patch_vendor_imports(file, replacements)
|
149
|
+
|
150
|
+
|
151
|
+
if __name__ == "__main__":
|
152
|
+
here = Path("__file__").resolve().parent
|
153
|
+
vendor_tl_dir = here / "_vendor"
|
154
|
+
has_vendor_file = len(glob.glob(f"{vendor_tl_dir.name}/vendor*.txt")) > 0
|
155
|
+
assert has_vendor_file, "_vendor/vendor*.txt file not found"
|
156
|
+
assert (
|
157
|
+
vendor_tl_dir / "__init__.py"
|
158
|
+
).exists(), "_vendor/__init__.py file not found"
|
159
|
+
vendor(vendor_tl_dir)
|
@@ -1,31 +1,42 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: outerbounds
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.133
|
4
4
|
Summary: More Data Science, Less Administration
|
5
5
|
License: Proprietary
|
6
6
|
Keywords: data science,machine learning,MLOps
|
7
7
|
Author: Outerbounds, Inc.
|
8
|
-
Requires-Python: >=3.
|
8
|
+
Requires-Python: >=3.7,<4.0
|
9
9
|
Classifier: Development Status :: 4 - Beta
|
10
10
|
Classifier: License :: Other/Proprietary License
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
12
|
+
Classifier: Programming Language :: Python :: 3.7
|
12
13
|
Classifier: Programming Language :: Python :: 3.8
|
13
14
|
Classifier: Programming Language :: Python :: 3.9
|
14
15
|
Classifier: Programming Language :: Python :: 3.10
|
15
16
|
Classifier: Programming Language :: Python :: 3.11
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
16
18
|
Provides-Extra: azure
|
17
19
|
Provides-Extra: gcp
|
18
|
-
|
20
|
+
Provides-Extra: snowflake
|
19
21
|
Requires-Dist: azure-identity (>=1.15.0,<2.0.0) ; extra == "azure"
|
22
|
+
Requires-Dist: azure-keyvault-secrets (>=4.7.0,<5.0.0) ; extra == "azure"
|
20
23
|
Requires-Dist: azure-storage-blob (>=12.9.0,<13.0.0) ; extra == "azure"
|
21
24
|
Requires-Dist: boto3
|
22
|
-
Requires-Dist: click (>=8.1.3,<9.0.0)
|
23
25
|
Requires-Dist: google-api-core (>=2.16.1,<3.0.0) ; extra == "gcp"
|
24
26
|
Requires-Dist: google-auth (>=2.27.0,<3.0.0) ; extra == "gcp"
|
27
|
+
Requires-Dist: google-cloud-secret-manager (>=2.20.0,<3.0.0) ; extra == "gcp"
|
25
28
|
Requires-Dist: google-cloud-storage (>=2.14.0,<3.0.0) ; extra == "gcp"
|
26
|
-
Requires-Dist:
|
27
|
-
Requires-Dist: ob-metaflow
|
29
|
+
Requires-Dist: metaflow-checkpoint (==0.1.6)
|
30
|
+
Requires-Dist: ob-metaflow (==2.13.4.1)
|
31
|
+
Requires-Dist: ob-metaflow-extensions (==1.1.121)
|
32
|
+
Requires-Dist: ob-metaflow-stubs (==6.0.3.133)
|
28
33
|
Requires-Dist: opentelemetry-distro (==0.41b0)
|
29
34
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http (==1.20.0)
|
30
35
|
Requires-Dist: opentelemetry-instrumentation-requests (==0.41b0)
|
31
36
|
Project-URL: Documentation, https://docs.metaflow.org
|
37
|
+
Description-Content-Type: text/markdown
|
38
|
+
|
39
|
+
# Outerbounds
|
40
|
+
|
41
|
+
Main package for the Outerbounds platform.
|
42
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
outerbounds/__init__.py,sha256=GPdaubvAYF8pOFWJ3b-sPMKCpyfpteWVMZWkmaYhxRw,32
|
2
|
+
outerbounds/_vendor/PyYAML.LICENSE,sha256=jTko-dxEkP1jVwfLiOsmvXZBAqcoKVQwfT5RZ6V36KQ,1101
|
3
|
+
outerbounds/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
outerbounds/_vendor/_yaml/__init__.py,sha256=nD985-g4Mrx97PhtSzI2L53o8sCHUJ4ZoBWcUd7o0PQ,1449
|
5
|
+
outerbounds/_vendor/click/__init__.py,sha256=rQBLutqg-z6m8nOzivIfigDn_emijB_dKv9BZ2FNi5s,3138
|
6
|
+
outerbounds/_vendor/click/_compat.py,sha256=JIHLYs7Jzz4KT9t-ds4o4jBzLjnwCiJQKqur-5iwCKI,18810
|
7
|
+
outerbounds/_vendor/click/_termui_impl.py,sha256=qK6Cfy4mRFxvxE8dya8RBhLpSC8HjF-lvBc6aNrPdwg,23451
|
8
|
+
outerbounds/_vendor/click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353
|
9
|
+
outerbounds/_vendor/click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860
|
10
|
+
outerbounds/_vendor/click/core.py,sha256=ici4JXpq5VWyQkFQQklE4GnUKR8wxSP1YAzqaVYAZ3Y,112862
|
11
|
+
outerbounds/_vendor/click/decorators.py,sha256=yo3zvzgUm5q7h5CXjyV6q3h_PJAiUaem178zXwdWUFI,16350
|
12
|
+
outerbounds/_vendor/click/exceptions.py,sha256=7gDaLGuFZBeCNwY9ERMsF2-Z3R9Fvq09Zc6IZSKjseo,9167
|
13
|
+
outerbounds/_vendor/click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706
|
14
|
+
outerbounds/_vendor/click/globals.py,sha256=TP-qM88STzc7f127h35TD_v920FgfOD2EwzqA0oE8XU,1961
|
15
|
+
outerbounds/_vendor/click/parser.py,sha256=cAEt1uQR8gq3-S9ysqbVU-fdAZNvilxw4ReJ_T1OQMk,19044
|
16
|
+
outerbounds/_vendor/click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
|
+
outerbounds/_vendor/click/shell_completion.py,sha256=qOp_BeC9esEOSZKyu5G7RIxEUaLsXUX-mTb7hB1r4QY,18018
|
18
|
+
outerbounds/_vendor/click/termui.py,sha256=ACBQVOvFCTSqtD5VREeCAdRtlHd-Imla-Lte4wSfMjA,28355
|
19
|
+
outerbounds/_vendor/click/testing.py,sha256=ptpMYgRY7dVfE3UDgkgwayu9ePw98sQI3D7zZXiCpj4,16063
|
20
|
+
outerbounds/_vendor/click/types.py,sha256=u8LK2CRcVw3jWDutzP_wgFV478TXhsjL8gYSFPjGKkE,35865
|
21
|
+
outerbounds/_vendor/click/utils.py,sha256=33D6E7poH_nrKB-xr-UyDEXnxOcCiQqxuRLtrqeVv6o,18682
|
22
|
+
outerbounds/_vendor/click.LICENSE,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475
|
23
|
+
outerbounds/_vendor/vendor_any.txt,sha256=9vi_h2zSBIx0sFM9i69xNEwe-HyeX0_sdtMjImmvgXo,27
|
24
|
+
outerbounds/_vendor/yaml/__init__.py,sha256=lPcXUknB0EUNfCL8MJOgq26y70nOQR_Eajqzycmtnhg,12569
|
25
|
+
outerbounds/_vendor/yaml/_yaml.cpython-311-darwin.so,sha256=YiF55JiadfOvw_mUH-lONNnsiMHj6C6o1SBfTCvvW54,362008
|
26
|
+
outerbounds/_vendor/yaml/composer.py,sha256=KI1ASnRYW7jWza4BxiHsjDdpV_AYR6wGKD_d3q5y1GY,4975
|
27
|
+
outerbounds/_vendor/yaml/constructor.py,sha256=a_QHcwgF8J3ius54IchRi50VSuX-tNZfL83JsRA9q9w,30058
|
28
|
+
outerbounds/_vendor/yaml/cyaml.py,sha256=pbSaKr0mn_yMEc4DuLbl38RGWVSkXBgA9NXHATnjfuE,4497
|
29
|
+
outerbounds/_vendor/yaml/dumper.py,sha256=ncn_DlBmKv_aTtkv9tBagK-8SQE9ETLIdwTYMO0_5WA,3507
|
30
|
+
outerbounds/_vendor/yaml/emitter.py,sha256=9jcV2QKdsHWAPJrqsWMEBCLCU56D25qLC1XiQFcU48A,44167
|
31
|
+
outerbounds/_vendor/yaml/error.py,sha256=1ImZXAcfUbnuVfkHYSeHakDojgwAjFs4pFUKfKNFLuw,2726
|
32
|
+
outerbounds/_vendor/yaml/events.py,sha256=VlHDUFXu2zAU6TFEQUBDIq8gU3s_1Q67vpNlYY645p4,2465
|
33
|
+
outerbounds/_vendor/yaml/loader.py,sha256=jX2YIC4HwJslE2DKVwLix2ne8qhJyFJzwjJz7CzVPOk,2060
|
34
|
+
outerbounds/_vendor/yaml/nodes.py,sha256=K0QBIan-NI8RqxiPyo6fLaR-GSTpmF_9eXtJ3uf6rEo,1422
|
35
|
+
outerbounds/_vendor/yaml/parser.py,sha256=BhbxGU0AjebJZIVFpBIPoP5YAGYOMVg7Vjmd-aFP5ts,26214
|
36
|
+
outerbounds/_vendor/yaml/reader.py,sha256=lR8yfw6FMasPB41qFrsBUOVtASViXnKd89tvJHQNsVc,7109
|
37
|
+
outerbounds/_vendor/yaml/representer.py,sha256=FK_yoIj_17GdgzVP8_yFBobV56PKqEkZ5AGtBdKjWDc,14088
|
38
|
+
outerbounds/_vendor/yaml/resolver.py,sha256=dPhU1d7G1JCMktPFvNhyqwj2oNvx1yf_Jfa35CydQXA,8992
|
39
|
+
outerbounds/_vendor/yaml/scanner.py,sha256=ZcI8IngR56PaQ0m27WU2vxCqmDCuRjz-hr7pirbMPuw,52982
|
40
|
+
outerbounds/_vendor/yaml/serializer.py,sha256=8wFZRy9SsQSktF_f9OOroroqsh4qVUe53ry07P9UgCc,4368
|
41
|
+
outerbounds/_vendor/yaml/tokens.py,sha256=JBSu38wihGr4l73JwbfMA7Ks1-X84g8-NskTz7KwPmA,2578
|
42
|
+
outerbounds/cli_main.py,sha256=e9UMnPysmc7gbrimq2I4KfltggyU7pw59Cn9aEguVcU,74
|
43
|
+
outerbounds/command_groups/__init__.py,sha256=QPWtj5wDRTINDxVUL7XPqG3HoxHNvYOg08EnuSZB2Hc,21
|
44
|
+
outerbounds/command_groups/apps_cli.py,sha256=8jmQufa0bK2sfRfs7DiWjoJ1oWiqZAixsL4Dte_KY4Y,17201
|
45
|
+
outerbounds/command_groups/cli.py,sha256=q0hdJO4biD3iEOdyJcxnRkeleA8AKAhx842kQ49I6kk,365
|
46
|
+
outerbounds/command_groups/local_setup_cli.py,sha256=tuuqJRXQ_guEwOuQSIf9wkUU0yg8yAs31myGViAK15s,36364
|
47
|
+
outerbounds/command_groups/perimeters_cli.py,sha256=iF_Uw7ROiSctf6FgoJEy30iDBLVE1j9FKuR3shgJRmc,19050
|
48
|
+
outerbounds/command_groups/tutorials_cli.py,sha256=UInFyiMqtscHFfi8YQwiY_6Sdw9quJOtRu5OukEBccw,3522
|
49
|
+
outerbounds/command_groups/workstations_cli.py,sha256=V5Jbj1cVb4IRllI7fOgNgL6OekRpuFDv6CEhDb4xC6w,22016
|
50
|
+
outerbounds/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
51
|
+
outerbounds/utils/kubeconfig.py,sha256=yvcyRXGR4AhQuqUDqmbGxEOHw5ixMFV0AZIDg1LI_Qo,7981
|
52
|
+
outerbounds/utils/metaflowconfig.py,sha256=l2vJbgPkLISU-XPGZFaC8ZKmYFyJemlD6bwB-EKUsAw,5770
|
53
|
+
outerbounds/utils/schema.py,sha256=lMUr9kNgn9wy-sO_t_Tlxmbt63yLeN4b0xQXbDUDj4A,2331
|
54
|
+
outerbounds/utils/utils.py,sha256=4Z8cszNob_8kDYCLNTrP-wWads_S_MdL3Uj3ju4mEsk,501
|
55
|
+
outerbounds/vendor.py,sha256=gRLRJNXtZBeUpPEog0LOeIsl6GosaFFbCxUvR4bW6IQ,5093
|
56
|
+
outerbounds-0.3.133.dist-info/METADATA,sha256=q0HvciFfYuFHoyzBF7-2hnU7EkQIk47mtcxUOxtuWKs,1761
|
57
|
+
outerbounds-0.3.133.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
58
|
+
outerbounds-0.3.133.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
|
59
|
+
outerbounds-0.3.133.dist-info/RECORD,,
|
@@ -1,15 +0,0 @@
|
|
1
|
-
outerbounds/__init__.py,sha256=GPdaubvAYF8pOFWJ3b-sPMKCpyfpteWVMZWkmaYhxRw,32
|
2
|
-
outerbounds/cli_main.py,sha256=e9UMnPysmc7gbrimq2I4KfltggyU7pw59Cn9aEguVcU,74
|
3
|
-
outerbounds/command_groups/__init__.py,sha256=QPWtj5wDRTINDxVUL7XPqG3HoxHNvYOg08EnuSZB2Hc,21
|
4
|
-
outerbounds/command_groups/cli.py,sha256=H4LxcYTmsY9DQUrReSRLjvbg9s9Ro7s-eUrcMqEJ_9A,261
|
5
|
-
outerbounds/command_groups/local_setup_cli.py,sha256=0sEi3V0sqoCW0RI2z3xMLNnit0pCsigWQ07m1mhDBso,29524
|
6
|
-
outerbounds/command_groups/perimeters_cli.py,sha256=9tOql42d00KfHpZYkLLGEAOiy8iRbIzsknldCyICwU0,12063
|
7
|
-
outerbounds/command_groups/workstations_cli.py,sha256=f3gwHMZPHzeOcGj5VfC5tZZA18JQhFzy2LRGzqAosOk,19286
|
8
|
-
outerbounds/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
outerbounds/utils/kubeconfig.py,sha256=l1mUP1j9VIq3fsffi5bJ1Nk-hYlwd1dIqkpj7DvVS1E,7936
|
10
|
-
outerbounds/utils/metaflowconfig.py,sha256=HgaDmK3F97rppfGUdysS1Zppe28ERTLV_HcB5IuPpV4,2631
|
11
|
-
outerbounds/utils/schema.py,sha256=Ht_Yf5uoKO0m36WXHZLSPmWPH6EFWXfZDQsiAUquc5k,2160
|
12
|
-
outerbounds-0.3.55rc3.dist-info/METADATA,sha256=ARhdx-T4KbMT1ri3AqRyA5vW4B_8dGHZGdRlcK-iBuI,1367
|
13
|
-
outerbounds-0.3.55rc3.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
|
14
|
-
outerbounds-0.3.55rc3.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
|
15
|
-
outerbounds-0.3.55rc3.dist-info/RECORD,,
|
File without changes
|