Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Lundin committed Jul 20, 2010
0 parents commit 1989586
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Daniel Lundin <[email protected]>
10 changes: 10 additions & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
AUTHORS
MANIFEST
MANIFEST.in
README
README.rst
setup.py
libuuid/__init__.py
libuuid/_uuid.c
libuuid/_uuid.pyx
libuuid/uuid.pxd
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include MANIFEST.in MANIFEST
include AUTHORS README.rst
recursive-include libuuid *.py *.pyx *.pxd _uuid.c
1 change: 1 addition & 0 deletions README
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
###################################################
pylibuuid - Faster UUID generation using libuuid
####################################################

Python bindings for libuuid. Compatible with the standard library `uuid` module.
Binary file added libuuid/.nfs000000005849ac8f00000c04
Binary file not shown.
9 changes: 9 additions & 0 deletions libuuid/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from libuuid._uuid import *

from uuid import UUID as _UUID
from uuid import (NAMESPACE_DNS, NAMESPACE_OID, NAMESPACE_URL, NAMESPACE_X500,
RESERVED_FUTURE, RESERVED_MICROSOFT, RESERVED_NCS, RFC_4122)




60 changes: 60 additions & 0 deletions libuuid/_uuid.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# cython: embedsignature=True
from binascii import hexlify
import uuid as uuid_std

cimport uuid
from uuid cimport *

cdef extern from "Python.h":
object PyString_FromFormat(char *format, ...)
object PyString_FromStringAndSize(char *s, int len)
object PyString_FromString(char *s)
object PyLong_FromVoidPtr(void *p)
object PyLong_FromString(char *, char**, int)
object _PyLong_FromByteArray(unsigned char *bytes, unsigned int n,
int little_endian, int is_signed)
int _PyLong_AsByteArray(object v, unsigned char *bytes, unsigned int n,
int little_endian, int is_signed) except -1

int PyString_Size(object s)
object PyString_FromStringAndSize(char *, int)
char *PyString_AS_STRING(object s)


class FastUUID(uuid_std.UUID):
def __init__(self, version=4, *args, **kwargs):
cdef object buf = PyString_FromStringAndSize(NULL, 16)
cdef unsigned char *_bytes = <unsigned char*>PyString_AS_STRING(buf)
if version == 1:
uuid_generate_time(_bytes)
elif version == 4:
uuid_generate_random(_bytes)
self.__dict__['bytes'] = buf
self.__dict__['int'] = _PyLong_FromByteArray(_bytes, 16, 0, 0)

def get_bytes(self):
return self.bytes


def uuid1(node=None, clock_seq=None):
if node or clock_seq:
raise NotImplementedError, "node and clock_seq are not supported in libuuid"
return FastUUID(1)

uuid3 = uuid_std.uuid3

uuid4 = FastUUID

uuid5 = uuid_std.uuid5

def uuid1_bytes():
cdef object bytes = PyString_FromStringAndSize(NULL, 16)
uuid_generate_time(<unsigned char*>PyString_AS_STRING(bytes))
return bytes

def uuid4_bytes():
cdef object bytes = PyString_FromStringAndSize(NULL, 16)
uuid_generate_random(<unsigned char*>PyString_AS_STRING(bytes))
return bytes


60 changes: 60 additions & 0 deletions libuuid/uuid.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Python bindings for libavro

cdef extern from *:
ctypedef char* const_char_ptr "const char*"

cdef extern from "stdint.h" nogil:
ctypedef int int32_t
ctypedef int uint32_t

cdef extern from 'stdio.h' nogil:
int snprintf(char *str, size_t size, char *format, ...)

cdef extern from "stdlib.h" nogil:
void free(void * ptr)
void * malloc(int size)

cdef extern from "string.h" nogil:
void *memset(void *, int, size_t)

cdef extern from 'sys/time.h' nogil:
ctypedef struct timeval:
unsigned int tv_sec
unsigned int tv_usec
ctypedef int32_t time_t

