We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Two models one code name 
### Willingness to contribute

Yes. I can contribute a fix for this bug independently.

### System information

- **Have I written custom code (as opposed to using a stock example script provided in MLflow)**: custom code
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: 20.04
- **MLflow installed from (source or binary)**: source
- **MLflow version (run ``mlflow --version``)**: 1.23.1
- **Python version**: 3.9
- **yarn version, if running the dev UI**: N/A


### Describe the problem

When two mlflow models have the same name for the code packaged with them, for example: a preprocessing code name `prep_features` was packaged with two different mlflow models. If the first mlflow model is loaded, then the second one is also loaded, python will only load the `prep_features` module once. This leads to problems if `prep_features` for the second model is different from the first model.



### Tracking information

_No response_

### Code to reproduce issue

prep_features. py change 1 to 2 when creating custom_model2 with the 2m1cn.py script
```python
def preprocess_features():
    return 1 # 2 for custom_model2
```
2m1cn.py use this file to create custom_model1 and custom_model2 
```python
import mlflow.pyfunc

class CM(mlflow.pyfunc.PythonModel):
    def __init__(self):
        pass
    def predict(self, context, model_input):
        from prep_features import preprocess_features
        return preprocess_features()

# Construct and save the model
model_path = "custom_model1" # "custom_model2"
code_path = ["prep_features.py"]
custom_model = CM()
mlflow.pyfunc.save_model(path=model_path, python_model=custom_model, code_path=code_path)
```

test.py now use this file to test your created models
```python
# Evaluate the models
import mlflow.pyfunc
import pandas as pd
model_input = pd.DataFrame([range(10)])
loaded_model1 = mlflow.pyfunc.load_model("custom_model1")
print(f"Model1: {loaded_model1.predict(model_input)}")
loaded_model2 = mlflow.pyfunc.load_model("custom_model2")
print(f"Model2: {loaded_model2.predict(model_input)}")
```

The output should be 1 for custom_model1 and 2 for custom_model 2. But because of the bug the output is 1 for both.

### Other info / logs

_No response_

### What component(s) does this bug affect?

- [ ] `area/artifacts`: Artifact stores and artifact logging
- [ ] `area/build`: Build and test infrastructure for MLflow
- [ ] `area/docs`: MLflow documentation pages
- [ ] `area/examples`: Example code
- [ ] `area/model-registry`: Model Registry service, APIs, and the fluent client calls for Model Registry
- [X] `area/models`: MLmodel format, model serialization/deserialization, flavors
- [ ] `area/projects`: MLproject format, project running backends
- [ ] `area/scoring`: MLflow Model server, model deployment tools, Spark UDFs
- [ ] `area/server-infra`: MLflow Tracking server backend
- [ ] `area/tracking`: Tracking Service, tracking client APIs, autologging

### What interface(s) does this bug affect?

- [ ] `area/uiux`: Front-end, user experience, plotting, JavaScript, JavaScript dev server
- [ ] `area/docker`: Docker use across MLflow's components, such as MLflow Projects and MLflow Models
- [ ] `area/sqlalchemy`: Use of SQLAlchemy in the Tracking Service or Model Registry
- [ ] `area/windows`: Windows support

### What language(s) does this bug affect?

- [ ] `language/r`: R APIs and clients
- [ ] `language/java`: Java APIs and clients
- [ ] `language/new`: Proposals for new client languages

### What integration(s) does this bug affect?

