|
8 | 8 | import sys
|
9 | 9 | import uuid
|
10 | 10 | from functools import lru_cache
|
| 11 | +from pathlib import Path |
11 | 12 | from threading import Thread
|
12 | 13 | from typing import Any, Callable, Dict, Union
|
13 | 14 |
|
@@ -187,39 +188,44 @@ def _system_info():
|
187 | 188 | raise NotImplementedError
|
188 | 189 |
|
189 | 190 |
|
| 191 | +def generate_id(): |
| 192 | + """TODO: check environ for CI-based ID""" |
| 193 | + return str(uuid.uuid4()) |
| 194 | + |
| 195 | + |
190 | 196 | @lru_cache(None)
|
191 | 197 | def _find_or_create_user_id():
|
192 | 198 | """
|
193 | 199 | The user's ID is stored on a file under the global config directory.
|
194 |
| - The file should contain a JSON with a "user_id" key: |
195 |
| - {"user_id": "16fd2706-8baf-433b-82eb-8c7fada847da"} |
196 |
| - IDs are generated randomly with UUID. |
| 200 | + The file should contain a single string: |
| 201 | + 16fd2706-8baf-433b-82eb-8c7fada847da |
| 202 | + IDs are generated randomly with UUID4. |
197 | 203 | """
|
198 |
| - |
199 |
| - config_dir = user_config_dir(os.path.join("iterative", "telemetry"), False) |
200 |
| - fname = os.path.join(config_dir, "user_id") |
201 |
| - lockfile = os.path.join(config_dir, "user_id.lock") |
202 |
| - |
203 |
| - # Since the `fname` and `lockfile` are under the global config, |
204 |
| - # we need to make sure such directory exist already. |
205 |
| - os.makedirs(config_dir, exist_ok=True) |
| 204 | + # DVC backwards-compatibility |
| 205 | + old = Path(user_config_dir(str(Path("dvc") / "user_id"), "iterative")) |
| 206 | + # cross-product path |
| 207 | + new = Path(user_config_dir(str(Path("iterative") / "telemetry"), False)) |
| 208 | + new.parent.mkdir(mode=0o755, parents=True, exist_ok=True) |
| 209 | + lockfile = str(new.with_suffix(".lock")) |
206 | 210 |
|
207 | 211 | try:
|
208 | 212 | with FileLock( # pylint: disable=abstract-class-instantiated
|
209 | 213 | lockfile, timeout=5
|
210 | 214 | ):
|
211 |
| - try: |
212 |
| - with open(fname, encoding="utf8") as fobj: |
213 |
| - user_id = json.load(fobj)["user_id"] |
214 |
| - |
215 |
| - except (FileNotFoundError, ValueError, KeyError): |
216 |
| - user_id = str(uuid.uuid4()) |
217 |
| - |
218 |
| - with open(fname, "w", encoding="utf8") as fobj: |
219 |
| - json.dump({"user_id": user_id}, fobj) |
220 |
| - |
221 |
| - return user_id |
222 |
| - |
| 215 | + uid = generate_id() |
| 216 | + if new.exists(): |
| 217 | + uid = new.read_text().strip() |
| 218 | + else: |
| 219 | + if old.exists(): |
| 220 | + uid = json.load(old.open(encoding="utf8"))["user_id"] |
| 221 | + new.write_text(uid) |
| 222 | + |
| 223 | + # only for non-DVC packages, |
| 224 | + # write legacy file in case legacy DVC is installed later |
| 225 | + if not old.exists() and uid.lower() != "do-not-track": |
| 226 | + old.write_text(f'{{"user_id": "{uid}"}}') |
| 227 | + |
| 228 | + return uid |
223 | 229 | except Timeout:
|
224 | 230 | logger.debug("Failed to acquire %s", lockfile)
|
225 | 231 | return None
|
0 commit comments