Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions .sg/rules/os-environ-usage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
id: os-environ-usage
message: Use `ddtrace.settings._env` instead of `os` to access environment variables
severity: error
language: python
files:
- "ddtrace/**"
ignores:
- "ddtrace/settings/_env.py"
rule:
any:
# Match os.environ access patterns
- pattern: os.environ
- pattern: os.environ[$$$ARGS]
- pattern: os.environ.get($$$ARGS)
- pattern: os.environ.keys($$$ARGS)
- pattern: os.environ.values($$$ARGS)
- pattern: os.environ.items($$$ARGS)
- pattern: os.environ.copy($$$ARGS)
- pattern: os.environ.clear($$$ARGS)
- pattern: os.environ.update($$$ARGS)
- pattern: os.environ.pop($$$ARGS)
- pattern: os.environ.setdefault($$$ARGS)

# Match os.getenv() calls
- pattern: os.getenv($$$ARGS)

# Match direct imports and usage of environ
- pattern: from os import environ
- pattern: from os import environ as $ALIAS
- pattern: from os import $$$IMPORTS, environ
- pattern: from os import $$$IMPORTS, environ as $ALIAS
- pattern: from os import environ, $$$IMPORTS
- pattern: from os import environ as $ALIAS, $$$IMPORTS

# Match direct imports and usage of getenv
- pattern: from os import getenv
- pattern: from os import getenv as $ALIAS
- pattern: from os import $$$IMPORTS, getenv
- pattern: from os import $$$IMPORTS, getenv as $ALIAS
- pattern: from os import getenv, $$$IMPORTS
- pattern: from os import getenv as $ALIAS, $$$IMPORTS

# Match usage of imported environ (direct name access)
- pattern: environ[$$$ARGS]
has:
kind: module
pattern: |
from os import environ
- pattern: environ.get($$$ARGS)
has:
kind: module
pattern: |
from os import environ
- pattern: environ.keys($$$ARGS)
has:
kind: module
pattern: |
from os import environ
- pattern: environ.values($$$ARGS)
has:
kind: module
pattern: |
from os import environ
- pattern: environ.items($$$ARGS)
has:
kind: module
pattern: |
from os import environ

# Match usage of imported getenv
- pattern: getenv($$$ARGS)
has:
kind: module
pattern: |
from os import getenv

note: |
Direct access to os.environ or os.getenv is not allowed in this codebase.

Instead, use the centralized environment variable helper `ddtrace.settings._env`

Before:
import os
value = os.environ["HOME"]
debug = os.getenv("DEBUG", "false")

After:
from ddtrace.settings import _env
value = _env.environ["HOME"]
debug = _env.getenv("DEBUG", "false")

This ensures consistent environment variable handling across the codebase.

247 changes: 247 additions & 0 deletions .sg/tests/__snapshots__/os-environ-usage-snapshot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
id: os-environ-usage
snapshots:
from os import environ:
labels:
- source: from os import environ
style: primary
start: 0
end: 22
? |
from os import environ
env_keys = environ.keys()
: labels:
- source: from os import environ
style: primary
start: 0
end: 22
? |
from os import environ
value = environ.get("SHELL")
: labels:
- source: from os import environ
style: primary
start: 0
end: 22
? |
from os import environ
value = environ["USER"]
: labels:
- source: from os import environ
style: primary
start: 0
end: 22
from os import environ as env_dict:
labels:
- source: from os import environ as env_dict
style: primary
start: 0
end: 34
? |
from os import environ as env_dict
value = env_dict.get("PATH")
: labels:
- source: from os import environ as env_dict
style: primary
start: 0
end: 34
? |
from os import environ as env_dict
value = env_dict["HOME"]
: labels:
- source: from os import environ as env_dict
style: primary
start: 0
end: 34
from os import environ, getenv:
labels:
- source: from os import environ, getenv
style: primary
start: 0
end: 30
from os import getenv:
labels:
- source: from os import getenv
style: primary
start: 0
end: 21
? |
from os import getenv
value = getenv("CONFIG")
: labels:
- source: from os import getenv
style: primary
start: 0
end: 21
? |
from os import getenv
value = getenv("MODE", "production")
: labels:
- source: from os import getenv
style: primary
start: 0
end: 21
from os import getenv as get_env_func:
labels:
- source: from os import getenv as get_env_func
style: primary
start: 0
end: 37
? |
from os import getenv as get_env_func
value = get_env_func("LEVEL")
: labels:
- source: from os import getenv as get_env_func
style: primary
start: 0
end: 37
? |
from os import getenv as get_env_func
value = get_env_func("PORT", "8080")
: labels:
- source: from os import getenv as get_env_func
style: primary
start: 0
end: 37
from os import getenv, environ:
labels:
- source: from os import getenv, environ
style: primary
start: 0
end: 30
from os import path, environ, getenv:
labels:
- source: from os import path, environ, getenv
style: primary
start: 0
end: 36
? |
import os
all_items = os.environ.items()
: labels:
- source: os.environ.items()
style: primary
start: 22
end: 40
? |
import os
all_keys = os.environ.keys()
: labels:
- source: os.environ.keys()
style: primary
start: 21
end: 38
? |
import os
all_values = os.environ.values()
: labels:
- source: os.environ.values()
style: primary
start: 23
end: 42
? |
import os
default_val = os.environ.setdefault("DEF", "default")
: labels:
- source: os.environ.setdefault("DEF", "default")
style: primary
start: 24
end: 63
? |
import os
env_copy = os.environ.copy()
: labels:
- source: os.environ.copy()
style: primary
start: 21
end: 38
? |
import os
env_ref = os.environ
: labels:
- source: os.environ
style: primary
start: 20
end: 30
? |
import os
for k, v in os.environ.items():
pass
: labels:
- source: os.environ.items()
style: primary
start: 22
end: 40
? |
import os
for key in os.environ:
pass
: labels:
- source: os.environ
style: primary
start: 21
end: 31
? |
import os
if "HOME" in os.environ:
pass
: labels:
- source: os.environ
style: primary
start: 23
end: 33
? |
import os
os.environ.clear()
: labels:
- source: os.environ.clear()
style: primary
start: 10
end: 28
? |
import os
os.environ.update({"NEW_VAR": "value"})
: labels:
- source: 'os.environ.update({"NEW_VAR": "value"})'
style: primary
start: 10
end: 49
? |
import os
removed = os.environ.pop("TEMP_VAR", None)
: labels:
- source: os.environ.pop("TEMP_VAR", None)
style: primary
start: 20
end: 52
? |
import os
value = os.environ.get("PATH")
: labels:
- source: os.environ.get("PATH")
style: primary
start: 18
end: 40
? |
import os
value = os.environ["HOME"]
: labels:
- source: os.environ["HOME"]
style: primary
start: 18
end: 36
? |
import os
value = os.getenv("DEBUG")
: labels:
- source: os.getenv("DEBUG")
style: primary
start: 18
end: 36
? |
import os
value = os.getenv("TIMEOUT", "30")
: labels:
- source: os.getenv("TIMEOUT", "30")
style: primary
start: 18
end: 44
Loading
Loading