uuid.py 2.97 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Stripped down version of the CPython uuid.py module
import os

int_ = int  # The built-in int type
bytes_ = bytes  # The built-in bytes type


class UUID:
    def __init__(self, hex=None, bytes=None, int=None, version=None):
        if [hex, bytes, int].count(None) != 2:
            raise TypeError("one of the hex, bytes, or int arguments must be given")

        if hex is not None:
            hex = hex.replace("urn:", "").replace("uuid:", "")
            hex = hex.strip("{}").replace("-", "")
            if len(hex) != 32:
                raise ValueError("badly formed hexadecimal UUID string")
            int = int_(hex, 16)
        if bytes is not None:
            if len(bytes) != 16:
                raise ValueError("bytes is not a 16-char string")
            assert isinstance(bytes, bytes_), repr(bytes)
23
            int = int_.from_bytes(bytes, "big")
24
25
26
27
28
29
30
31
32
33
34
35
        if int is not None:
            if not 0 <= int < 1 << 128:
                raise ValueError("int is out of range (need a 128-bit value)")
        if version is not None:
            if not 1 <= version <= 5:
                raise ValueError("illegal version number")
            # Set the variant to RFC 4122.
            int &= ~(0xC000 << 48)
            int |= 0x8000 << 48
            # Set the version number.
            int &= ~(0xF000 << 64)
            int |= version << 76
36
37

        setattr(self, "int", int)
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

    def __eq__(self, other):
        if isinstance(other, UUID):
            return self.int == other.int
        return NotImplemented

    def __lt__(self, other):
        if isinstance(other, UUID):
            return self.int < other.int
        return NotImplemented

    def __gt__(self, other):
        if isinstance(other, UUID):
            return self.int > other.int
        return NotImplemented

    def __le__(self, other):
        if isinstance(other, UUID):
            return self.int <= other.int
        return NotImplemented

    def __ge__(self, other):
        if isinstance(other, UUID):
            return self.int >= other.int
        return NotImplemented

    def __hash__(self):
        return hash(self.int)

    def __int__(self):
        return self.int

    def __repr__(self):
        return "{}({!r})".format(self.__class__.__name__, str(self))

    def __setattr__(self, name, value):
        raise TypeError("UUID objects are immutable")

    def __str__(self):
        hex = "{:032x}".format(self.int)
        return "{}-{}-{}-{}-{}".format(
            hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:]
        )

    @property
    def bytes(self):
        return self.int.to_bytes(16, "big")

    @property
    def node(self):
        return self.int & 0xFFFFFFFFFFFF

    @property
    def hex(self):
        return "{:032x}".format(self.int)

    @property
    def urn(self):
        return "urn:uuid:" + str(self)

    @property
    def version(self):
        return int((self.int >> 76) & 0xF)


def uuid4():
    """Generate a random UUID."""
    return UUID(bytes=os.urandom(16), version=4)