Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit56e9423

Browse files
committed
Merge branch 'py3' into 0.3
Conflicts:git/refs/log.py
2 parentsd46e3fe +68f8a43 commit56e9423

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+721
-452
lines changed

‎README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,6 @@ In short, I want to make a new release of 0.3 with all contributions and fixes i
8383

8484
The goals I have set for myself, in order, are as follows, all on branch 0.3.
8585

86-
* bring the test suite back online to work with the most commonly used git version
87-
* merge all open pull requests, may there be a test-case or not, back. If something breaks, fix it if possible or let the contributor know
88-
* conform git-python's structure and toolchain to the one used in my[other OSS projects](https://github.com/Byron/bcore)
89-
* evaluate all open issues and close them if possible
9086
* evaluate python 3.3 compatibility and establish it if possible
9187

9288
While that is happening, I will try hard to foster community around the project. This means being more responsive on the mailing list and in issues, as well as setting up clear guide lines about the[contribution](http://rfc.zeromq.org/spec:22) and maintenance workflow.

‎VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.3.3
1+
0.3.4

‎doc/source/changes.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,18 @@
22
Changelog
33
=========
44

5+
0.3.4 - Python 3 Support
6+
========================
7+
* Internally, hexadecimal SHA1 are treated as ascii encoded strings. Binary SHA1 are treated as bytes.
8+
* Id attribute of Commit objects is now `hexsha`, instead of `binsha`. The latter makes no sense in python 3 and I see no application of it anyway besides its artificial usage in test cases.
9+
* **IMPORTANT**: If you were using the config_writer(), you implicitly relied on __del__ to work as expected to flush changes. To be sure changes are flushed under PY3, you will have to call the new `release()` method to trigger a flush. For some reason, __del__ is not called necessarily anymore when a symbol goes out of scope.
10+
* The `Tree` now has a `.join('name')` method which is equivalent to `tree / 'name'`
11+
512
0.3.3
613
=====
714
* When fetching, pulling or pushing, and an error occours, it will not be reported on stdout anymore. However, if there is a fatal error, it will still result in a GitCommandError to be thrown. This goes hand in hand with improved fetch result parsing.
815
* Code Cleanup (in preparation for python 3 support)
16+
917
* Applied autopep8 and cleaned up code
1018
* Using python logging module instead of print statments to signal certain kinds of errors
1119

‎git/cmd.py

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,24 @@
77
importos
88
importsys
99
importlogging
10-
fromutilimport (
11-
LazyMixin,
12-
stream_copy
13-
)
14-
fromexcimportGitCommandError
15-
1610
fromsubprocessimport (
1711
call,
1812
Popen,
1913
PIPE
2014
)
2115

16+
17+
from .utilimport (
18+
LazyMixin,
19+
stream_copy
20+
)
21+
from .excimportGitCommandError
22+
fromgit.compatimport (
23+
string_types,
24+
defenc,
25+
PY3
26+
)
27+
2228
execute_kwargs= ('istream','with_keep_cwd','with_extended_output',
2329
'with_exceptions','as_process',
2430
'output_stream')
@@ -114,7 +120,7 @@ def wait(self):
114120
:raise GitCommandError: if the return status is not 0"""
115121
status=self.proc.wait()
116122
ifstatus!=0:
117-
raiseGitCommandError(self.args,status,self.proc.stderr.read())
123+
raiseGitCommandError(self.args,status,self.proc.stderr.read().decode(defenc))
118124
# END status handling
119125
returnstatus
120126
# END auto interrupt
@@ -314,6 +320,7 @@ def execute(self, command,
314320
always be created with a pipe due to issues with subprocess.
315321
This merely is a workaround as data will be copied from the
316322
output pipe to the given output stream directly.
323+
Judging from the implementation, you shouldn't use this flag !
317324
318325
:param subprocess_kwargs:
319326
Keyword arguments to be passed to subprocess.Popen. Please note that
@@ -365,23 +372,23 @@ def execute(self, command,
365372

366373
# Wait for the process to return
367374
status=0
368-
stdout_value=''
369-
stderr_value=''
375+
stdout_value=b''
376+
stderr_value=b''
370377
try:
371378
ifoutput_streamisNone:
372379
stdout_value,stderr_value=proc.communicate()
373380
# strip trailing "\n"
374-
ifstdout_value.endswith("\n"):
381+
ifstdout_value.endswith(b"\n"):
375382
stdout_value=stdout_value[:-1]
376-
ifstderr_value.endswith("\n"):
383+
ifstderr_value.endswith(b"\n"):
377384
stderr_value=stderr_value[:-1]
378385
status=proc.returncode
379386
else:
380387
stream_copy(proc.stdout,output_stream,self.max_chunk_size)
381388
stdout_value=output_stream
382389
stderr_value=proc.stderr.read()
383390
# strip trailing "\n"
384-
ifstderr_value.endswith("\n"):
391+
ifstderr_value.endswith(b"\n"):
385392
stderr_value=stderr_value[:-1]
386393
status=proc.wait()
387394
# END stdout handling
@@ -392,9 +399,10 @@ def execute(self, command,
392399
ifself.GIT_PYTHON_TRACE=='full':
393400
cmdstr=" ".join(command)
394401
ifstderr_value:
395-
log.info("%s -> %d; stdout: '%s'; stderr: '%s'",cmdstr,status,stdout_value,stderr_value)
402+
log.info("%s -> %d; stdout: '%s'; stderr: '%s'",
403+
cmdstr,status,stdout_value.decode(defenc),stderr_value.decode(defenc))
396404
elifstdout_value:
397-
log.info("%s -> %d; stdout: '%s'",cmdstr,status,stdout_value)
405+
log.info("%s -> %d; stdout: '%s'",cmdstr,status,stdout_value.decode(defenc))
398406
else:
399407
log.info("%s -> %d",cmdstr,status)
400408
# END handle debug printing
@@ -405,9 +413,12 @@ def execute(self, command,
405413
else:
406414
raiseGitCommandError(command,status,stderr_value)
407415

416+
ifisinstance(stdout_value,bytes):# could also be output_stream
417+
stdout_value=stdout_value.decode(defenc)
418+
408419
# Allow access to the command's status code
409420
ifwith_extended_output:
410-
return (status,stdout_value,stderr_value)
421+
return (status,stdout_value,stderr_value.decode(defenc))
411422
else:
412423
returnstdout_value
413424

@@ -433,16 +444,18 @@ def transform_kwargs(self, split_single_char_options=False, **kwargs):
433444
@classmethod
434445
def__unpack_args(cls,arg_list):
435446
ifnotisinstance(arg_list, (list,tuple)):
436-
ifisinstance(arg_list,unicode):
437-
return [arg_list.encode('utf-8')]
447+
# This is just required for unicode conversion, as subprocess can't handle it
448+
# However, in any other case, passing strings (usually utf-8 encoded) is totally fine
449+
ifnotPY3andisinstance(arg_list,unicode):
450+
return [arg_list.encode(defenc)]
438451
return [str(arg_list)]
439452

440453
outlist=list()
441454
forarginarg_list:
442455
ifisinstance(arg_list, (list,tuple)):
443456
outlist.extend(cls.__unpack_args(arg))
444-
elifisinstance(arg_list,unicode):
445-
outlist.append(arg_list.encode('utf-8'))
457+
elifnotPY3andisinstance(arg_list,unicode):
458+
outlist.append(arg_list.encode(defenc))
446459
# END recursion
447460
else:
448461
outlist.append(str(arg))
@@ -498,8 +511,8 @@ def _call_process(self, method, *args, **kwargs):
498511

499512
# Prepare the argument list
500513
opt_args=self.transform_kwargs(**kwargs)
501-
502514
ext_args=self.__unpack_args([aforainargsifaisnotNone])
515+
503516
args=opt_args+ext_args
504517

505518
defmake_call():
@@ -567,14 +580,20 @@ def _parse_object_header(self, header_line):
567580
raiseValueError("Failed to parse header: %r"%header_line)
568581
return (tokens[0],tokens[1],int(tokens[2]))
569582

570-
def__prepare_ref(self,ref):
571-
# required for command to separate refs on stdin
572-
refstr=str(ref)# could be ref-object
573-
ifrefstr.endswith("\n"):
574-
returnrefstr
575-
returnrefstr+"\n"
583+
def_prepare_ref(self,ref):
584+
# required for command to separate refs on stdin, as bytes
585+
refstr=ref
586+
ifisinstance(ref,bytes):
587+
# Assume 40 bytes hexsha - bin-to-ascii for some reason returns bytes, not text
588+
refstr=ref.decode('ascii')
589+
elifnotisinstance(ref,string_types):
590+
refstr=str(ref)# could be ref-object
591+
592+
ifnotrefstr.endswith("\n"):
593+
refstr+="\n"
594+
returnrefstr.encode(defenc)
576595

577-
def__get_persistent_cmd(self,attr_name,cmd_name,*args,**kwargs):
596+
def_get_persistent_cmd(self,attr_name,cmd_name,*args,**kwargs):
578597
cur_val=getattr(self,attr_name)
579598
ifcur_valisnotNone:
580599
returncur_val
@@ -587,7 +606,7 @@ def __get_persistent_cmd(self, attr_name, cmd_name, *args, **kwargs):
587606
returncmd
588607

589608
def__get_object_header(self,cmd,ref):
590-
cmd.stdin.write(self.__prepare_ref(ref))
609+
cmd.stdin.write(self._prepare_ref(ref))
591610
cmd.stdin.flush()
592611
returnself._parse_object_header(cmd.stdout.readline())
593612

@@ -599,7 +618,7 @@ def get_object_header(self, ref):
599618
once and reuses the command in subsequent calls.
600619
601620
:return: (hexsha, type_string, size_as_int)"""
602-
cmd=self.__get_persistent_cmd("cat_file_header","cat_file",batch_check=True)
621+
cmd=self._get_persistent_cmd("cat_file_header","cat_file",batch_check=True)
603622
returnself.__get_object_header(cmd,ref)
604623

605624
defget_object_data(self,ref):
@@ -616,7 +635,7 @@ def stream_object_data(self, ref):
616635
:return: (hexsha, type_string, size_as_int, stream)
617636
:note: This method is not threadsafe, you need one independent Command instance
618637
per thread to be safe !"""
619-
cmd=self.__get_persistent_cmd("cat_file_all","cat_file",batch=True)
638+
cmd=self._get_persistent_cmd("cat_file_all","cat_file",batch=True)
620639
hexsha,typename,size=self.__get_object_header(cmd,ref)
621640
return (hexsha,typename,size,self.CatFileContentStream(size,cmd.stdout))
622641

‎git/compat.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#-*-coding:utf-8-*-
2+
# config.py
3+
# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
4+
#
5+
# This module is part of GitPython and is released under
6+
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
7+
"""utilities to help provide compatibility with python 3"""
8+
# flake8: noqa
9+
10+
importsys
11+
12+
fromgitdb.utils.compatimport (
13+
PY3,
14+
xrange,
15+
MAXSIZE,
16+
izip,
17+
)
18+
19+
fromgitdb.utils.encodingimport (
20+
string_types,
21+
text_type,
22+
force_bytes,
23+
force_text
24+
)
25+
26+
defenc=sys.getdefaultencoding()
27+
ifPY3:
28+
importio
29+
FileType=io.IOBase
30+
defbyte_ord(b):
31+
returnb
32+
defbchr(n):
33+
returnbytes([n])
34+
defmviter(d):
35+
returnd.values()
36+
else:
37+
FileType=file
38+
# usually, this is just ascii, which might not enough for our encoding needs
39+
# Unless it's set specifically, we override it to be utf-8
40+
ifdefenc=='ascii':
41+
defenc='utf-8'
42+
byte_ord=ord
43+
bchr=chr
44+
defmviter(d):
45+
returnd.itervalues()
46+
47+
48+
defwith_metaclass(meta,*bases):
49+
"""copied from https://github.com/Byron/bcore/blob/master/src/python/butility/future.py#L15"""
50+
classmetaclass(meta):
51+
__call__=type.__call__
52+
__init__=type.__init__
53+
54+
def__new__(cls,name,nbases,d):
55+
ifnbasesisNone:
56+
returntype.__new__(cls,name, (),d)
57+
# There may be clients who rely on this attribute to be set to a reasonable value, which is why
58+
# we set the __metaclass__ attribute explicitly
59+
ifnotPY3and'___metaclass__'notind:
60+
d['__metaclass__']=meta
61+
# end
62+
returnmeta(name,bases,d)
63+
# end
64+
# end metaclass
65+
returnmetaclass(meta.__name__+'Helper',None, {})
66+
# end handle py2

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp