Skip to content
This repository was archived by the owner on Apr 13, 2024. It is now read-only.

Commit 18c7ce2

Browse files
committed
Python 3 support (now supporting 2.7, 3.2, 3.3, 3.4)
... and a Travis CI config
1 parent e13dfb0 commit 18c7ce2

File tree

15 files changed

+247
-222
lines changed

15 files changed

+247
-222
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
http_signature/_version.py export-subst
2+
httpsig/_version.py export-subst

.travis.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
language: python
2+
python:
3+
- "2.7"
4+
- "3.2"
5+
- "3.3"
6+
- "3.4"
7+
install:
8+
- pip install .
9+
- pip install nose
10+
script: nosetests

MANIFEST

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ httpsig/sign.py
1111
httpsig/utils.py
1212
httpsig/verify.py
1313
httpsig/tests/__init__.py
14+
httpsig/tests/rsa_private.pem
15+
httpsig/tests/rsa_public.pem
1416
httpsig/tests/test_signature.py
1517
httpsig/tests/test_utils.py
1618
httpsig/tests/test_verify.py

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
include README.rst
22
include CHANGES.rst
33
include versioneer.py
4+
include httpsig/_version.py
5+
include httpsig/tests/*.pem

httpsig/_version.py

Lines changed: 86 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,51 @@
11

2-
IN_LONG_VERSION_PY = True
32
# This file helps to compute a version number in source trees obtained from
43
# git-archive tarball (such as those provided by githubs download-from-tag
54
# feature). Distribution tarballs (build by setup.py sdist) and build
65
# directories (produced by setup.py build) will contain a much shorter file
76
# that just contains the computed version number.
87

98
# This file is released into the public domain. Generated by
10-
# versioneer-0.7 (https://github.com/warner/python-versioneer)
9+
# versioneer-0.10 (https://github.com/warner/python-versioneer)
1110

1211
# these strings will be replaced by git during git-archive
1312
git_refnames = "$Format:%d$"
1413
git_full = "$Format:%H$"
1514

1615

1716
import subprocess
17+
import sys
18+
import errno
1819

19-
def run_command(args, cwd=None, verbose=False):
20-
try:
21-
# remember shell=False, so use git.cmd on windows, not just git
22-
p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd)
23-
except EnvironmentError, e:
20+
21+
def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
22+
assert isinstance(commands, list)
23+
p = None
24+
for c in commands:
25+
try:
26+
# remember shell=False, so use git.cmd on windows, not just git
27+
p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
28+
stderr=(subprocess.PIPE if hide_stderr
29+
else None))
30+
break
31+
except EnvironmentError:
32+
e = sys.exc_info()[1]
33+
if e.errno == errno.ENOENT:
34+
continue
35+
if verbose:
36+
print("unable to run %s" % args[0])
37+
print(e)
38+
return None
39+
else:
2440
if verbose:
25-
print "unable to run %s" % args[0]
26-
print e
41+
print("unable to find command, tried %s" % (commands,))
2742
return None
2843
stdout = p.communicate()[0].strip()
44+
if sys.version >= '3':
45+
stdout = stdout.decode()
2946
if p.returncode != 0:
3047
if verbose:
31-
print "unable to run %s (error)" % args[0]
48+
print("unable to run %s (error)" % args[0])
3249
return None
3350
return stdout
3451

@@ -37,14 +54,15 @@ def run_command(args, cwd=None, verbose=False):
3754
import re
3855
import os.path
3956

40-
def get_expanded_variables(versionfile_source):
57+
def get_expanded_variables(versionfile_abs):
4158
# the code embedded in _version.py can just fetch the value of these
4259
# variables. When used from setup.py, we don't want to import
4360
# _version.py, so we do it with a regexp instead. This function is not
4461
# used from _version.py.
4562
variables = {}
4663
try:
47-
for line in open(versionfile_source,"r").readlines():
64+
f = open(versionfile_abs,"r")
65+
for line in f.readlines():
4866
if line.strip().startswith("git_refnames ="):
4967
mo = re.search(r'=\s*"(.*)"', line)
5068
if mo:
@@ -53,6 +71,7 @@ def get_expanded_variables(versionfile_source):
5371
mo = re.search(r'=\s*"(.*)"', line)
5472
if mo:
5573
variables["full"] = mo.group(1)
74+
f.close()
5675
except EnvironmentError:
5776
pass
5877
return variables
@@ -61,80 +80,64 @@ def versions_from_expanded_variables(variables, tag_prefix, verbose=False):
6180
refnames = variables["refnames"].strip()
6281
if refnames.startswith("$Format"):
6382
if verbose:
64-
print "variables are unexpanded, not using"
83+
print("variables are unexpanded, not using")
6584
return {} # unexpanded, so not in an unpacked git-archive tarball
6685
refs = set([r.strip() for r in refnames.strip("()").split(",")])
67-
for ref in list(refs):
68-
if not re.search(r'\d', ref):
69-
if verbose:
70-
print "discarding '%s', no digits" % ref
71-
refs.discard(ref)
72-
# Assume all version tags have a digit. git's %d expansion
73-
# behaves like git log --decorate=short and strips out the
74-
# refs/heads/ and refs/tags/ prefixes that would let us
75-
# distinguish between branches and tags. By ignoring refnames
76-
# without digits, we filter out many common branch names like
77-
# "release" and "stabilization", as well as "HEAD" and "master".
86+
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
87+
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
88+
TAG = "tag: "
89+
tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
90+
if not tags:
91+
# Either we're using git < 1.8.3, or there really are no tags. We use
92+
# a heuristic: assume all version tags have a digit. The old git %d
93+
# expansion behaves like git log --decorate=short and strips out the
94+
# refs/heads/ and refs/tags/ prefixes that would let us distinguish
95+
# between branches and tags. By ignoring refnames without digits, we
96+
# filter out many common branch names like "release" and
97+
# "stabilization", as well as "HEAD" and "master".
98+
tags = set([r for r in refs if re.search(r'\d', r)])
99+
if verbose:
100+
print("discarding '%s', no digits" % ",".join(refs-tags))
78101
if verbose:
79-
print "remaining refs:", ",".join(sorted(refs))
80-
for ref in sorted(refs):
102+
print("likely tags: %s" % ",".join(sorted(tags)))
103+
for ref in sorted(tags):
81104
# sorting will prefer e.g. "2.0" over "2.0rc1"
82105
if ref.startswith(tag_prefix):
83106
r = ref[len(tag_prefix):]
84107
if verbose:
85-
print "picking %s" % r
108+
print("picking %s" % r)
86109
return { "version": r,
87110
"full": variables["full"].strip() }
88111
# no suitable tags, so we use the full revision id
89112
if verbose:
90-
print "no suitable tags, using full revision id"
113+
print("no suitable tags, using full revision id")
91114
return { "version": variables["full"].strip(),
92115
"full": variables["full"].strip() }
93116

94-
def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):
95-
# this runs 'git' from the root of the source tree. That either means
96-
# someone ran a setup.py command (and this code is in versioneer.py, so
97-
# IN_LONG_VERSION_PY=False, thus the containing directory is the root of
98-
# the source tree), or someone ran a project-specific entry point (and
99-
# this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the
100-
# containing directory is somewhere deeper in the source tree). This only
101-
# gets called if the git-archive 'subst' variables were *not* expanded,
102-
# and _version.py hasn't already been rewritten with a short version
103-
# string, meaning we're inside a checked out source tree.
117+
def versions_from_vcs(tag_prefix, root, verbose=False):
118+
# this runs 'git' from the root of the source tree. This only gets called
119+
# if the git-archive 'subst' variables were *not* expanded, and
120+
# _version.py hasn't already been rewritten with a short version string,
121+
# meaning we're inside a checked out source tree.
104122

105-
try:
106-
here = os.path.abspath(__file__)
107-
except NameError:
108-
# some py2exe/bbfreeze/non-CPython implementations don't do __file__
109-
return {} # not always correct
110-
111-
# versionfile_source is the relative path from the top of the source tree
112-
# (where the .git directory might live) to this file. Invert this to find
113-
# the root from __file__.
114-
root = here
115-
if IN_LONG_VERSION_PY:
116-
for i in range(len(versionfile_source.split("/"))):
117-
root = os.path.dirname(root)
118-
else:
119-
root = os.path.dirname(here)
120123
if not os.path.exists(os.path.join(root, ".git")):
121124
if verbose:
122-
print "no .git in", root
125+
print("no .git in %s" % root)
123126
return {}
124127

125-
GIT = "git"
128+
GITS = ["git"]
126129
if sys.platform == "win32":
127-
GIT = "git.cmd"
128-
stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"],
130+
GITS = ["git.cmd", "git.exe"]
131+
stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"],
129132
cwd=root)
130133
if stdout is None:
131134
return {}
132135
if not stdout.startswith(tag_prefix):
133136
if verbose:
134-
print "tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)
137+
print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix))
135138
return {}
136139
tag = stdout[len(tag_prefix):]
137-
stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root)
140+
stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
138141
if stdout is None:
139142
return {}
140143
full = stdout.strip()
@@ -143,34 +146,14 @@ def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):
143146
return {"version": tag, "full": full}
144147

145148

146-
def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False):
147-
if IN_LONG_VERSION_PY:
148-
# We're running from _version.py. If it's from a source tree
149-
# (execute-in-place), we can work upwards to find the root of the
150-
# tree, and then check the parent directory for a version string. If
151-
# it's in an installed application, there's no hope.
152-
try:
153-
here = os.path.abspath(__file__)
154-
except NameError:
155-
# py2exe/bbfreeze/non-CPython don't have __file__
156-
return {} # without __file__, we have no hope
157-
# versionfile_source is the relative path from the top of the source
158-
# tree to _version.py. Invert this to find the root from __file__.
159-
root = here
160-
for i in range(len(versionfile_source.split("/"))):
161-
root = os.path.dirname(root)
162-
else:
163-
# we're running from versioneer.py, which means we're running from
164-
# the setup.py in a source tree. sys.argv[0] is setup.py in the root.
165-
here = os.path.abspath(sys.argv[0])
166-
root = os.path.dirname(here)
167-
149+
def versions_from_parentdir(parentdir_prefix, root, verbose=False):
168150
# Source tarballs conventionally unpack into a directory that includes
169151
# both the project name and a version string.
170152
dirname = os.path.basename(root)
171153
if not dirname.startswith(parentdir_prefix):
172154
if verbose:
173-
print "guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % (root, dirname, parentdir_prefix)
155+
print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" %
156+
(root, dirname, parentdir_prefix))
174157
return None
175158
return {"version": dirname[len(parentdir_prefix):], "full": ""}
176159

@@ -179,14 +162,27 @@ def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False)
179162
versionfile_source = "httpsig/_version.py"
180163

181164
def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
165+
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
166+
# __file__, we can work backwards from there to the root. Some
167+
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
168+
# case we can only use expanded variables.
169+
182170
variables = { "refnames": git_refnames, "full": git_full }
183171
ver = versions_from_expanded_variables(variables, tag_prefix, verbose)
184-
if not ver:
185-
ver = versions_from_vcs(tag_prefix, versionfile_source, verbose)
186-
if not ver:
187-
ver = versions_from_parentdir(parentdir_prefix, versionfile_source,
188-
verbose)
189-
if not ver:
190-
ver = default
191-
return ver
172+
if ver:
173+
return ver
174+
175+
try:
176+
root = os.path.abspath(__file__)
177+
# versionfile_source is the relative path from the top of the source
178+
# tree (where the .git directory might live) to this file. Invert
179+
# this to find the root from __file__.
180+
for i in range(len(versionfile_source.split("/"))):
181+
root = os.path.dirname(root)
182+
except NameError:
183+
return default
184+
185+
return (versions_from_vcs(tag_prefix, root, verbose)
186+
or versions_from_parentdir(parentdir_prefix, root, verbose)
187+
or default)
192188

httpsig/requests_auth.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
from requests.auth import AuthBase
2-
from urlparse import urlparse
2+
try:
3+
# Python 3
4+
from urllib.parse import urlparse
5+
except ImportError:
6+
# Python 2
7+
from urlparse import urlparse
38

49
from .sign import HeaderSigner
510

0 commit comments

Comments
 (0)