Skip to content

Commit aedb8d6

Browse files
authored
Merge pull request #3 from comet-ml/update-mlflow-2.0.1
Update support to mlflow 2.0.1
2 parents 198423b + efc1a00 commit aedb8d6

File tree

13 files changed

+197
-87
lines changed

13 files changed

+197
-87
lines changed

.flake8

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[flake8]
2-
exclude = .git,__pycache__,data,tools
3-
ignore = E101, E111, E114, E115, E116, E117, E121, E122, E123, E124, E125, E126, E127, E128, E129, E131, E133, E2, E3, E5, E501, E701, E702, E703, E704, W1, W2, W3, W503, W504
2+
max-line-length = 100
3+
extend-ignore = E203

.github/workflows/package.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: package
2+
3+
on:
4+
push:
5+
release:
6+
types: [published]
7+
8+
9+
jobs:
10+
build-package:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v3
14+
- name: Set up Python 3.9
15+
uses: actions/setup-python@v3
16+
with:
17+
python-version: 3.9
18+
- name: Build pip package
19+
run: |
20+
pip install -U pip build
21+
python3 -m build --sdist --wheel --outdir dist/ .
22+
- name: Archive Pypi artifacts
23+
uses: actions/upload-artifact@v3
24+
with:
25+
name: pypi_dist
26+
path: dist
27+
- name: Publish package
28+
if: startsWith(github.ref, 'refs/tags')
29+
uses: pypa/gh-action-pypi-publish@release/v1
30+
with:
31+
password: ${{ secrets.TWINE_PROD_PASSWORD }}

