Skip to content

Commit

Permalink
For dials/dials#1998 bring in UUID4 (#477)
Browse files Browse the repository at this point in the history
UUID generation involves spawning a subprocess on import which appears to
cause problems in large-rank MPI jobs - however we only really need random
128 bit UUID4's which can be generated easily.

This also fixes the otherwise currently broken CI tests due to the pytest v7 release.

Co-authored-by: Markus Gerstel <markus.gerstel@diamond.ac.uk>
  • Loading branch information
graeme-winter and Anthchirp authored Feb 8, 2022
1 parent 456d981 commit 42b1945
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .azure-pipelines/ci-conda-env.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ conda-forge::pytest-forked
conda-forge::pytest-mock
conda-forge::pytest-timeout
conda-forge::pytest-xdist
conda-forge::pytest
conda-forge::pytest<7
conda-forge::requests
conda-forge::scipy
conda-forge::scons
Expand Down
1 change: 1 addition & 0 deletions newsfragments/477.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add method ersatz_uuid4 which gives an implementation of a random 128 bit UUID4
1 change: 1 addition & 0 deletions newsfragments/477.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Avoid currently broken pytest v7 in CI tests
4 changes: 2 additions & 2 deletions src/dxtbx/format/FormatHDF5EigerNearlyNexus.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

import sys
import uuid

import h5py
import numpy as np
Expand All @@ -23,6 +22,7 @@
NXmxReader,
generate_scan_model,
)
from dxtbx.util import ersatz_uuid4


def find_entries(nx_file):
Expand Down Expand Up @@ -319,7 +319,7 @@ def understand(image_file):

def _start(self):
# Read the file structure
temp_file = "tmp_master_%s.nxs" % uuid.uuid1().hex
temp_file = "tmp_master_%s.nxs" % ersatz_uuid4()
fixer = EigerNXmxFixer(self._image_file, temp_file)
reader = NXmxReader(handle=fixer.handle)

Expand Down
8 changes: 8 additions & 0 deletions src/dxtbx/util/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import math
import os
import sys
from urllib.parse import urlparse

Expand Down Expand Up @@ -80,3 +81,10 @@ def get_url_scheme(url) -> str:
"""Extract the URL scheme from the string url, respecting Windows file paths"""

return urlparse(str(url)).scheme if "://" in str(url) else ""


def ersatz_uuid4() -> str:
"""Generate an ersatz UUID4 i.e. random 128 bit UUID."""

h = "%032x" % int.from_bytes(os.urandom(16), byteorder="little")
return "%s-%s-%s-%s-%s" % (h[:8], h[8:12], h[12:16], h[16:20], h[20:])
18 changes: 18 additions & 0 deletions tests/test_util.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from dxtbx.util import ersatz_uuid4
from dxtbx.util import format_float_with_standard_uncertainty as ffwsu


Expand All @@ -14,3 +15,20 @@ def test_format_float_with_standard_uncertainty():
assert ffwsu(90, 0) == "90"
assert ffwsu(90.0, 0) == "90.0"
assert ffwsu(90 + 1e-14, 0) == "90.0"


def test_ersatz_uuid4():
"""Test ersatz UUID4 behaviour:
- (pseudo)randomness and uniqueness
- shape e.g. 00000000-0000-0000-0000-000000000000
- content e.g. hex digits"""

uuids = [ersatz_uuid4() for j in range(1000)]

assert len(uuids) == len(set(uuids))

for uuid in uuids:
bits = uuid.split("-")
assert tuple(len(b) for b in bits) == (8, 4, 4, 4, 12)
for b in bits:
assert set(b) <= set("0123456789abcdef")

0 comments on commit 42b1945

Please sign in to comment.