- [ ] `integrations/azure`: Azure and Azure ML integrations
- [ ] `integrations/sagemaker`: SageMaker integrations
- [ ] `integrations/databricks`: Databricks integrations

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mlflow/utils/model_utils.py`
Content:
```
1 import os
2 import sys
3 
4 from mlflow.exceptions import MlflowException
5 from mlflow.models import Model
6 from mlflow.models.model import MLMODEL_FILE_NAME
7 from mlflow.protos.databricks_pb2 import RESOURCE_DOES_NOT_EXIST, RESOURCE_ALREADY_EXISTS
8 from mlflow.tracking.artifact_utils import _download_artifact_from_uri
9 from mlflow.utils.uri import append_to_uri_path
10 from mlflow.utils.file_utils import _copy_file_or_tree
11 
12 FLAVOR_CONFIG_CODE = "code"
13 
14 
15 def _get_flavor_configuration(model_path, flavor_name):
16     """
17     Obtains the configuration for the specified flavor from the specified
18     MLflow model path. If the model does not contain the specified flavor,
19     an exception will be thrown.
20 
21     :param model_path: The path to the root directory of the MLflow model for which to load
22                        the specified flavor configuration.
23     :param flavor_name: The name of the flavor configuration to load.
24     :return: The flavor configuration as a dictionary.
25     """
26     model_configuration_path = os.path.join(model_path, MLMODEL_FILE_NAME)
27     if not os.path.exists(model_configuration_path):
28         raise MlflowException(
29             'Could not find an "{model_file}" configuration file at "{model_path}"'.format(
30                 model_file=MLMODEL_FILE_NAME, model_path=model_path
31             ),
32             RESOURCE_DOES_NOT_EXIST,
33         )
34 
35     model_conf = Model.load(model_configuration_path)
36     if flavor_name not in model_conf.flavors:
37         raise MlflowException(
38             'Model does not have the "{flavor_name}" flavor'.format(flavor_name=flavor_name),
39             RESOURCE_DOES_NOT_EXIST,
40         )
41     conf = model_conf.flavors[flavor_name]
42     return conf
43 
44 
45 def _get_flavor_configuration_from_uri(model_uri, flavor_name):
46     """
47     Obtains the configuration for the specified flavor from the specified
48     MLflow model uri. If the model does not contain the specified flavor,
49     an exception will be thrown.
50 
51     :param model_uri: The path to the root directory of the MLflow model for which to load
52                        the specified flavor configuration.
53     :param flavor_name: The name of the flavor configuration to load.
54     :return: The flavor configuration as a dictionary.
55     """
56     try:
57         ml_model_file = _download_artifact_from_uri(
58             artifact_uri=append_to_uri_path(model_uri, MLMODEL_FILE_NAME)
59         )
60     except Exception as ex:
61         raise MlflowException(
62             'Failed to download an "{model_file}" model file from "{model_uri}": {ex}'.format(
63                 model_file=MLMODEL_FILE_NAME, model_uri=model_uri, ex=ex
64             ),
65             RESOURCE_DOES_NOT_EXIST,
66         )
67     model_conf = Model.load(ml_model_file)
68     if flavor_name not in model_conf.flavors:
69         raise MlflowException(
70             'Model does not have the "{flavor_name}" flavor'.format(flavor_name=flavor_name),
71             RESOURCE_DOES_NOT_EXIST,
72         )
73     return model_conf.flavors[flavor_name]
74 
75 
76 def _get_code_dirs(src_code_path, dst_code_path=None):
77     """
78     Obtains the names of the subdirectories contained under the specified source code
79     path and joins them with the specified destination code path.
80     :param src_code_path: The path of the source code directory for which to list subdirectories.
81     :param dst_code_path: The destination directory path to which subdirectory names should be
82                           joined.
83     """
84     if not dst_code_path:
85         dst_code_path = src_code_path
86     return [
87         (os.path.join(dst_code_path, x))
88         for x in os.listdir(src_code_path)
89         if os.path.isdir(os.path.join(src_code_path, x)) and not x == "__pycache__"
90     ]
91 
92 
93 def _validate_code_paths(code_paths):
94     if code_paths is not None:
95         if not isinstance(code_paths, list):
96             raise TypeError("Argument code_paths should be a list, not {}".format(type(code_paths)))
97 
98 
99 def _validate_and_copy_code_paths(code_paths, path, default_subpath="code"):
100     """
101     Validates that a code path is a valid list and copies the code paths to a directory. This
102     can later be used to log custom code as an artifact.
103 
104     :param code_paths: A list of files or directories containing code that should be logged
105     as artifacts
106     :param path: The local model path.
107     :param default_subpath: The default directory name used to store code artifacts.
108     """
109     _validate_code_paths(code_paths)
110     if code_paths is not None:
111         code_dir_subpath = default_subpath
112         for code_path in code_paths:
113             _copy_file_or_tree(src=code_path, dst=path, dst_dir=code_dir_subpath)
114     else:
115         code_dir_subpath = None
116     return code_dir_subpath
117 
118 
119 def _add_code_to_system_path(code_path):
120     sys.path = [code_path] + _get_code_dirs(code_path) + sys.path
121 
122 
123 def _validate_and_prepare_target_save_path(path):
124     if os.path.exists(path) and any(os.scandir(path)):
125         raise MlflowException(
126             message="Path '{}' already exists and is not empty".format(path),
127             error_code=RESOURCE_ALREADY_EXISTS,
128         )
129 
130     os.makedirs(path, exist_ok=True)
131 
132 
133 def _add_code_from_conf_to_system_path(local_path, conf, code_key=FLAVOR_CONFIG_CODE):
134     """
135     Checks if any code_paths were logged with the model in the flavor conf and prepends
136     the directory to the system path.
137 
138     :param local_path: The local path containing model artifacts.
139     :param conf: The flavor-specific conf that should contain the FLAVOR_CONFIG_CODE
140     key, which specifies the directory containing custom code logged as artifacts.
141     :param code_key: The key used by the flavor to indicate custom code artifacts.
142     By default this is FLAVOR_CONFIG_CODE.
143     """
144     if code_key in conf and conf[code_key]:
145         code_path = os.path.join(local_path, conf[code_key])
146         _add_code_to_system_path(code_path)
147
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mlflow/utils/model_utils.py b/mlflow/utils/model_utils.py
--- a/mlflow/utils/model_utils.py
+++ b/mlflow/utils/model_utils.py
@@ -1,5 +1,6 @@
 import os
 import sys