# UUID Variant definitions
UUID_VARIANT_NCS = 0
UUID_VARIANT_DCE = 1
UUID_VARIANT_MICROSOFT = 2
UUID_VARIANT_OTHER = 3

# UUID Type definitions
UUID_TYPE_DCE_TIME = 1
UUID_TYPE_DCE_RANDOM = 4

cdef extern from 'uuid/uuid.h' nogil:
ctypedef unsigned char uuid_t[16]

void uuid_clear(uuid_t uu)

int uuid_compare(uuid_t uu1, uuid_t uu2)

void uuid_copy(uuid_t dst, uuid_t src)

void uuid_generate(uuid_t out)
void uuid_generate_random(uuid_t out)
void uuid_generate_time(uuid_t out)

int uuid_is_null(uuid_t uu)

int uuid_parse(const_char_ptr indata, uuid_t uu)

void uuid_unparse(uuid_t uu, char *out)
void uuid_unparse_lower(uuid_t uu, char *out)
void uuid_unparse_upper(uuid_t uu, char *out)

time_t uuid_time(uuid_t uu, timeval *ret_tv)
int uuid_type(uuid_t uu)
int uuid_variant(uuid_t uu)

75 changes: 75 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Python bindings to libuuid."""

__version_info__ = (0, 9, 0)
__version__ = ".".join(map(str, __version_info__))
__author__ = "Daniel Lundin"
__contact__ = "[email protected]"
__homepage__ = "http://github.com/dln/pylibuuid/"
__docformat__ = "restructuredtext"

import codecs
import os
from glob import glob


try:
import setuptools
except ImportError:
from ez_setup import use_setuptools
use_setuptools()

from setuptools import setup, find_packages, Extension
from distutils.command.sdist import sdist

extra_setup_args = {}
try:
from Cython.Distutils import build_ext
import Cython.Compiler.Version
import Cython.Compiler.Main as cython_compiler
print("building with Cython " + Cython.Compiler.Version.version)
class Sdist(sdist):
def __init__(self, *args, **kwargs):
for src in glob('libuuid/*.pyx'):
cython_compiler.compile(glob('libuuid/*.pyx'),
cython_compiler.default_options)
sdist.__init__(self, *args, **kwargs)
extra_setup_args['cmdclass'] = {'build_ext': build_ext, 'sdist': Sdist}
source_extension = ".pyx"
except ImportError:
print("building without Cython")
source_extension = ".c"


ext_modules = [
Extension('libuuid._uuid',
sources=['libuuid/_uuid' + source_extension],
libraries=['uuid'])
]


long_description = codecs.open('README.rst', "r", "utf-8").read()

setup(name = 'python-libuuid',
version = __version__,
description = __doc__,
author = __author__,
author_email = __contact__,
url = __homepage__,
packages = ['libuuid'],
ext_modules = ext_modules,
zip_safe=False,
test_suite="nose.collector",
classifiers=[
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"License :: OSI Approved :: Apache Software License",
"Intended Audience :: Developers",
"Topic :: Communications",
"Topic :: System :: Distributed Computing",
"Topic :: Software Development :: Libraries :: Python Modules",
],
long_description=long_description,
**extra_setup_args
)
128 changes: 128 additions & 0 deletions tests/test_uuid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# -*- coding: utf-8 -*-
from random import choice, randrange
import os
import shutil
import string
import sys
import tempfile
import time
import unittest
import uuid

import libuuid


def test_properties():
_PROPERTIES = [
'bytes', 'bytes_le', 'clock_seq', 'clock_seq_hi_variant',
'clock_seq_low', 'fields', 'hex', 'node', 'time', 'time_hi_version',
'time_low', 'time_mid', 'urn', 'variant', 'version'
]

def _check_property(factory_func, prop):
u = factory_func()
u2 = uuid.UUID(bytes=u.bytes)
a1 = getattr(u, prop)
a2 = getattr(u2, prop)
assert a1 == a2

for prop in _PROPERTIES:
test_properties.__doc__ = "Property: " + prop
yield _check_property, libuuid.uuid1, prop
yield _check_property, libuuid.uuid4, prop

def test_methods():
_METHODS = [
'__hash__', '__int__', '__repr__', '__str__', 'get_bytes',
'get_bytes_le', 'get_clock_seq', 'get_clock_seq_hi_variant',
'get_clock_seq_low', 'get_fields', 'get_hex', 'get_node', 'get_time',
'get_time_hi_version', 'get_time_low', 'get_time_mid', 'get_urn',
'get_variant', 'get_version'
]

def _check_method(factory_func, method, *args, **kwargs):
u = factory_func()
u2 = uuid.UUID(bytes=u.bytes)
m1 = getattr(u, method)(*args, **kwargs)
m2 = getattr(u2, method)(*args, **kwargs)
assert m1 == m2

for method in _METHODS:
test_methods.__doc__ = "Method: " + method
yield _check_method, libuuid.uuid1, method
yield _check_method, libuuid.uuid4, method


def test_constants():

_CONSTANTS = ['NAMESPACE_DNS', 'NAMESPACE_OID', 'NAMESPACE_URL',
'NAMESPACE_X500', 'RESERVED_FUTURE', 'RESERVED_MICROSOFT',
'RESERVED_NCS', 'RFC_4122']

def _check_constant(const):
m1 = getattr(libuuid, const)
m2 = getattr(uuid, const)
assert m1 == m2

for constant in _CONSTANTS:
test_methods.__doc__ = "Constant: " + constant
yield _check_constant, constant


class TestUUID(unittest.TestCase):

def test_uuid1(self):
u = libuuid.uuid1()
u2 = uuid.UUID(bytes=u.bytes)
self.assertEqual(u.bytes, u2.bytes)

def test_uuid4(self):
u = libuuid.uuid4()
u2 = uuid.UUID(bytes=u.bytes)
self.assertEqual(u.bytes, u2.bytes)

def test_is_UUID_instance(self):
u = libuuid.uuid4()
self.assert_(isinstance(u, uuid.UUID))

def test_uuid4_args_unsupported(self):
self.assertRaises(NotImplementedError, lambda: libuuid.uuid1(42))
self.assertRaises(NotImplementedError, lambda: libuuid.uuid1(42, 42))
self.assertRaises(NotImplementedError, lambda: libuuid.uuid1(node=42))
self.assertRaises(NotImplementedError, lambda: libuuid.uuid1(clock_seq=42))
self.assertRaises(NotImplementedError, lambda: libuuid.uuid1(node=42, clock_seq=42))

def test_uuid1_bytes(self):
b = libuuid.uuid1_bytes()
self.assertEquals(type(b), str)
self.assertEquals(uuid.UUID(bytes=b).version, 1)

def test_uuid4_bytes(self):
b = libuuid.uuid4_bytes()
self.assertEquals(type(b), str)
self.assertEquals(uuid.UUID(bytes=b).version, 4)

def test_basic_sanity_uuid4(self):
buf = set()
for _ in xrange(10000):
u = libuuid.uuid4_bytes()
self.assert_(u not in buf)
buf.add(u)

def test_basic_sanity_uuid1(self):
buf = set()
clocks = []
for _ in xrange(1000):
u = libuuid.uuid1()
clocks.append(u.time)
self.assert_(u.bytes not in buf)
buf.add(u.bytes)
self.assertEquals(clocks, sorted(clocks), "Timestamps increment")
t = (time.time() * 1e7) + 0x01b21dd213814000L # RFC 4122 timestamp
diff = abs(t - clocks[-1])
self.assert_(diff < 10000, "Timestamp reasonable")





0 comments on commit 1989586

Please sign in to comment.