* ubuntutools/lp/lp_functions.py,

ubuntutools/lp/udtexceptions.py:
  - Add new public functions that expose features from LP API
  - Modify isLPTeamMember to use LP API
* requestsync
  - Use new functions to check if user can upload requested package directly
    instead of checking team membership
  - Default to current development release if no release is specified on
    commandline
* buildd
  - Check if user has upload privileges instead of checking for team
    membership when seeing if operations are permitted
This commit is contained in:
Iain Lane 2009-05-09 20:09:56 +01:00
parent dc4750eb91
commit b4cd975dc8
6 changed files with 176 additions and 69 deletions

11
buildd
View File

@ -116,7 +116,7 @@ packages.checkReleaseExists(release)
(page, version) = packages.checkSourceExists(package, release)
# Get the component the package is in.
component = packages.packageComponent(package, release)
component = lp_functions.packageComponent(package, release)
# Output details.
print "The source version for '%s' in %s (%s) is at %s." % (package,
@ -156,14 +156,9 @@ if len(buildstats) == 1 and options.architecture != "i386":
# Operations that are remaining may only be done by Ubuntu developers (retry)
# or buildd admins (rescore). Check if the proper permissions are in place.
if op == "rescore": teamNeeded = "launchpad-buildd-admins"
if op == "rescore": necessaryPrivs = lp_functions.isLPTeamMember('launchpad-buildd-admins')
if op == "retry":
if component in ("main", "restricted"):
teamNeeded = "ubuntu-core-dev"
else:
teamNeeded = "ubuntu-dev"
necessaryPrivs = lp_functions.isLPTeamMember(teamNeeded)
necessaryPrivs = lp_functions.canUploadPackage(package, release)
if not necessaryPrivs:
print >> sys.stderr, "You cannot perform the %s operation on a %s package " \

16
debian/changelog vendored
View File

@ -13,7 +13,21 @@ ubuntu-dev-tools (0.74) UNRELEASED; urgency=low
- Delete the directory just after creating it if the package
doesn't exist.
-- Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com> Wed, 06 May 2009 23:14:33 +0200
[ Iain Lane ]
* ubuntutools/lp/lp_functions.py,
ubuntutools/lp/udtexceptions.py:
- Add new public functions that expose features from LP API
- Modify isLPTeamMember to use LP API
* requestsync
- Use new functions to check if user can upload requested package directly
instead of checking team membership
- Default to current development release if no release is specified on
commandline
* buildd
- Check if user has upload privileges instead of checking for team
membership when seeing if operations are permitted
-- Iain Lane <laney@ubuntu.com> Sat, 09 May 2009 20:09:28 +0100
ubuntu-dev-tools (0.73) karmic; urgency=low

View File

@ -2,7 +2,7 @@
.SH NAME
requestsync \- helper to file sync requests for Ubuntu
.SH SYNOPSIS
.B requestsync\fR [\fB\-d distro\fR] [\fB\-nse\fR] [\fB\-k \fIkeyid\fR] <\fBsource package\fR> <\fBtarget release\fR> [\fIbase version\fR]
.B requestsync\fR [\fB\-d distro\fR] [\fB\-nse\fR] [\fB\-k \fIkeyid\fR] <\fBsource package\fR> [\fBtarget release\fR] [\fIbase version\fR]
.br
.B requestsync \-\-lp\fR [\fB\-nse\fR] <\fBsource package\fR> <\fBtarget release\fR> [\fIbase version\fR]
.br

View File

@ -40,12 +40,13 @@ import ubuntutools.lp.cookie as lp_cookie
import ubuntutools.lp.functions as lp_functions
import ubuntutools.lp.libsupport as lp_libsupport
import ubuntutools.lp.urlopener as lp_urlopener
import ubuntutools.lp.udtexceptions as udtexceptions
# https_proxy fix
import ubuntutools.common
launchpad_cookiefile = lp_cookie.prepareLaunchpadCookie()
def checkNeedsSponsorship(component):
def checkNeedsSponsorship(srcpkg):
"""
Check that the user has the appropriate permissions by checking what
Launchpad returns while authenticating with their cookie.
@ -59,25 +60,14 @@ def checkNeedsSponsorship(component):
The prepareLaunchpadCookie function above shall ensure that a cookie
file exists first.
"""
# TODO: use launchpadlib here
# Once LP: #313233 has been fixed this can be implemented by either:
# >>> me = launchpad.me
# >>> me.inTeam(<TEAM>) #or
# >>> me in <TEAM>
urlopener = lp_urlopener.setupLaunchpadUrlOpener(launchpad_cookiefile)
# Check where the package is and assign the appropriate variables.
if component in ['main', 'restricted']:
team = "ubuntu-core-dev"
sponsor = "ubuntu-main-sponsors"
else:
team = "ubuntu-dev"
team = "motu"
sponsor = "ubuntu-universe-sponsors"
# Check if they are a member of the team.
teamMember = lp_functions.isLPTeamMember(team)
if not teamMember:
if not lp_functions.canUploadPackage(srcpkg):
# Check if they have a per-package upload permission.
if lp_functions.isPerPackageUploader(args[0]):
@ -89,11 +79,7 @@ def checkNeedsSponsorship(component):
"the '%s'\nteam, who shall be subscribed to this bug report." % sponsor
print "This must be done before it can be processed by a member of " \
"the Ubuntu Archive team."
print "If the above is correct please press Enter, otherwise please " \
"press Ctrl-C to stop this script now\nand check the cookie file " \
"at:", launchpad_cookiefile
print "Logging into Launchpad, deleting the above and rerunning this " \
"script should be enough to generate the cookie."
print "If the above is correct please press Enter."
raw_input_exit_on_ctrlc() # Abort if necessary.
return True # Sponsorship required.
@ -150,18 +136,14 @@ def checkExistingReports(package):
raw_input_exit_on_ctrlc()
def cur_version_component(sourcepkg, release):
'''Determine current package version in ubuntu.'''
madison = subprocess.Popen(['rmadison', '-u', 'ubuntu', '-a', 'source', \
'-s', release, sourcepkg], stdout=subprocess.PIPE)
out = madison.communicate()[0]
assert (madison.returncode == 0)
for l in out.splitlines():
(pkg, version, rel, builds) = l.split('|')
component = 'main'
if rel.find('/') != -1:
component = rel.split('/')[1]
return (version.strip(), component.strip())
try:
version = lp_functions.packageVersion(sourcepkg, release)
component = lp_functions.packageComponent(sourcepkg, release)
return (version, component)
except udtexceptions.PackageNotFoundException:
print "%s doesn't appear to exist in %s, specify -n for a package not in Ubuntu." % (sourcepkg, release)
sys.exit(1)
@ -505,15 +487,17 @@ if __name__ == '__main__':
distro = options.dist
ffe = options.ffe
if len(args) not in (2, 3):
optParser.error("Source package / target release missing - please " \
"specify.")
if len(args) not in (2, 3): # no release specified, assume development release
release = lp_functions.ubuntuDevelopmentSeries()
print >> sys.stderr, ("Source package / target release missing - assuming %s " %
release)
else:
release = args[1]
if not use_lp_bugs and not get_email_address():
sys.exit(1)
srcpkg = args[0]
release = args[1]
force_base_ver = None
# Base version specified.
@ -534,7 +518,7 @@ if __name__ == '__main__':
sys.exit(1)
# -s flag not specified - check if we do need sponsorship.
if not sponsorship: sponsorship = checkNeedsSponsorship(component)
if not sponsorship: sponsorship = checkNeedsSponsorship(srcpkg)
# Check for existing package reports.
if not newsource and use_lp_bugs: checkExistingReports(srcpkg)

View File

@ -22,45 +22,148 @@ import cookie
import urlopener as lp_urlopener
import urllib2
import sys
from udtexceptions import PackageNotFoundException, TeamNotFoundException, SeriesNotFoundException
import libsupport as lp_libsupport
import launchpadlib
from re import findall
# Takes time to initialise - move to top level so we only pay the penalty
# once. Should probably make this a proper class so we can instansiate
# singleton-style (lazily).
launchpad = lp_libsupport.get_launchpad("ubuntu-dev-tools")
def ubuntuDevelopmentSeries():
""" Get the string repr of the current Ubuntu development series """
ubuntu = launchpad.distributions['ubuntu']
return ubuntu.current_series.name
def _ubuntuSeries(name):
""" Get the LP representation of a series
returns the LP API repr of a series passed by name (e.g. 'karmic')
If the series is not found: raise SeriesNotFoundException
"""
ubuntu = launchpad.distributions['ubuntu']
try:
return ubuntu.getSeries(name_or_version=name)
except launchpadlib.errors.HTTPError:
raise SeriesNotFoundException('The series %s was not found' % name)
def _ubuntuSourcePackage(package, series):
""" Finds an Ubuntu source package on LP
returns LP API repr of the source package
If the package does not exist: raise PackageNotFoundException
"""
try:
lpseries = _ubuntuSeries(series)
ubuntu = launchpad.distributions['ubuntu']
u_archive = ubuntu.main_archive
component = u_archive.getPublishedSources(source_name=package, status="Published",
exact_match=True, distro_series=lpseries)[0]
return component
except IndexError:
raise PackageNotFoundException("The package %s does not exist in the Ubuntu main archive" %
package)
def packageVersion(package, series=ubuntuDevelopmentSeries()):
""" Retrieves the version of a given source package in the current
development distroseries
returns unicode string repr of source package version
If the package does not exist: raise PackageNotFoundException
"""
return _ubuntuSourcePackage(package, series).source_package_version
def packageComponent(package, series=ubuntuDevelopmentSeries()):
""" Retrieves the component for a given source package
returns unicode string representation of component
If the package does not exist: raise PackageNotFoundException
"""
return _ubuntuSourcePackage(package, series).component_name
def canUploadPackage(package, series=ubuntuDevelopmentSeries()):
""" Checks whether the user can upload package to Ubuntu's main archive
Uses LP API to do this.
If the user can upload the package: return True.
If the user cannot upload the package: return False.
If the package does not exist: raise PackageNotFoundException
"""
ubuntu = launchpad.distributions['ubuntu']
u_archive = ubuntu.main_archive
uploaders = u_archive.getUploadersForComponent(component_name=packageComponent(package, series))
for permission in uploaders:
current_uploader = permission.person
if _findMember(current_uploader, launchpad.me):
return True
return False
def _findMember(haystack, needle):
""" Find a person in a haystack. A haystack can consist of either people or teams.
If the needle is in the haystack: return True
If the needle is not in the haystack: return False
"""
if not haystack.is_team:
return (str(haystack) == str(needle))
else: # is a team
members = haystack.members
for m in members:
if _findMember(m, needle):
return True
return False
def isLPTeamMember(team):
""" Checks if the user is a member of a certain team on Launchpad.
We do this by opening the team page on Launchpad and checking if the
text "You are not a member of this team" is present using the
user's cookie file for authentication.
Uses the LP API.
If the user is a member of the team: return True.
If the user is not a member of the team: return False.
If the team is not found: raise a TeamNotFoundException.
"""
# TODO: Check if launchpadlib may be a better way of doing this.
# Prepare cookie.
cookieFile = cookie.prepareLaunchpadCookie()
# Prepare URL opener.
urlopener = lp_urlopener.setupLaunchpadUrlOpener(cookieFile)
# Try to open the Launchpad team page:
try:
lpTeamPage = urlopener.open("https://launchpad.net/~%s" % team).read()
except urllib2.HTTPError, error:
print >> sys.stderr, "Unable to connect to Launchpad. Received a %s." % error.code
sys.exit(1)
# Check if text is present in page.
if ("You are not a member of this team") in lpTeamPage:
return False
lpteam = launchpad.people[team]
return True
if not lpteam.is_team:
raise KeyError
return _findMember(lpteam, launchpad.me)
except KeyError:
raise TeamNotFoundException("The team %s does not exist on Launchpad" %
team)
def isPerPackageUploader(package):
# Checks if the user has upload privileges for a certain package.
launchpad = lp_libsupport.get_launchpad("ubuntu-dev-tools")
me = findall('~(\S+)', '%s' % launchpad.me)[0]
main_archive = launchpad.distributions["ubuntu"].main_archive
try:

View File

@ -0,0 +1,11 @@
class PackageNotFoundException(BaseException):
""" Thrown when a package is not found """
pass
class TeamNotFoundException(BaseException):
""" Thrown when a team is not found """
pass
class SeriesNotFoundException(BaseException):
""" Thrown when a distroseries is not found """
pass