Skip to content

fix config path & format #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jul 20, 2022
4 changes: 2 additions & 2 deletions docs/gen_ref_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
elif parts[-1] == "__main__":
continue

with mkdocs_gen_files.open(full_doc_path, "w") as fd:
with mkdocs_gen_files.open(full_doc_path, "w") as fobj:
identifier = ".".join(parts)
print("::: " + identifier, file=fd)
print("::: " + identifier, file=fobj)

mkdocs_gen_files.set_edit_path(full_doc_path, path)
73 changes: 49 additions & 24 deletions src/iterative_telemetry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import sys
import uuid
from functools import lru_cache
from pathlib import Path
from threading import Thread
from typing import Any, Callable, Dict, Union

Expand Down Expand Up @@ -74,8 +75,7 @@ def is_enabled(self):
return (
os.environ.get(DO_NOT_TRACK_ENV, None) is None and self.enabled()
if callable(self.enabled)
else self.enabled
and _find_or_create_user_id() != DO_NOT_TRACK_VALUE
else self.enabled and _find_or_create_user_id() is not None
)

def send(
Expand Down Expand Up @@ -154,7 +154,7 @@ def _runtime_info(self):
# "scm_class": _scm_in_use(),
**_system_info(),
"user_id": _find_or_create_user_id(),
"group_id": _find_or_create_user_id(), # TODO
"group_id": "", # TODO
}


Expand Down Expand Up @@ -187,39 +187,64 @@ def _system_info():
raise NotImplementedError


def _generate_id():
"""A randomly generated ID string"""
return str(uuid.uuid4()) # TODO: CI env-based ID


def _read_user_id(config_file: Path):
try:
with config_file.open(encoding="utf8") as fobj:
return json.load(fobj)["user_id"]
except (FileNotFoundError, ValueError, KeyError):
pass
return None


def _read_user_id_locked(config_file: Path):
lockfile = str(config_file.with_suffix(".lock"))
if config_file.parent.is_dir():
with FileLock(lockfile, timeout=5):
return _read_user_id(config_file)
return None


@lru_cache(None)
def _find_or_create_user_id():
"""
The user's ID is stored on a file under the global config directory.
The file should contain a JSON with a "user_id" key:
{"user_id": "16fd2706-8baf-433b-82eb-8c7fada847da"}
IDs are generated randomly with UUID.
IDs are generated randomly with UUID4.
"""

config_dir = user_config_dir("telemetry", "iterative")
fname = os.path.join(config_dir, "user_id")
lockfile = os.path.join(config_dir, "user_id.lock")

# Since the `fname` and `lockfile` are under the global config,
# we need to make sure such directory exist already.
os.makedirs(config_dir, exist_ok=True)
config_file = Path(
user_config_dir(os.path.join("iterative", "telemetry"), False)
)
config_file.parent.mkdir(mode=0o755, parents=True, exist_ok=True)
lockfile = str(config_file.with_suffix(".lock"))
# DVC backwards-compatibility
config_file_old = Path(
user_config_dir(os.path.join("dvc", "user_id"), "iterative")
)

try:
with FileLock( # pylint: disable=abstract-class-instantiated
lockfile, timeout=5
):
try:
with open(fname, encoding="utf8") as fobj:
user_id = json.load(fobj)["user_id"]

except (FileNotFoundError, ValueError, KeyError):
user_id = str(uuid.uuid4())

with open(fname, "w", encoding="utf8") as fobj:
user_id = _read_user_id(config_file)
if user_id is None:
try:
user_id = _read_user_id_locked(config_file_old)
except Timeout:
logger.debug(
"Failed to acquire %s",
config_file_old.with_suffix(".lock"),
)
return None
if user_id is None:
user_id = _generate_id()
with config_file.open(mode="w", encoding="utf8") as fobj:
json.dump({"user_id": user_id}, fobj)

return user_id

except Timeout:
logger.debug("Failed to acquire %s", lockfile)
return None
return user_id if user_id.lower() != DO_NOT_TRACK_VALUE.lower() else None