Conversation
Version 0.5.0
Fixing Qaoa tests for v0.5.0 release
…ndling, unsafe eval
Fix 1 : Gate matrix class-level constantsFile: native_gates.py Promoted [self.matrix = np.array(...)] from per-instance allocation in [init] to shared class-level attributes for 8 gates: [Id], [X], [Y], [Z], [H], [S], [S_dagger], [SWAP]. All matrices now use [dtype=np.complex128] explicitly. Verified that [x1.matrix is X.matrix] instances share the class constant (zero per-instance allocation). Fix 2 : [Instruction.eq] pickle → structuralFile: instruction.py Replaced [pickle.dumps(self) == pickle.dumps(value)] with: if not isinstance(value, type(self)):
return False
return self.to_dict() == value.to_dict()Removed the from pickle import dumps import. This is now consistent with how [Gate.eq] and [Breakpoint.eq] already worked. Fix 3 : Job unit testsFile: test_job.py Replaced the 4-line # 3M-TODO placeholder with 276 lines covering 25 test methods across 7 test classes: [TestJobStatus], [TestJobType], [TestJobConstruction], [TestJobStatusProperty], [TestJobEquality], [TestJobRepr], and [TestGenerateJob] (including symbolic substitution). |
|
Hi @nm727, thanks for the work you did! A few preliminary comments: we don't merge directly do main, because main represents the latest version of MPQP, instead we merge to dev and we merge dev to main only when we are ready to release a new version. In addition, in order to facilitate the review process, we try to have single feature branches, and merge them one after the other. I see that your work is split into clearly separated fixes, would you be able to submit each of these changes as a separated PR? Thanks! |
|
hello @Henri-ColibrITD thank you for the response! It should be resolved now. |
| raise RuntimeError(f"""\ | ||
| Database version {db_version} is outdated. Current supported version: {DATABASE_VERSION}. | ||
| Automated migration is not yet supported, please contact library authors to get\ | ||
| help for the migration.""") | ||
| import shutil | ||
| from warnings import warn | ||
|
|
||
| db_path = get_env_variable("DB_PATH") | ||
| backup_path = db_path + f".v{db_version}.bak" | ||
| shutil.copy2(db_path, backup_path) | ||
| warn( | ||
| f"Database version {db_version} is outdated (current: " | ||
| f"{DATABASE_VERSION}). The old database has been backed up to " | ||
| f"'{backup_path}' and a fresh database will be created.", | ||
| stacklevel=2, | ||
| ) | ||
| Path(db_path).unlink() | ||
| setup_local_storage(db_path) |
There was a problem hiding this comment.
interesting idea, for now we never changed db version so this problem cannot occur. We might prefer leaving the error as it was and create a proper migration script once we have a new version. To be discussed
Fix 1 : SQL Placeholder Mismatch (save.py)
Problem: The [INSERT INTO jobs] had 6 column names ([type, circuit, device, measure, remote_id, status]) but only 4 ? placeholders. The list-of-jobs branch would crash with [sqlite3.OperationalError] every time. The single-job branch had the inverse issue, only 4 columns, silently dropping remote_id and [status].
Fix: Both branches now consistently write all 6 columns with 6 placeholders and pass the full 6-value tuple.
Fix 2 : Stale Database Dead-End (setup.py)
Problem: When the DB version didn't match, users got RuntimeError: "please contact library authors" a complete brick wall with no recovery path.
Fix: The decorator now automatically:
Backs up the old DB to [.v<old_version>.bak]
Emits a UserWarning explaining what happened
Deletes the stale DB and re-creates a fresh one
Users keep their old data as a backup file and can continue working immediately.
Fix 3 : Unsafe [eval()] Deserialization (load.py)
Problem: 20+ bare [eval()] calls on strings from the SQLite database. If a DB file is shared, downloaded, or tampered with, this is arbitrary code execution.
Fix: Introduced [_safe_eval()] which:
Builds a restricted namespace containing only known MPQP symbols (from [mpqp.all]) plus numpy helpers, [complex64], [float64])
Sets builtins to {} — blocking access to import, [open], os, exec, import, etc.
Wraps every call in try/except with a descriptive [ValueError] on failure
Namespace is lazily built once and cached in [_SAFE_NAMESPACE]
All 20 [eval()] calls are now [_safe_eval()] calls.