diff --git a/.changes/unreleased/Features-20220406-080328.yaml b/.changes/unreleased/Features-20220406-080328.yaml new file mode 100644 index 00000000000..f6af4e42d1b --- /dev/null +++ b/.changes/unreleased/Features-20220406-080328.yaml @@ -0,0 +1,7 @@ +kind: Features +body: Support the DO_NOT_TRACK environment variable from the consoledonottrack.com initiative +time: 2022-04-06T08:03:28.877054+02:00 +custom: + Author: agoblet + Issue: "3540" + PR: "5000" diff --git a/core/dbt/flags.py b/core/dbt/flags.py index 3cb42d65a73..e0e16244649 100644 --- a/core/dbt/flags.py +++ b/core/dbt/flags.py @@ -36,6 +36,16 @@ EVENT_BUFFER_SIZE = 100000 QUIET = None +_NON_BOOLEAN_FLAGS = [ + "LOG_FORMAT", + "PRINTER_WIDTH", + "PROFILES_DIR", + "INDIRECT_SELECTION", + "EVENT_BUFFER_SIZE", +] + +_NON_DBT_ENV_FLAGS = ["DO_NOT_TRACK"] + # Global CLI defaults. These flags are set from three places: # CLI args, environment variables, and user_config (profiles.yml). # Environment variables use the pattern 'DBT_{flag name}', like DBT_PROFILES_DIR @@ -133,31 +143,22 @@ def set_from_args(args, user_config): EVENT_BUFFER_SIZE = get_flag_value("EVENT_BUFFER_SIZE", args, user_config) QUIET = get_flag_value("QUIET", args, user_config) + _set_overrides_from_env() -def get_flag_value(flag, args, user_config): - lc_flag = flag.lower() - flag_value = getattr(args, lc_flag, None) + +def _set_overrides_from_env(): + global SEND_ANONYMOUS_USAGE_STATS + + flag_value = _get_flag_value_from_env("DO_NOT_TRACK") if flag_value is None: - # Environment variables use pattern 'DBT_{flag name}' - env_flag = f"DBT_{flag}" - env_value = os.getenv(env_flag) - if env_value is not None and env_value != "": - env_value = env_value.lower() - # non Boolean values - if flag in [ - "LOG_FORMAT", - "PRINTER_WIDTH", - "PROFILES_DIR", - "INDIRECT_SELECTION", - "EVENT_BUFFER_SIZE", - ]: - flag_value = env_value - else: - flag_value = env_set_bool(env_value) - elif user_config is not None and getattr(user_config, lc_flag, None) is not None: - flag_value = getattr(user_config, lc_flag) - else: - flag_value = flag_defaults[flag] + return + + SEND_ANONYMOUS_USAGE_STATS = not flag_value + + +def get_flag_value(flag, args, user_config): + flag_value = _load_flag_value(flag, args, user_config) + if flag in ["PRINTER_WIDTH", "EVENT_BUFFER_SIZE"]: # must be ints flag_value = int(flag_value) if flag == "PROFILES_DIR": @@ -166,6 +167,42 @@ def get_flag_value(flag, args, user_config): return flag_value +def _load_flag_value(flag, args, user_config): + lc_flag = flag.lower() + flag_value = getattr(args, lc_flag, None) + if flag_value is not None: + return flag_value + + flag_value = _get_flag_value_from_env(flag) + if flag_value is not None: + return flag_value + + if user_config is not None and getattr(user_config, lc_flag, None) is not None: + return getattr(user_config, lc_flag) + + return flag_defaults[flag] + + +def _get_flag_value_from_env(flag): + # Environment variables use pattern 'DBT_{flag name}' + env_flag = _get_env_flag(flag) + env_value = os.getenv(env_flag) + if env_value is None or env_value == "": + return None + + env_value = env_value.lower() + if flag in _NON_BOOLEAN_FLAGS: + flag_value = env_value + else: + flag_value = env_set_bool(env_value) + + return flag_value + + +def _get_env_flag(flag): + return flag if flag in _NON_DBT_ENV_FLAGS else f"DBT_{flag}" + + def get_flag_dict(): return { "use_experimental_parser": USE_EXPERIMENTAL_PARSER, diff --git a/dev-requirements.txt b/dev-requirements.txt index d7198674bff..cd36ec45ce2 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,4 +1,4 @@ -black==22.1.0 +black==22.3.0 bumpversion flake8 flaky diff --git a/test/unit/test_flags.py b/test/unit/test_flags.py index 845e7d6c156..8415540ffdd 100644 --- a/test/unit/test_flags.py +++ b/test/unit/test_flags.py @@ -178,8 +178,12 @@ def test__flags(self): setattr(self.args, 'send_anonymous_usage_stats', True) flags.set_from_args(self.args, self.user_config) self.assertEqual(flags.SEND_ANONYMOUS_USAGE_STATS, True) + os.environ['DO_NOT_TRACK'] = '1' + flags.set_from_args(self.args, self.user_config) + self.assertEqual(flags.SEND_ANONYMOUS_USAGE_STATS, False) # cleanup os.environ.pop('DBT_SEND_ANONYMOUS_USAGE_STATS') + os.environ.pop('DO_NOT_TRACK') delattr(self.args, 'send_anonymous_usage_stats') # printer_width diff --git a/test/unit/test_tracking.py b/test/unit/test_tracking.py index 3f0165d5d5c..a247734d53f 100644 --- a/test/unit/test_tracking.py +++ b/test/unit/test_tracking.py @@ -71,3 +71,16 @@ def test_disable_never_enabled(self): assert dbt.tracking.active_user.id is None assert isinstance(dbt.tracking.active_user.invocation_id, str) assert isinstance(dbt.tracking.active_user.run_started_at, datetime.datetime) + + def test_initialize_from_flags(self): + for send_aonymous_usage_stats in [True, False]: + with self.subTest( + send_aonymous_usage_stats=send_aonymous_usage_stats + ): + dbt.tracking.flags.SEND_ANONYMOUS_USAGE_STATS = ( + send_aonymous_usage_stats + ) + + dbt.tracking.initialize_from_flags() + + assert dbt.tracking.active_user.do_not_track != send_aonymous_usage_stats