Repository: wandb/wandb

Issue:
[Feature]: Allow to disable code saving from tracking code
### Description

Currently, a user can enable code saving from the UI settings and Wandb will send the entry-point code to the tracking service.

If Wandb logging is integrated in other applications, it would be crucial for app developers to disable code saving. Allowing this feature to be enabled from user side, instead of from app developer side, can have bad repercussions.

### Suggested Solution

Allow to force-disable any code saving from application code.

### Alternatives

_No response_

### Additional Context

_No response_


Discussion:
Hey @psinger you can set the `WANDB_DISABLE_CODE` environment variable to true, or you can call `wandb.init(save_code=False)`
@vanpelt thanks - but that's what I already tried

Changing the client setting in the UI appears to override these settings.
Could you please re-open this issue?
@psinger can you give us a code snippet that is exhibiting the behavior you're seeing?  The [existing logic](https://github.com/wandb/client/blob/master/wandb/sdk/wandb_init.py#L252-L255) should ensure that if a given team has code_saving disabled on the server a user can not manually enable it, this is by design.
@vanpelt I opened another issue, so we can close one of them.

The replication is simple:
- Enable code saving in UI
- Disable code saving in code (by environment variable and init flag)

Then I can still see the code being logged in an experiment in the UI.

If I understand the code snippet you linked, it only disables code saving, if user disables it in the UI.
But here it is the other way around, I want to disable it if it is explicitly disabled in the code.
Thanks @psinger we've created a ticket and hope to have a fix in the next cli release.  Code saving is a special case setting that we don't want to allow overrides when it's set to false but do when it's set to true so this got missed in a recent refactor.  As a workaround in the current affected releases you can do:  `wandb.run._settings.update(save_code=False)` after calling `wandb.init`.

Resolving patch:
diff --git a/wandb/sdk/wandb_init.py b/wandb/sdk/wandb_init.py
--- a/wandb/sdk/wandb_init.py
+++ b/wandb/sdk/wandb_init.py
@@ -256,7 +256,7 @@ def setup(self, kwargs) -> None:  # noqa: C901
             settings._apply_user(user_settings)
 
         # ensure that user settings don't set saving to true
-        # if user explicitly set these to false
+        # if user explicitly set these to false in UI
         if save_code_pre_user_settings is False:
             settings.update({"save_code": False}, source=Source.INIT)
 
diff --git a/wandb/sdk/wandb_settings.py b/wandb/sdk/wandb_settings.py
--- a/wandb/sdk/wandb_settings.py
+++ b/wandb/sdk/wandb_settings.py
@@ -518,8 +518,8 @@ def _default_props(self) -> Dict[str, Dict[str, Any]]:
                 "hook": lambda _: "local" if self.is_local else "cloud",
                 "auto_hook": True,
             },
-            disable_code={"preprocessor": _str_as_bool, "is_policy": True},
-            disable_git={"preprocessor": _str_as_bool, "is_policy": True},
+            disable_code={"preprocessor": _str_as_bool},
+            disable_git={"preprocessor": _str_as_bool},
             disabled={"value": False, "preprocessor": _str_as_bool},
             files_dir={
                 "value": "files",
@@ -588,7 +588,7 @@ def _default_props(self) -> Dict[str, Dict[str, Any]]:
             },
             run_url={"hook": lambda _: self._run_url(), "auto_hook": True},
             sagemaker_disable={"preprocessor": _str_as_bool},
-            save_code={"preprocessor": _str_as_bool, "is_policy": True},
+            save_code={"preprocessor": _str_as_bool},
             settings_system={
                 "value": os.path.join("~", ".config", "wandb", "settings"),
                 "hook": lambda x: self._path_convert(x),


Test patch:
diff --git a/tests/wandb_run_test.py b/tests/wandb_run_test.py
--- a/tests/wandb_run_test.py
+++ b/tests/wandb_run_test.py
@@ -146,14 +146,13 @@ def test_log_code_env(live_mock_server, test_settings, save_code):
         with open("test.py", "w") as f:
             f.write('print("test")')
 
-        # first, ditch user preference for code saving
-        # since it has higher priority for policy settings
-        live_mock_server.set_ctx({"code_saving_enabled": None})
-        # note that save_code is a policy by definition
+        # simulate user turning on code saving in UI
+        live_mock_server.set_ctx({"code_saving_enabled": True})
         test_settings.update(
-            save_code=None,
-            code_dir=".",
-            source=wandb.sdk.wandb_settings.Source.SETTINGS,
+            save_code=None, source=wandb.sdk.wandb_settings.Source.BASE,
+        )
+        test_settings.update(
+            code_dir=".", source=wandb.sdk.wandb_settings.Source.SETTINGS
         )
         run = wandb.init(settings=test_settings)
         assert run._settings.save_code is save_code
diff --git a/tests/wandb_settings_test.py b/tests/wandb_settings_test.py
--- a/tests/wandb_settings_test.py
+++ b/tests/wandb_settings_test.py
@@ -472,26 +472,18 @@ def test_preprocess_base_url(url, processed_url):
 
 
 def test_code_saving_save_code_env_false(live_mock_server, test_settings):
+    test_settings.update({"save_code": None}, source=Source.BASE)
     with mock.patch.dict("os.environ", WANDB_SAVE_CODE="false"):
-        # first, ditch user preference for code saving
-        # since it has higher priority for policy settings
-        live_mock_server.set_ctx({"code_saving_enabled": None})
-        # note that save_code is a policy by definition
-        test_settings.update({"save_code": None}, source=Source.SETTINGS)
         run = wandb.init(settings=test_settings)
-        assert run._settings.save_code is False
+        assert run.settings.save_code is False
         run.finish()
 
 
 def test_code_saving_disable_code(live_mock_server, test_settings):
+    test_settings.update({"save_code": None}, source=Source.BASE)
     with mock.patch.dict("os.environ", WANDB_DISABLE_CODE="true"):
-        # first, ditch user preference for code saving
-        # since it has higher priority for policies
-        live_mock_server.set_ctx({"code_saving_enabled": None})
-        # note that save_code is a policy by definition
-        test_settings.update({"save_code": None}, source=Source.SETTINGS)
         run = wandb.init(settings=test_settings)
-        assert run._settings.save_code is False
+        assert run.settings.save_code is False
         run.finish()