|
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