Skip to content

Commit a14a2eb

Browse files
authored
Allow specifying ranges in cortex requirements.txt
1 parent 133f20b commit a14a2eb

File tree

8 files changed

+69
-19
lines changed

8 files changed

+69
-19
lines changed

docs/applications/implementations/aggregators.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ def aggregate_spark(data, columns, args):
3737
return discretizer.getSplits()
3838
```
3939

40-
## Customization
40+
## Pre-installed Packages
4141

42-
You can import PyPI packages or your own Python packages to help create more complex aggregators. See [Python Packages](../advanced/python-packages.md) for more details.
42+
The following packages have been pre-installed and can be used in your implementations:
43+
44+
```text
45+
pyspark==2.4.0
46+
boto3==1.9.78
47+
msgpack==0.6.1
48+
numpy>=1.13.3,<2
49+
requirements-parser==0.2.0
50+
packaging==19.0.0
51+
```
52+
53+
You can install additional PyPI packages and import your own Python packages. See [Python Packages](../advanced/python-packages.md) for more details.

docs/applications/implementations/models.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ def create_estimator(run_config, model_config):
4646
)
4747
```
4848

49-
## Customization
49+
## Pre-installed Packages
5050

51-
You can import PyPI packages or your own Python packages to help create more complex models. See [Python Packages](../advanced/python-packages.md) for more details.
51+
The following packages have been pre-installed and can be used in your implementations:
52+
53+
```text
54+
tensorflow==1.12.0
55+
boto3==1.9.78
56+
msgpack==0.6.1
57+
numpy>=1.13.3,<2
58+
requirements-parser==0.2.0
59+
packaging==19.0.0
60+
```
61+
62+
You can install additional PyPI packages and import your own Python packages. See [Python Packages](../advanced/python-packages.md) for more details.

docs/applications/implementations/transformers.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,17 @@ def reverse_transform_python(transformed_value, args):
8181
return args["mean"] + (transformed_value * args["stddev"])
8282
```
8383

84-
## Customization
84+
## Pre-installed Packages
8585

86-
You can import PyPI packages or your own Python packages to help create more complex transformers. See [Python Packages](../advanced/python-packages.md) for more details.
86+
The following packages have been pre-installed and can be used in your implementations:
87+
88+
```text
89+
pyspark==2.4.0
90+
boto3==1.9.78
91+
msgpack==0.6.1
92+
numpy>=1.13.3,<2
93+
requirements-parser==0.2.0
94+
packaging==19.0.0
95+
```
96+
97+
You can install additional PyPI packages and import your own Python packages. See [Python Packages](../advanced/python-packages.md) for more details.

pkg/operator/context/context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func New(
6161

6262
ctx.StatusPrefix = StatusPrefix(ctx.App.Name)
6363

64-
pythonPackages, err := loadPythonPackages(files)
64+
pythonPackages, err := loadPythonPackages(files, ctx.DatasetVersion)
6565
if err != nil {
6666
return nil, err
6767
}

pkg/operator/context/python_packages.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,14 @@ func findCustomPackages(files map[string][]byte) []string {
4747
return customPackages
4848
}
4949

50-
func loadPythonPackages(files map[string][]byte) (context.PythonPackages, error) {
50+
func loadPythonPackages(files map[string][]byte, datasetVersion string) (context.PythonPackages, error) {
5151
pythonPackages := make(map[string]*context.PythonPackage)
5252

5353
if reqFileBytes, ok := files[consts.RequirementsTxt]; ok {
5454
var buf bytes.Buffer
5555
buf.Write(reqFileBytes)
56+
// Invalidate cached packages when refreshed without depending on environment ID
57+
buf.WriteString(datasetVersion)
5658
id := hash.Bytes(buf.Bytes())
5759
pythonPackage := context.PythonPackage{
5860
ResourceConfigFields: userconfig.ResourceConfigFields{
@@ -80,6 +82,8 @@ func loadPythonPackages(files map[string][]byte) (context.PythonPackages, error)
8082
for _, packageName := range customPackages {
8183
zipBytesInputs := []zip.BytesInput{}
8284
var buf bytes.Buffer
85+
// Invalidate cached packages when refreshed without depending on environment ID
86+
buf.WriteString(datasetVersion)
8387
for filePath, fileBytes := range files {
8488
if strings.HasPrefix(filePath, filepath.Join(consts.PackageDir, packageName)) {
8589
buf.Write(fileBytes)

pkg/workloads/lib/package.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from lib.exceptions import UserException, CortexException
2525

2626
import requirements
27+
from packaging.requirements import Requirement
2728

2829
logger = get_logger()
2930

@@ -39,12 +40,27 @@ def get_build_order(python_packages):
3940

4041

4142
def get_restricted_packages():
42-
cortex_packages = {"pyspark": "2.4.0", "tensorflow": "1.12.0"}
43+
req_list = ["pyspark==2.4.0", "tensorflow==1.12.0"]
4344
req_files = glob.glob("/src/**/requirements.txt", recursive=True)
45+
4446
for req_file in req_files:
47+
# clean requirements file, like removing comments
4548
with open(req_file) as f:
4649
for req in requirements.parse(f):
47-
cortex_packages[req.name] = req.specs[0][1]
50+
specifiers = [op + version for op, version in req.specs]
51+
req_list.append(req.name + ",".join(specifiers))
52+
53+
cortex_packages = {}
54+
55+
for req_line in req_list:
56+
parsed_req = Requirement(req_line)
57+
if cortex_packages.get(parsed_req.name) is None:
58+
cortex_packages[parsed_req.name] = parsed_req.specifier
59+
else:
60+
cortex_packages[parsed_req.name] = (
61+
cortex_packages[parsed_req.name] & parsed_req.specifier
62+
)
63+
4864
return cortex_packages
4965

5066

@@ -79,11 +95,11 @@ def build_packages(python_packages, bucket):
7995
for wheelname in os.listdir(package_wheel_path):
8096
name_split = wheelname.split("-")
8197
dist_name, version = name_split[0], name_split[1]
82-
expected_version = restricted_packages.get(dist_name, None)
83-
if expected_version is not None and version != expected_version:
98+
expected_version_specs = restricted_packages.get(dist_name, None)
99+
if expected_version_specs is not None and not expected_version_specs.contains(version):
84100
raise UserException(
85-
"when installing {}, found {}=={} but cortex requires {}=={}".format(
86-
package_name, dist_name, version, dist_name, expected_version
101+
"when installing {}, found {}=={} which conflicts with cortex's requirements {}{}".format(
102+
package_name, dist_name, version, dist_name, expected_version_specs
87103
)
88104
)
89105

pkg/workloads/lib/requirements.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# specify exact version for each dependency, name==version
2-
31
boto3==1.9.78
42
msgpack==0.6.1
5-
numpy==1.15.4
3+
numpy>=1.13.3,<2
64
requirements-parser==0.2.0
5+
packaging==19.0.0

pkg/workloads/tf_api/requirements.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# specify exact version for each dependency, name==version
2-
31
flask==1.0.2
42
flask-api==1.1
53
waitress==1.2.1

0 commit comments

Comments
 (0)