+from pathlib import Path
 
 from mlflow.exceptions import MlflowException
 from mlflow.models import Model
@@ -118,6 +119,13 @@
 
 def _add_code_to_system_path(code_path):
     sys.path = [code_path] + _get_code_dirs(code_path) + sys.path
+    # Delete cached modules so they will get reloaded anew from the correct code path
+    # Otherwise python will use the cached modules
+    modules = [
+        p.stem for p in Path(code_path).rglob("*.py") if p.is_file() and p.name != "__init__.py"
+    ]
+    for module in modules:
+        sys.modules.pop(module, None)
 
 
 def _validate_and_prepare_target_save_path(path):

{"golden_diff": "diff --git a/mlflow/utils/model_utils.py b/mlflow/utils/model_utils.py\n--- a/mlflow/utils/model_utils.py\n+++ b/mlflow/utils/model_utils.py\n@@ -1,5 +1,6 @@\n import os\n import sys\n+from pathlib import Path\n \n from mlflow.exceptions import MlflowException\n from mlflow.models import Model\n@@ -118,6 +119,13 @@\n \n def _add_code_to_system_path(code_path):\n     sys.path = [code_path] + _get_code_dirs(code_path) + sys.path\n+    # Delete cached modules so they will get reloaded anew from the correct code path\n+    # Otherwise python will use the cached modules\n+    modules = [\n+        p.stem for p in Path(code_path).rglob(\"*.py\") if p.is_file() and p.name != \"__init__.py\"\n+    ]\n+    for module in modules:\n+        sys.modules.pop(module, None)\n \n \n def _validate_and_prepare_target_save_path(path):\n", "issue": "Two models one code name \n### Willingness to contribute\r\n\r\nYes. I can contribute a fix for this bug independently.\r\n\r\n### System information\r\n\r\n- **Have I written custom code (as opposed to using a stock example script provided in MLflow)**: custom code\r\n- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: 20.04\r\n- **MLflow installed from (source or binary)**: source\r\n- **MLflow version (run ``mlflow --version``)**: 1.23.1\r\n- **Python version**: 3.9\r\n- **yarn version, if running the dev UI**: N/A\r\n\r\n\r\n### Describe the problem\r\n\r\nWhen two mlflow models have the same name for the code packaged with them, for example: a preprocessing code name `prep_features` was packaged with two different mlflow models. If the first mlflow model is loaded, then the second one is also loaded, python will only load the `prep_features` module once. This leads to problems if `prep_features` for the second model is different from the first model.\r\n\r\n\r\n\r\n### Tracking information\r\n\r\n_No response_\r\n\r\n### Code to reproduce issue\r\n\r\nprep_features. py change 1 to 2 when creating custom_model2 with the 2m1cn.py script\r\n```python\r\ndef preprocess_features():\r\n    return 1 # 2 for custom_model2\r\n```\r\n2m1cn.py use this file to create custom_model1 and custom_model2 \r\n```python\r\nimport mlflow.pyfunc\r\n\r\nclass CM(mlflow.pyfunc.PythonModel):\r\n    def __init__(self):\r\n        pass\r\n    def predict(self, context, model_input):\r\n        from prep_features import preprocess_features\r\n        return preprocess_features()\r\n\r\n# Construct and save the model\r\nmodel_path = \"custom_model1\" # \"custom_model2\"\r\ncode_path = [\"prep_features.py\"]\r\ncustom_model = CM()\r\nmlflow.pyfunc.save_model(path=model_path, python_model=custom_model, code_path=code_path)\r\n```\r\n\r\ntest.py now use this file to test your created models\r\n```python\r\n# Evaluate the models\r\nimport mlflow.pyfunc\r\nimport pandas as pd\r\nmodel_input = pd.DataFrame([range(10)])\r\nloaded_model1 = mlflow.pyfunc.load_model(\"custom_model1\")\r\nprint(f\"Model1: {loaded_model1.predict(model_input)}\")\r\nloaded_model2 = mlflow.pyfunc.load_model(\"custom_model2\")\r\nprint(f\"Model2: {loaded_model2.predict(model_input)}\")\r\n```\r\n\r\nThe output should be 1 for custom_model1 and 2 for custom_model 2. But because of the bug the output is 1 for both.\r\n\r\n### Other info / logs\r\n\r\n_No response_\r\n\r\n### What component(s) does this bug affect?\r\n\r\n- [ ] `area/artifacts`: Artifact stores and artifact logging\r\n- [ ] `area/build`: Build and test infrastructure for MLflow\r\n- [ ] `area/docs`: MLflow documentation pages\r\n- [ ] `area/examples`: Example code\r\n- [ ] `area/model-registry`: Model Registry service, APIs, and the fluent client calls for Model Registry\r\n- [X] `area/models`: MLmodel format, model serialization/deserialization, flavors\r\n- [ ] `area/projects`: MLproject format, project running backends\r\n- [ ] `area/scoring`: MLflow Model server, model deployment tools, Spark UDFs\r\n- [ ] `area/server-infra`: MLflow Tracking server backend\r\n- [ ] `area/tracking`: Tracking Service, tracking client APIs, autologging\r\n\r\n### What interface(s) does this bug affect?\r\n\r\n- [ ] `area/uiux`: Front-end, user experience, plotting, JavaScript, JavaScript dev server\r\n- [ ] `area/docker`: Docker use across MLflow's components, such as MLflow Projects and MLflow Models\r\n- [ ] `area/sqlalchemy`: Use of SQLAlchemy in the Tracking Service or Model Registry\r\n- [ ] `area/windows`: Windows support\r\n\r\n### What language(s) does this bug affect?\r\n\r\n- [ ] `language/r`: R APIs and clients\r\n- [ ] `language/java`: Java APIs and clients\r\n- [ ] `language/new`: Proposals for new client languages\r\n\r\n### What integration(s) does this bug affect?\r\n\r\n- [ ] `integrations/azure`: Azure and Azure ML integrations\r\n- [ ] `integrations/sagemaker`: SageMaker integrations\r\n- [ ] `integrations/databricks`: Databricks integrations\n", "before_files": [{"content": "import os\nimport sys\n\nfrom mlflow.exceptions import MlflowException\nfrom mlflow.models import Model\nfrom mlflow.models.model import MLMODEL_FILE_NAME\nfrom mlflow.protos.databricks_pb2 import RESOURCE_DOES_NOT_EXIST, RESOURCE_ALREADY_EXISTS\nfrom mlflow.tracking.artifact_utils import _download_artifact_from_uri\nfrom mlflow.utils.uri import append_to_uri_path\nfrom mlflow.utils.file_utils import _copy_file_or_tree\n\nFLAVOR_CONFIG_CODE = \"code\"\n\n\ndef _get_flavor_configuration(model_path, flavor_name):\n    \"\"\"\n    Obtains the configuration for the specified flavor from the specified\n    MLflow model path. If the model does not contain the specified flavor,\n    an exception will be thrown.\n\n    :param model_path: The path to the root directory of the MLflow model for which to load\n                       the specified flavor configuration.\n    :param flavor_name: The name of the flavor configuration to load.\n    :return: The flavor configuration as a dictionary.\n    \"\"\"\n    model_configuration_path = os.path.join(model_path, MLMODEL_FILE_NAME)\n    if not os.path.exists(model_configuration_path):\n        raise MlflowException(\n            'Could not find an \"{model_file}\" configuration file at \"{model_path}\"'.format(\n                model_file=MLMODEL_FILE_NAME, model_path=model_path\n            ),\n            RESOURCE_DOES_NOT_EXIST,\n        )\n\n    model_conf = Model.load(model_configuration_path)\n    if flavor_name not in model_conf.flavors:\n        raise MlflowException(\n            'Model does not have the \"{flavor_name}\" flavor'.format(flavor_name=flavor_name),\n            RESOURCE_DOES_NOT_EXIST,\n        )\n    conf = model_conf.flavors[flavor_name]\n    return conf\n\n\ndef _get_flavor_configuration_from_uri(model_uri, flavor_name):\n    \"\"\"\n    Obtains the configuration for the specified flavor from the specified\n    MLflow model uri. If the model does not contain the specified flavor,\n    an exception will be thrown.\n\n    :param model_uri: The path to the root directory of the MLflow model for which to load\n                       the specified flavor configuration.\n    :param flavor_name: The name of the flavor configuration to load.\n    :return: The flavor configuration as a dictionary.\n    \"\"\"\n    try:\n        ml_model_file = _download_artifact_from_uri(\n            artifact_uri=append_to_uri_path(model_uri, MLMODEL_FILE_NAME)\n        )\n    except Exception as ex:\n        raise MlflowException(\n            'Failed to download an \"{model_file}\" model file from \"{model_uri}\": {ex}'.format(\n                model_file=MLMODEL_FILE_NAME, model_uri=model_uri, ex=ex\n            ),\n            RESOURCE_DOES_NOT_EXIST,\n        )\n    model_conf = Model.load(ml_model_file)\n    if flavor_name not in model_conf.flavors:\n        raise MlflowException(\n            'Model does not have the \"{flavor_name}\" flavor'.format(flavor_name=flavor_name),\n            RESOURCE_DOES_NOT_EXIST,\n        )\n    return model_conf.flavors[flavor_name]\n\n\ndef _get_code_dirs(src_code_path, dst_code_path=None):\n    \"\"\"\n    Obtains the names of the subdirectories contained under the specified source code\n    path and joins them with the specified destination code path.\n    :param src_code_path: The path of the source code directory for which to list subdirectories.\n    :param dst_code_path: The destination directory path to which subdirectory names should be\n                          joined.\n    \"\"\"\n    if not dst_code_path:\n        dst_code_path = src_code_path\n    return [\n        (os.path.join(dst_code_path, x))\n        for x in os.listdir(src_code_path)\n        if os.path.isdir(os.path.join(src_code_path, x)) and not x == \"__pycache__\"\n    ]\n\n\ndef _validate_code_paths(code_paths):\n    if code_paths is not None:\n        if not isinstance(code_paths, list):\n            raise TypeError(\"Argument code_paths should be a list, not {}\".format(type(code_paths)))\n\n\ndef _validate_and_copy_code_paths(code_paths, path, default_subpath=\"code\"):\n    \"\"\"\n    Validates that a code path is a valid list and copies the code paths to a directory. This\n    can later be used to log custom code as an artifact.\n\n    :param code_paths: A list of files or directories containing code that should be logged\n    as artifacts\n    :param path: The local model path.\n    :param default_subpath: The default directory name used to store code artifacts.\n    \"\"\"\n    _validate_code_paths(code_paths)\n    if code_paths is not None:\n        code_dir_subpath = default_subpath\n        for code_path in code_paths:\n            _copy_file_or_tree(src=code_path, dst=path, dst_dir=code_dir_subpath)\n    else:\n        code_dir_subpath = None\n    return code_dir_subpath\n\n\ndef _add_code_to_system_path(code_path):\n    sys.path = [code_path] + _get_code_dirs(code_path) + sys.path\n\n\ndef _validate_and_prepare_target_save_path(path):\n    if os.path.exists(path) and any(os.scandir(path)):\n        raise MlflowException(\n            message=\"Path '{}' already exists and is not empty\".format(path),\n            error_code=RESOURCE_ALREADY_EXISTS,\n        )\n\n    os.makedirs(path, exist_ok=True)\n\n\ndef _add_code_from_conf_to_system_path(local_path, conf, code_key=FLAVOR_CONFIG_CODE):\n    \"\"\"\n    Checks if any code_paths were logged with the model in the flavor conf and prepends\n    the directory to the system path.\n\n    :param local_path: The local path containing model artifacts.\n    :param conf: The flavor-specific conf that should contain the FLAVOR_CONFIG_CODE\n    key, which specifies the directory containing custom code logged as artifacts.\n    :param code_key: The key used by the flavor to indicate custom code artifacts.\n    By default this is FLAVOR_CONFIG_CODE.\n    \"\"\"\n    if code_key in conf and conf[code_key]:\n        code_path = os.path.join(local_path, conf[code_key])\n        _add_code_to_system_path(code_path)\n", "path": "mlflow/utils/model_utils.py"}], "after_files": [{"content": "import os\nimport sys\nfrom pathlib import Path\n\nfrom mlflow.exceptions import MlflowException\nfrom mlflow.models import Model\nfrom mlflow.models.model import MLMODEL_FILE_NAME\nfrom mlflow.protos.databricks_pb2 import RESOURCE_DOES_NOT_EXIST, RESOURCE_ALREADY_EXISTS\nfrom mlflow.tracking.artifact_utils import _download_artifact_from_uri\nfrom mlflow.utils.uri import append_to_uri_path\nfrom mlflow.utils.file_utils import _copy_file_or_tree\n\nFLAVOR_CONFIG_CODE = \"code\"\n\n\ndef _get_flavor_configuration(model_path, flavor_name):\n    \"\"\"\n    Obtains the configuration for the specified flavor from the specified\n    MLflow model path. If the model does not contain the specified flavor,\n    an exception will be thrown.\n\n    :param model_path: The path to the root directory of the MLflow model for which to load\n                       the specified flavor configuration.\n    :param flavor_name: The name of the flavor configuration to load.\n    :return: The flavor configuration as a dictionary.\n    \"\"\"\n    model_configuration_path = os.path.join(model_path, MLMODEL_FILE_NAME)\n    if not os.path.exists(model_configuration_path):\n        raise MlflowException(\n            'Could not find an \"{model_file}\" configuration file at \"{model_path}\"'.format(\n                model_file=MLMODEL_FILE_NAME, model_path=model_path\n            ),\n            RESOURCE_DOES_NOT_EXIST,\n        )\n\n    model_conf = Model.load(model_configuration_path)\n    if flavor_name not in model_conf.flavors:\n        raise MlflowException(\n            'Model does not have the \"{flavor_name}\" flavor'.format(flavor_name=flavor_name),\n            RESOURCE_DOES_NOT_EXIST,\n        )\n    conf = model_conf.flavors[flavor_name]\n    return conf\n\n\ndef _get_flavor_configuration_from_uri(model_uri, flavor_name):\n    \"\"\"\n    Obtains the configuration for the specified flavor from the specified\n    MLflow model uri. If the model does not contain the specified flavor,\n    an exception will be thrown.\n\n    :param model_uri: The path to the root directory of the MLflow model for which to load\n                       the specified flavor configuration.\n    :param flavor_name: The name of the flavor configuration to load.\n    :return: The flavor configuration as a dictionary.\n    \"\"\"\n    try:\n        ml_model_file = _download_artifact_from_uri(\n            artifact_uri=append_to_uri_path(model_uri, MLMODEL_FILE_NAME)\n        )\n    except Exception as ex:\n        raise MlflowException(\n            'Failed to download an \"{model_file}\" model file from \"{model_uri}\": {ex}'.format(\n                model_file=MLMODEL_FILE_NAME, model_uri=model_uri, ex=ex\n            ),\n            RESOURCE_DOES_NOT_EXIST,\n        )\n    model_conf = Model.load(ml_model_file)\n    if flavor_name not in model_conf.flavors:\n        raise MlflowException(\n            'Model does not have the \"{flavor_name}\" flavor'.format(flavor_name=flavor_name),\n            RESOURCE_DOES_NOT_EXIST,\n        )\n    return model_conf.flavors[flavor_name]\n\n\ndef _get_code_dirs(src_code_path, dst_code_path=None):\n    \"\"\"\n    Obtains the names of the subdirectories contained under the specified source code\n    path and joins them with the specified destination code path.\n    :param src_code_path: The path of the source code directory for which to list subdirectories.\n    :param dst_code_path: The destination directory path to which subdirectory names should be\n                          joined.\n    \"\"\"\n    if not dst_code_path:\n        dst_code_path = src_code_path\n    return [\n        (os.path.join(dst_code_path, x))\n        for x in os.listdir(src_code_path)\n        if os.path.isdir(os.path.join(src_code_path, x)) and not x == \"__pycache__\"\n    ]\n\n\ndef _validate_code_paths(code_paths):\n    if code_paths is not None:\n        if not isinstance(code_paths, list):\n            raise TypeError(\"Argument code_paths should be a list, not {}\".format(type(code_paths)))\n\n\ndef _validate_and_copy_code_paths(code_paths, path, default_subpath=\"code\"):\n    \"\"\"\n    Validates that a code path is a valid list and copies the code paths to a directory. This\n    can later be used to log custom code as an artifact.\n\n    :param code_paths: A list of files or directories containing code that should be logged\n    as artifacts\n    :param path: The local model path.\n    :param default_subpath: The default directory name used to store code artifacts.\n    \"\"\"\n    _validate_code_paths(code_paths)\n    if code_paths is not None:\n        code_dir_subpath = default_subpath\n        for code_path in code_paths:\n            _copy_file_or_tree(src=code_path, dst=path, dst_dir=code_dir_subpath)\n    else:\n        code_dir_subpath = None\n    return code_dir_subpath\n\n\ndef _add_code_to_system_path(code_path):\n    sys.path = [code_path] + _get_code_dirs(code_path) + sys.path\n    # Delete cached modules so they will get reloaded anew from the correct code path\n    # Otherwise python will use the cached modules\n    modules = [\n        p.stem for p in Path(code_path).rglob(\"*.py\") if p.is_file() and p.name != \"__init__.py\"\n    ]\n    for module in modules:\n        sys.modules.pop(module, None)\n\n\ndef _validate_and_prepare_target_save_path(path):\n    if os.path.exists(path) and any(os.scandir(path)):\n        raise MlflowException(\n            message=\"Path '{}' already exists and is not empty\".format(path),\n            error_code=RESOURCE_ALREADY_EXISTS,\n        )\n\n    os.makedirs(path, exist_ok=True)\n\n\ndef _add_code_from_conf_to_system_path(local_path, conf, code_key=FLAVOR_CONFIG_CODE):\n    \"\"\"\n    Checks if any code_paths were logged with the model in the flavor conf and prepends\n    the directory to the system path.\n\n    :param local_path: The local path containing model artifacts.\n    :param conf: The flavor-specific conf that should contain the FLAVOR_CONFIG_CODE\n    key, which specifies the directory containing custom code logged as artifacts.\n    :param code_key: The key used by the flavor to indicate custom code artifacts.\n    By default this is FLAVOR_CONFIG_CODE.\n    \"\"\"\n    if code_key in conf and conf[code_key]:\n        code_path = os.path.join(local_path, conf[code_key])\n        _add_code_to_system_path(code_path)\n", "path": "mlflow/utils/model_utils.py"}]}