Merge branch 'python3'

This commit is contained in:
J. David Ibáñez 2011-08-19 21:59:31 +02:00
commit ef9a5f6e55
12 changed files with 157 additions and 119 deletions

@ -1,7 +1,8 @@
pygit2 - libgit2 bindings in Python
=====================================
pygit2 is a set of Python 2.5+ bindings to the libgit2 linkable C Git library.
pygit2 is a set of Python bindings to the libgit2 linkable C Git library.
The supported versions of Python are 2.6, 2.7, 3.1 and 3.2
INSTALLING AND RUNNING
========================
@ -16,7 +17,7 @@ For instance, in Debian-based systems run:
$ sudo apt-get install zlib1g-dev libssl-dev
Also, make sure you have Python 2.5+ installed together with the Python development headers.
Also, make sure you have Python 2.6+ installed together with the Python development headers.
When those are installed, you can install pygit2:

153
pygit2.c

@ -277,26 +277,37 @@ py_str_to_git_oid(PyObject *py_str, git_oid *oid)
const char *hex_or_bin;
int err;
hex_or_bin = PyString_AsString(py_str);
if (hex_or_bin == NULL) {
Error_set_py_obj(GIT_ENOTOID, py_str);
return 0;
}
if (PyString_Size(py_str) == 20) {
/* Case 1: raw sha */
if (PyString_Check(py_str)) {
hex_or_bin = PyString_AsString(py_str);
if (hex_or_bin == NULL)
return 0;
git_oid_fromraw(oid, (const unsigned char*)hex_or_bin);
err = 0;
return 1;
}
else {
/* Case 2: hex sha */
if (PyUnicode_Check(py_str)) {
py_str = PyUnicode_AsASCIIString(py_str);
if (py_str == NULL)
return 0;
hex_or_bin = PyString_AsString(py_str);
Py_DECREF(py_str);
if (hex_or_bin == NULL)
return 0;
err = git_oid_fromstr(oid, hex_or_bin);
if (err < 0) {
Error_set_py_obj(err, py_str);
return 0;
}
return 1;
}
if (err < 0) {
Error_set_py_obj(err, py_str);
return 0;
}
return 1;
/* Type error */
PyErr_Format(PyExc_TypeError,
"Git object id must be byte or a text string, not: %.200s",
Py_TYPE(py_str)->tp_name);
return 0;
}
static PyObject*
@ -305,7 +316,32 @@ git_oid_to_py_str(const git_oid *oid)
char hex[GIT_OID_HEXSZ];
git_oid_fmt(hex, oid);
return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ);
return PyUnicode_DecodeASCII(hex, GIT_OID_HEXSZ, "strict");
}
char *
py_str_to_c_str(PyObject *value)
{
char *c_str;
/* Case 1: byte string */
if (PyString_Check(value))
return PyString_AsString(value);
/* Case 2: text string */
if (PyUnicode_Check(value)) {
value = PyUnicode_AsUTF8String(value);
if (value == NULL)
return NULL;
c_str = PyString_AsString(value);
Py_DECREF(value);
return c_str;
}
/* Type error */
PyErr_Format(PyExc_TypeError, "unexpected %.200s",
Py_TYPE(value)->tp_name);
return NULL;
}
static int
@ -494,11 +530,6 @@ Repository_walk(Repository *self, PyObject *args)
if (!PyArg_ParseTuple(args, "OI", &value, &sort))
return NULL;
if (value != Py_None && !PyString_Check(value)) {
PyErr_SetObject(PyExc_TypeError, value);
return NULL;
}
err = git_revwalk_new(&walk, self->repo);
if (err < 0)
return Error_set(err);
@ -1027,7 +1058,14 @@ Commit_get_message_encoding(Commit *commit)
static PyObject *
Commit_get_message(Commit *commit)
{
return PyString_FromString(git_commit_message(commit->commit));
const char *encoding;
const char *message;
int len;
encoding = git_commit_message_encoding(commit->commit);
message = git_commit_message(commit->commit);
len = strlen(message);
return PyUnicode_Decode(message, (Py_ssize_t)len, encoding, "strict");
}
static PyObject *
@ -1269,7 +1307,7 @@ Tree_contains(Tree *self, PyObject *py_name)
{
char *name;
name = PyString_AsString(py_name);
name = py_str_to_c_str(py_name);
if (name == NULL)
return -1;
@ -1290,21 +1328,6 @@ wrap_tree_entry(const git_tree_entry *entry, Tree *tree)
return py_entry;
}
static TreeEntry *
Tree_getitem_by_name(Tree *self, PyObject *py_name)
{
char *name;
const git_tree_entry *entry;
name = PyString_AS_STRING(py_name);
entry = git_tree_entry_byname(self->tree, name);
if (!entry) {
PyErr_SetObject(PyExc_KeyError, py_name);
return NULL;
}
return wrap_tree_entry(entry, self);
}
static int
Tree_fix_index(Tree *self, PyObject *py_index)
{
@ -1371,18 +1394,23 @@ Tree_getitem_by_index(Tree *self, PyObject *py_index)
static TreeEntry *
Tree_getitem(Tree *self, PyObject *value)
{
if (PyString_Check(value)) {
return Tree_getitem_by_name(self, value);
}
else if (PyInt_Check(value)) {
char *name;
const git_tree_entry *entry;
/* Case 1: integer */
if (PyInt_Check(value))
return Tree_getitem_by_index(self, value);
}
else {
PyErr_Format(PyExc_TypeError,
"Tree entry index must be int or str, not %.200s",
Py_TYPE(value)->tp_name);
/* Case 2: byte or text string */
name = py_str_to_c_str(value);
if (name == NULL)
return NULL;
entry = git_tree_entry_byname(self->tree, name);
if (!entry) {
PyErr_SetObject(PyExc_KeyError, value);
return NULL;
}
return wrap_tree_entry(entry, self);
}
static PySequenceMethods Tree_as_sequence = {
@ -1750,17 +1778,8 @@ Index_get_position(Index *self, PyObject *value)
char *path;
int idx;
if (PyString_Check(value)) {
path = PyString_AsString(value);
if (!path)
return -1;
idx = git_index_find(self->index, path);
if (idx < 0) {
Error_set_str(idx, path);
return -1;
}
}
else if (PyInt_Check(value)) {
/* Case 1: integer */
if (PyInt_Check(value)) {
idx = (int)PyInt_AsLong(value);
if (idx == -1 && PyErr_Occurred())
return -1;
@ -1768,14 +1787,18 @@ Index_get_position(Index *self, PyObject *value)
PyErr_SetObject(PyExc_ValueError, value);
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError,
"Index entry key must be int or str, not %.200s",
Py_TYPE(value)->tp_name);
return -1;
return idx;
}
/* Case 2: byte or text string */
path = py_str_to_c_str(value);
if (!path)
return -1;
idx = git_index_find(self->index, path);
if (idx < 0) {
Error_set_str(idx, path);
return -1;
}
return idx;
}
@ -1785,7 +1808,7 @@ Index_contains(Index *self, PyObject *value)
char *path;
int idx;
path = PyString_AsString(value);
path = py_str_to_c_str(value);
if (!path)
return -1;
idx = git_index_find(self->index, path);

@ -27,13 +27,15 @@
"""Tests for Blob objects."""
__author__ = 'dborowitz@google.com (Dave Borowitz)'
from __future__ import unicode_literals
import unittest
import pygit2
import utils
__author__ = 'dborowitz@google.com (Dave Borowitz)'
BLOB_SHA = 'af431f20fc541ed6d5afede3e2dc7160f6f01f16'
@ -43,8 +45,8 @@ class BlobTest(utils.BareRepoTestCase):
blob = self.repo[BLOB_SHA]
self.assertTrue(isinstance(blob, pygit2.Blob))
self.assertEqual(pygit2.GIT_OBJ_BLOB, blob.type)
self.assertEqual('a contents\n', blob.data)
self.assertEqual('a contents\n', blob.read_raw())
self.assertEqual(b'a contents\n', blob.data)
self.assertEqual(b'a contents\n', blob.read_raw())
if __name__ == '__main__':

@ -27,13 +27,15 @@
"""Tests for Commit objects."""
__author__ = 'dborowitz@google.com (Dave Borowitz)'
from __future__ import unicode_literals
import unittest
from pygit2 import GIT_OBJ_COMMIT
import utils
__author__ = 'dborowitz@google.com (Dave Borowitz)'
COMMIT_SHA = '5fe808e8953c12735680c257f56600cb0de44b10'

@ -28,14 +28,16 @@
"""Tests for Index files."""
__author__ = 'jdavid@itaapy.com (J. David Ibáñez)'
import unittest
from __future__ import unicode_literals
import os
import utils
import unittest
import pygit2
import utils
__author__ = 'jdavid@itaapy.com (J. David Ibáñez)'
class IndexBareTest(utils.BareRepoTestCase):
@ -98,7 +100,7 @@ class IndexTest(utils.RepoTestCase):
self.assertEqual(len(list(index)), n)
# Compare SHAs, not IndexEntry object identity
entries = [index[x].sha for x in xrange(n)]
entries = [index[x].sha for x in range(n)]
self.assertEqual(list(x.sha for x in index), entries)
def test_mode(self):

@ -28,15 +28,15 @@
"""Tests for reference objects."""
from __future__ import unicode_literals
import unittest
from pygit2 import GIT_REF_OID, GIT_REF_SYMBOLIC
import utils
__author__ = 'david.versmisse@itaapy.com (David Versmisse)'
import unittest
import utils
from pygit2 import GIT_REF_OID, GIT_REF_SYMBOLIC
LAST_COMMIT = '2be5719152d4f82c7302b1c0932d8e5f0a4a0e98'

@ -27,8 +27,7 @@
"""Tests for Repository objects."""
__author__ = 'dborowitz@google.com (Dave Borowitz)'
from __future__ import unicode_literals
import binascii
import unittest
import os
@ -38,6 +37,9 @@ from pygit2 import (GitError, GIT_OBJ_ANY, GIT_OBJ_BLOB, GIT_OBJ_COMMIT,
init_repository)
import utils
__author__ = 'dborowitz@google.com (Dave Borowitz)'
A_HEX_SHA = 'af431f20fc541ed6d5afede3e2dc7160f6f01f16'
A_BIN_SHA = binascii.unhexlify(A_HEX_SHA)
@ -57,7 +59,7 @@ class RepositoryTest(utils.BareRepoTestCase):
self.assertEqual((GIT_OBJ_BLOB, 'a contents 2\n'), a2)
def test_write(self):
data = "hello world"
data = b"hello world"
# invalid object type
self.assertRaises(GitError, self.repo.write, GIT_OBJ_ANY, data)

@ -28,13 +28,16 @@
"""Tests for revision walk."""
__author__ = 'jdavid@itaapy.com (J. David Ibáñez)'
from __future__ import unicode_literals
import unittest
from pygit2 import GIT_SORT_TIME, GIT_SORT_REVERSE
import utils
__author__ = 'jdavid@itaapy.com (J. David Ibáñez)'
# In the order given by git log
log = [
'2be5719152d4f82c7302b1c0932d8e5f0a4a0e98',

@ -28,13 +28,15 @@
"""Tests for revision walk."""
__author__ = 'mike.perdide@gmail.com (Julien Miotte)'
from __future__ import unicode_literals
import unittest
import pygit2
import utils
__author__ = 'mike.perdide@gmail.com (Julien Miotte)'
EXPECTED = {
"current_file": pygit2.GIT_STATUS_CURRENT,
"file_deleted": pygit2.GIT_STATUS_WT_DELETED,

@ -27,13 +27,15 @@
"""Tests for Tag objects."""
__author__ = 'dborowitz@google.com (Dave Borowitz)'
from __future__ import unicode_literals
import unittest
import pygit2
import utils
__author__ = 'dborowitz@google.com (Dave Borowitz)'
TAG_SHA = '3d2962987c695a29f1f80b6c3aa4ec046ef44369'

@ -27,14 +27,16 @@
"""Tests for Commit objects."""
__author__ = 'dborowitz@google.com (Dave Borowitz)'
from __future__ import unicode_literals
import operator
import unittest
import pygit2
import utils
__author__ = 'dborowitz@google.com (Dave Borowitz)'
TREE_SHA = '967fce8df97cc71722d3c2a5930ef3e6f1d27b12'
SUBTREE_SHA = '614fd9a3094bf618ea938fffc00e7d1a54f89ad0'
@ -55,27 +57,27 @@ class TreeTest(utils.BareRepoTestCase):
self.assertRaisesWithArg(IndexError, 3, lambda: tree[3])
self.assertEqual(3, len(tree))
a_sha = '7f129fd57e31e935c6d60a0c794efe4e6927664b'
sha = '7f129fd57e31e935c6d60a0c794efe4e6927664b'
self.assertTrue('a' in tree)
self.assertTreeEntryEqual(tree[0], a_sha, 'a', 0100644)
self.assertTreeEntryEqual(tree[-3], a_sha, 'a', 0100644)
self.assertTreeEntryEqual(tree['a'], a_sha, 'a', 0100644)
self.assertTreeEntryEqual(tree[0], sha, 'a', 0o0100644)
self.assertTreeEntryEqual(tree[-3], sha, 'a', 0o0100644)
self.assertTreeEntryEqual(tree['a'], sha, 'a', 0o0100644)
b_sha = '85f120ee4dac60d0719fd51731e4199aa5a37df6'
sha = '85f120ee4dac60d0719fd51731e4199aa5a37df6'
self.assertTrue('b' in tree)
self.assertTreeEntryEqual(tree[1], b_sha, 'b', 0100644)
self.assertTreeEntryEqual(tree[-2], b_sha, 'b', 0100644)
self.assertTreeEntryEqual(tree['b'], b_sha, 'b', 0100644)
self.assertTreeEntryEqual(tree[1], sha, 'b', 0o0100644)
self.assertTreeEntryEqual(tree[-2], sha, 'b', 0o0100644)
self.assertTreeEntryEqual(tree['b'], sha, 'b', 0o0100644)
def test_read_subtree(self):
tree = self.repo[TREE_SHA]
subtree_entry = tree['c']
self.assertTreeEntryEqual(subtree_entry, SUBTREE_SHA, 'c', 0040000)
self.assertTreeEntryEqual(subtree_entry, SUBTREE_SHA, 'c', 0o0040000)
subtree = subtree_entry.to_object()
self.assertEqual(1, len(subtree))
self.assertTreeEntryEqual(
subtree[0], '297efb891a47de80be0cfe9c639e4b8c9b450989', 'd', 0100644)
sha = '297efb891a47de80be0cfe9c639e4b8c9b450989'
self.assertTreeEntryEqual(subtree[0], sha, 'd', 0o0100644)
# XXX Creating new trees was removed from libgit2 by v0.11.0, we
# deactivate this test temporarily, since the feature may come back in
@ -83,15 +85,15 @@ class TreeTest(utils.BareRepoTestCase):
def xtest_new_tree(self):
tree = pygit2.Tree(self.repo)
self.assertEqual(0, len(tree))
tree.add_entry('1' * 40, 'x', 0100644)
tree.add_entry('2' * 40, 'y', 0100755)
tree.add_entry('1' * 40, 'x', 0o0100644)
tree.add_entry('2' * 40, 'y', 0o0100755)
self.assertEqual(2, len(tree))
self.assertTrue('x' in tree)
self.assertTrue('y' in tree)
self.assertRaisesWithArg(KeyError, '1' * 40, tree['x'].to_object)
tree.add_entry('3' * 40, 'z1', 0100644)
tree.add_entry('4' * 40, 'z2', 0100644)
tree.add_entry('3' * 40, 'z1', 0o0100644)
tree.add_entry('4' * 40, 'z2', 0o0100644)
self.assertEqual(4, len(tree))
del tree['z1']
del tree[2]
@ -120,4 +122,4 @@ class TreeTest(utils.BareRepoTestCase):
if __name__ == '__main__':
unittest.main()
unittest.main()

@ -25,11 +25,8 @@
"""Test utilities for libgit2."""
__author__ = 'dborowitz@google.com (Dave Borowitz)'
import os
import shutil
import sys
import tarfile
import tempfile
import unittest
@ -37,6 +34,9 @@ import unittest
import pygit2
__author__ = 'dborowitz@google.com (Dave Borowitz)'
class BaseTestCase(unittest.TestCase):
def tearDown(self):
@ -45,10 +45,7 @@ class BaseTestCase(unittest.TestCase):
def assertRaisesWithArg(self, exc_class, arg, func, *args, **kwargs):
try:
func(*args, **kwargs)
except exc_class:
# XXX Use the 'exc_class as exc_value' syntax as soon as we drop
# support for Python 2.5
exc_value = sys.exc_info()[1]
except exc_class as exc_value:
self.assertEqual((arg,), exc_value.args)
else:
self.fail('%s(%r) not raised' % (exc_class.__name__, arg))