.github/workflows/tests.yml

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,3 @@ jobs:
4343
pip install pre-commit
4444
- name: Run pre-commit
4545
run: pre-commit run --all-files
46-
package:
47-
runs-on: ubuntu-18.04
48-
needs: [test, lint]
49-
steps:
50-
- uses: actions/checkout@v1
51-
- name: Set up Python 3.7
52-
uses: actions/setup-python@v1
53-
with:
54-
python-version: 3.7
55-
- name: Package and upload to Pypi Test
56-
env:
57-
TWINE_USERNAME: __token__
58-
TWINE_PASSWORD: ${{ secrets.TWINE_TEST_PASSWORD }}
59-
run: |
60-
python -m pip install --upgrade pip
61-
pip install -U wheel twine
62-
python setup.py bdist_wheel sdist
63-
ls dist/
64-
twine upload --repository-url https://test.pypi.org/legacy/ --skip-existing dist/*
65-
- name: Upload to Pypi production if it's a new tag
66-
if: contains(github.ref, 'tags')
67-
env:
68-
TWINE_USERNAME: __token__
69-
TWINE_PASSWORD: ${{ secrets.TWINE_PROD_PASSWORD }}
70-
run: |
71-
twine upload dist/*

.pre-commit-config.yaml

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,34 @@
11
repos:
2-
- repo: https://github.com/asottile/seed-isort-config
3-
rev: v1.9.4
4-
hooks:
5-
- id: seed-isort-config
6-
- repo: https://github.com/pre-commit/mirrors-isort
7-
rev: v4.3.21
2+
- repo: https://github.com/PyCQA/isort
3+
rev: 5.10.1
84
hooks:
95
- id: isort
106
- repo: https://github.com/ambv/black
11-
rev: 19.10b0
7+
rev: 22.10.0
128
hooks:
139
- id: black
14-
- repo: https://gitlab.com/pycqa/flake8
15-
rev: 3.7.9
10+
- repo: https://github.com/pycqa/flake8
11+
rev: 5.0.4
1612
hooks:
1713
- id: flake8
18-
additional_dependencies: ['flake8-coding==1.3.2', 'flake8-copyright==0.2.2', 'flake8-debugger==3.2.1', 'flake8-mypy==17.8.0']
14+
args: ['--config=.flake8']
15+
additional_dependencies: ['flake8-coding==1.3.2', 'flake8-copyright==0.2.3', 'flake8-debugger==4.1.2', 'flake8-mypy==17.8.0']
1916
- repo: https://github.com/pre-commit/pre-commit-hooks
20-
rev: v2.5.0
17+
rev: v4.3.0
2118
hooks:
22-
- id: trailing-whitespace
19+
- id: check-json
20+
- id: check-merge-conflict
2321
- id: check-yaml
22+
- id: debug-statements
2423
- id: mixed-line-ending
25-
- id: name-tests-test
26-
args: ['--django']
2724
- id: requirements-txt-fixer
25+
- id: trailing-whitespace
2826
- repo: https://github.com/codespell-project/codespell
29-
rev: v1.16.0
27+
rev: v2.2.2
3028
hooks:
3129
- id: codespell
3230
exclude_types: [json]
3331
args: ['--ignore-words-list=feld']
3432
- repo: meta
3533
hooks:
36-
- id: check-hooks-apply
3734
- id: check-useless-excludes
38-
default_language_version:
39-
python: python3.7

comet_for_mlflow/cli.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,22 @@ def main():
4242
"--no-upload",
4343
dest="upload",
4444
action="store_false",
45-
help="Do not upload the prepared experiments to comet.ml; will not create comet.ml projects",
45+
help="Do not upload the prepared experiments to comet.ml;"
46+
" will not create comet.ml projects",
4647
)
4748
parser.set_defaults(upload=True)
4849

4950
parser.add_argument(
5051
"--api-key",
51-
help="Set the Comet API key; required with --upload (the default); can also be configured in the usual places",
52+
help="Set the Comet API key; required with --upload (the default);"
53+
" can also be configured in the usual places",
5254
)
5355
parser.add_argument(
5456
"--mlflow-store-uri",
55-
help="Set the MLFlow store uri. The MLFlow store uri to used to retrieve MLFlow runs, given directly to MLFlow, and supports all MLFlow schemes (file:// or SQLAlchemy-compatible database connection strings). If not set, reads MLFLOW_TRACKING_URI environment variable",
57+
help="Set the MLFlow store uri. The MLFlow store uri to used to retrieve"
58+
" MLFlow runs, given directly to MLFlow, and supports all MLFlow schemes"
59+
" (file:// or SQLAlchemy-compatible database connection strings)."
60+
" If not set, reads MLFLOW_TRACKING_URI environment variable",
5661
)
5762

5863
parser.add_argument(
@@ -83,7 +88,8 @@ def main():
8388
help="Answer all yes/no questions automatically with 'no'",
8489
)
8590
parser.add_argument(
86-
"--email", help="Set email address if needed for creating a comet.ml account",
91+
"--email",
92+
help="Set email address if needed for creating a comet.ml account",
8793
)
8894

8995
args = parser.parse_args()

comet_for_mlflow/comet_for_mlflow.py

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,19 @@
4141
from comet_ml.exceptions import CometRestApiException
4242
from comet_ml.offline import upload_single_offline_experiment
4343
from mlflow.entities.run_tag import RunTag
44-
from mlflow.entities.view_type import ViewType
4544
from mlflow.tracking import _get_store
4645
from mlflow.tracking._model_registry.utils import _get_store as get_model_registry_store
4746
from mlflow.tracking.registry import UnsupportedModelRegistryStoreURIException
4847
from tabulate import tabulate
4948
from tqdm import tqdm
5049

50+
from .compat import (
51+
get_artifact_repository,
52+
get_mlflow_model_name,
53+
get_mlflow_run_id,
54+
search_mlflow_store_experiments,
55+
search_mlflow_store_runs,
56+
)
5157
from .file_writer import JsonLinesFile
5258
from .utils import (
5359
get_comet_project_name,
@@ -65,18 +71,10 @@
6571
pass
6672

6773

68-
try:
69-
# MLFLOW version 1.4.0
70-
from mlflow.store.artifact.artifact_repository_registry import (
71-
get_artifact_repository,
72-
)
73-
except ImportError:
74-
# MLFLOW version < 1.4.0
75-
from mlflow.store.artifact_repository_registry import get_artifact_repository
76-
7774
logging.basicConfig(level=logging.INFO, format="%(message)s")
7875
LOGGER = logging.getLogger()
7976

77+
8078
# Install a global exception hook
8179
def except_hook(exc_type, exc_value, exc_traceback):
8280
Reporting.report(
@@ -137,8 +135,7 @@ def __init__(
137135
except UnsupportedModelRegistryStoreURIException:
138136
self.model_registry_store = None
139137

140-
# Most of list_experiments returns a list anyway
141-
self.mlflow_experiments = list(self.store.list_experiments())
138+
self.mlflow_experiments = search_mlflow_store_experiments(self.store)
142139
self.len_experiments = len(self.mlflow_experiments) # We start counting at 0
143140

144141
self.summary = {
@@ -239,22 +236,28 @@ def prepare(self):
239236

240237
LOGGER.info("")
241238
LOGGER.info(
242-
"If you need support, you can contact us at http://chat.comet.ml/ or https://comet.ml/docs/quick-start/#getting-support"
239+
"""If you need support, you can contact us at http://chat.comet.ml/"""
240+
""" or https://comet.ml/docs/quick-start/#getting-support"""
243241
)
244242
LOGGER.info("")
245243

246244
def prepare_mlflow_exp(
247-
self, exp,
245+
self,
246+
exp,
248247
):
249-
runs_info = self.store.list_run_infos(exp.experiment_id, ViewType.ALL)
248+
runs_info = search_mlflow_store_runs(self.store, exp.experiment_id)
250249
len_runs = len(runs_info)
251250

252251
for run_number, run_info in enumerate(runs_info):
253252
try:
254-
run_id = run_info.run_id
253+
run_id = get_mlflow_run_id(run_info)
254+
255255
run = self.store.get_run(run_id)
256256
LOGGER.info(
257-
"## Preparing run %d/%d [%s]", run_number + 1, len_runs, run_id,
257+
"## Preparing run %d/%d [%s]",
258+
run_number + 1,
259+
len_runs,
260+
run_id,
258261
)
259262
LOGGER.debug(
260263
"## Preparing run %d/%d: %r", run_number + 1, len_runs, run
@@ -410,15 +413,25 @@ def prepare_single_mlflow_run(self, run, original_experiment_name):
410413
break
411414

412415
if matching_model:
416+
model_name = get_mlflow_model_name(matching_model)
417+
418+
prefix = "models/"
419+
if artifact_path.startswith(prefix):
420+
comet_artifact_path = artifact_path[len(prefix) :]
421+
else:
422+
comet_artifact_path = artifact_path
423+
413424
json_writer.log_artifact_as_model(
414425
local_artifact_path,
415-
artifact_path,
426+
comet_artifact_path,
416427
run_start_time,
417-
matching_model.registered_model.name,
428+
model_name,
418429
)
419430
else:
420431
json_writer.log_artifact_as_asset(
421-
local_artifact_path, artifact_path, run_start_time,
432+
local_artifact_path,
433+
artifact_path,
434+
run_start_time,
422435
)
423436

424437
return self.compress_archive(run.info.run_id)
@@ -438,12 +451,15 @@ def upload(self, prepared_data):
438451
project_note = experiment.tags.get("mlflow.note.content", None)
439452
if project_note:
440453
note_template = (
441-
u"/!\\ This project notes has been copied from MLFlow. It might be overwritten if you run comet_for_mlflow again/!\\ \n%s"
454+
"/!\\ This project notes has been copied from MLFlow."
455+
" It might be overwritten if you run comet_for_mlflow again/!\\ \n%s"
442456
% project_note
443457
)
444458
# We don't support Unicode project notes yet
445459
self.api_client.set_project_notes(
446-
self.workspace, project_name, note_template,
460+
self.workspace,
461+
project_name,
462+
note_template,
447463
)
448464

449465
all_project_names.append(project_name)
@@ -487,7 +503,8 @@ def upload(self, prepared_data):
487503
LOGGER.info("\t- %s", url)
488504

489505
LOGGER.info(
490-
"Get deeper instrumentation by adding Comet SDK to your project: https://comet.ml/docs/python-sdk/mlflow/"
506+
"Get deeper instrumentation by adding Comet SDK to your project:"
507+
" https://comet.ml/docs/python-sdk/mlflow/"
491508
)
492509
LOGGER.info("")
493510

@@ -598,19 +615,23 @@ def create_or_login(self):
598615
Reporting.report("mlflow_new_user", api_key=new_account["apiKey"])
599616

600617
LOGGER.info(
601-
"A Comet.ml account has been created for you and an email was sent to you to setup your password later."
618+
"A Comet.ml account has been created for you and an email was sent to"
619+
" you to setup your password later."
602620
)
603621
save_api_key(new_account["apiKey"])
604622
LOGGER.info(
605-
"Your Comet API Key has been saved to ~/.comet.ini, it is also available on your Comet.ml dashboard."
623+
"Your Comet API Key has been saved to ~/.comet.ini, it is also"
624+
" available on your Comet.ml dashboard."
606625
)
607626
return (
608627
new_account["apiKey"],
609628
new_account["token"],
610629
)
611630
else:
612631
LOGGER.info(
613-
"An account already exists for this account, please input your API Key below (you can find it in your Settings page, https://comet.ml/docs/quick-start/#getting-your-comet-api-key):"
632+
"An account already exists for this account, please input your API Key"
633+
" below (you can find it in your Settings page,"
634+
" https://comet.ml/docs/quick-start/#getting-your-comet-api-key):"
614635
)
615636
api_key = input("API Key: ")
616637

0 commit comments

Comments
 (0)