././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5232527 launchpadlib-1.10.13/0000755000175000017500000000000000000000000016006 5ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/COPYING.txt0000644000175000017500000001672700000000000017674 0ustar00cjwatsoncjwatson00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1574442870.0 launchpadlib-1.10.13/HACKING.rst0000644000175000017500000000213700000000000017607 0ustar00cjwatsoncjwatson00000000000000.. This file is part of lazr.launchpadlib. lazr.launchpadlib is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. lazr.launchpadlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with lazr.launchpadlib. If not, see . ============ Introduction ============ To run this project's tests, use `tox `. Getting help ------------ If you find bugs in this package, you can report them here: https://launchpad.net/launchpadlib If you want to discuss this package, join the team and mailing list here: https://launchpad.net/~lazr-developers or send a message to: lazr-developers@lists.launchpad.net ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288690.0 launchpadlib-1.10.13/NEWS.rst0000644000175000017500000002305400000000000017320 0ustar00cjwatsoncjwatson00000000000000===================== NEWS for launchpadlib ===================== 1.10.13 (2020-04-19) ==================== - Fix test runs under sudo. 1.10.12 (2020-04-17) ==================== - Postpone keyring.errors import in the same way that we postpone importing keyring itself. 1.10.11 (2020-04-14) ==================== - Don't store credentials or open a browser window when running under sudo. [bug=1825014,1862948] - Fall back to in-memory credentials store if no keyring backend is available. [bug=1864204] 1.10.10 (2020-02-04) ==================== - Fix AccessToken.from_string crash on Python 3.8. [bug=1861873] 1.10.9 (2019-11-28) =================== - Explicitly install version.txt; launchpadlib requires it. 1.10.8 (2019-11-26) =================== - Squash a deprecation warning on Python >= 3.7 in launchpadlib.testing.launchpad. - Switch from buildout to tox. - Weaken hosted-files test slightly to avoid problems with zope.publisher >= 4.2.2. 1.10.7 (2019-05-22) =================== - Change 'dev' URLs from launchpad.dev to launchpad.test. 1.10.6 (2018-03-08) =================== - Fix saving of credentials in python3 with gnome-keyring. [bug=1685962] 1.10.5 (2017-02-02) =================== - Fix AccessToken.from_string crash on Python 3. [bug=1471927] - Fix fallback if authorizing a token with a browser raises webbrowser.Error. - Stop introduction.txt doctest from writing to $HOME. 1.10.4 (2016-07-12) =================== - Fix _bad_oauth_token crash on Python 3. [bug=1471894] - Time out make_end_user_authorize_token after 15 minutes. - Ignore PendingDeprecationWarning from lazr.restfulclient. [bug=1473577] - Ask forgiveness rather than permission when creating cache directories. - Fix browser token authorization on OS X. [bug=1516080] 1.10.3 (2014-12-05) =================== - Port to Python3. - Detect proxies from the environment by default. 1.10.2 (2012-07-05) =================== - Typo in the doctest fix, discovered when trying to integrate with launchpad itself. [bug=1020667] 1.10.1 (2012-07-04) =================== - Fix a doctest in introduction.txt so that the test suite runs with python-2.7 (note the doctests only run when running integrated with launchpad's test suite itself). [bug=1020667] 1.10.0 (2012-06-19) =================== - Add environment variable, LP_DISABLE_SSL_CERTIFICATE_VALIDATION, to disable SSL certificate checks. Most useful when testing against development servers. 1.9.12 (2011-12-05) =================== - Move keyring base64 encoding to KeyringCredential and be more defensive about decoding. [bug=900307] 1.9.11 (2011-11-21) =================== - 1.9.10 was a bad release due to incomplete NEWS entries. - Add fake Launchpad web service for unit test. - Improve HACKING documentation. - Improve launchpadlib directory discovery on Windows. - Added script to delete spurious bugtasks or split a bugtask from a bug. - Properly handle Unicode passwords if returned by the keyring. - Base 64 encode serialized credentials before putting in keyring/wallet. 1.9.10 (2011-11-21) =================== - Base 64 encode serialized credentials before putting in keyring/wallet. 1.9.9 (2011-07-27) ================== - Fix a failing test for lazr.restfulclient 0.12.0. 1.9.8 (2011-02-28) ================== - Detect the error Launchpad sends when it doesn't recognize an access token, and get a new token. 1.9.7 (2011-02-15) ================== - Slightly tweaked the behavior of EDGE_SERVICE_ROOT, and improved tests. 1.9.6 (2011-02-14) ================== - Added EDGE_SERVICE_ROOT and the 'edge' alias back, though they both operate on production behind the scenes. Using the 'edge' alias will cause a deprecation warning. 1.9.5 (2011-02-08) ================== - Fixed a bug that prevented the deprecated get_token_and_login code from working, and that required that users of get_token_and_login get a new token on every usage. 1.9.4 (2011-01-18) ================== - Removed references to the 'edge' service root, which is being phased out. - Fixed a minor bug in the upload_release_tarball contrib script which was causing tarballs to be uploaded with the wrong media type. - The XSLT stylesheet for converting the Launchpad WADL into HTML documentation has been moved back into Launchpad. 1.9.3 (2011-01-10) ================== - The keyring package import is now delayed until the keyring needs to be accessed. This reduces launchapdlib users' exposure to unintended side effects of importing keyring (KWallet authorization dialogs and the registration of a SIGCHLD handler). 1.9.2 (2011-01-07) ================== - Added a missing import. 1.9.1 (2011-01-06) ================== - Corrected a test failure. 1.9.0 (2011-01-05) ================== - When an authorization token expires or becomes invalid, attempt to acquire a new one, even in the middle of a session, rather than crashing. - The HTML generated by wadl-to-refhtml.xsl now validates. - Most of the helper login methods have been deprecated. There are now only two helper methods: * Launchpad.login_anonymously, for anonymous credential-free access. * Launchpad.login_with, for programs that need a credential. 1.8.0 (2010-11-15) ================== - Store authorization tokens in the Gnome keyring or KDE wallet, when available. The credentials_file parameter of Launchpad.login_with() is now ignored. - By default, Launchpad.login_with() now asks Launchpad for desktop-wide integration. This removes the need for each individual application to get its own OAuth token. 1.7.0 (2010-09-23) ================== - Removed "fake Launchpad browser" code that didn't work and was misleading developers. - Added support for http://qastaging.launchpad.net by adding astaging to the uris. 1.6.5 (2010-08-23) ================== - Make launchpadlib compatible with the latest lazr.restfulclient. 1.6.4 (2010-08-18) ================== - Test fixes. 1.6.3 (2010-08-12) ================== - Instead of making the end-user hit Enter after authorizing an application to access their Launchpad account, launchpadlib will automatically poll Launchpad until the user makes a decision. - launchpadlib now raises a more helpful exception when the end-user explicitly denies access to a launchpadlib application. - Improved the XSLT stylesheet to reflect Launchpad's more complex top-level structure. [bug=286941] - Test fixes. [bug=488448,616055] 1.6.2 (2010-06-21) ================== - Extended the optimization from version 1.6.1 to apply to Launchpad's top-level collection of people. 1.6.1 (2010-06-16) ================== - Added an optimization that lets launchpadlib avoid making an HTTP request in some situations. 1.6.0 (2010-04-07) ================== - Fixed a test to work against the latest version of Launchpad. 1.5.8 (2010-03-25) ================== - Use version 1.0 of the Launchpad web service by default. 1.5.7 (2010-03-16) ================== - Send a Referer header whenever making requests to the Launchpad website (as opposed to the web service) to avoid falling afoul of new cross-site-request-forgery countermeasures. 1.5.6 (2010-03-04) ================== - Fixed a minor bug when using login_with() to access a version of the Launchpad web service other than the default. - Added a check to catch old client code that would cause newer versions of launchpadlib to make nonsensical requests to https://api.launchpad.dev/beta/beta/, and raise a helpful exception telling the developer how to fix it. 1.5.5 ===== - Added the ability to access different versions of the Launchpad web service. 1.5.4 (2009-12-17) ================== - Made it easy to get anonymous access to a Launchpad instance. - Made it easy to plug in different clients that take the user's Launchpad login and password for purposes of authorizing a request token. The most secure technique is still the default: to open the user's web browser to the appropriate Launchpad page. - Introduced a command-line script bin/launchpad-credentials-console, which takes the user's Launchpad login and password, and authorizes a request token on their behalf. - Introduced a command-line script bin/launchpad-request-token, which creates a request token on any Launchpad installation and dumps the JSON description of that token to standard output. - Shorthand service names like 'edge' should now be respected everywhere in launchpadlib. 1.5.3 (2009-10-22) ================== - Moved some more code from launchpadlib into the more generic lazr.restfulclient. 1.5.2 (2009-10-01) ================== - Added a number of new sample scripts from elsewhere. - Added a reference to the production Launchpad instance. - Made it easier to specify a Launchpad instance to run against. 1.5.1 (2009-07-16) ================== - Added a sample script for uploading a release tarball to Launchpad. 1.5.0 (2009-07-09) ================== - Most of launchpadlib's code has been moved to the generic lazr.restfulclient library. launchpadlib now contains only code specific to Launchpad. There should be no changes in functionality. - Moved bootstrap.py into the top-level directory. Having it in a subdirectory with a top-level symlink was breaking installation on Windows. - The notice to the end-user (that we're opening their web browser) is now better formatted. 1.0.1 (2009-05-30) ================== - Correct tests for new launchpad cache behavior in librarian - Remove build dependency on setuptools_bzr because it was causing bzr to be downloaded during installation of the package, which was unnecessary and annoying. 1.0 (2009-03-24) ================ - Initial release on PyPI ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5232527 launchpadlib-1.10.13/PKG-INFO0000644000175000017500000003431000000000000017104 0ustar00cjwatsoncjwatson00000000000000Metadata-Version: 2.1 Name: launchpadlib Version: 1.10.13 Summary: Script Launchpad through its web services interfaces. Officially supported. Home-page: https://help.launchpad.net/API/launchpadlib Author: The Launchpad developers Author-email: launchpadlib@lists.launchpad.net Maintainer: LAZR Developers Maintainer-email: lazr-developers@lists.launchpad.net License: LGPL v3 Download-URL: https://launchpad.net/launchpadlib/+download Description: .. This file is part of launchpadlib. launchpadlib is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. launchpadlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with launchpadlib. If not, see . launchpadlib ************ See https://help.launchpad.net/API/launchpadlib . ===================== NEWS for launchpadlib ===================== 1.10.13 (2020-04-19) ==================== - Fix test runs under sudo. 1.10.12 (2020-04-17) ==================== - Postpone keyring.errors import in the same way that we postpone importing keyring itself. 1.10.11 (2020-04-14) ==================== - Don't store credentials or open a browser window when running under sudo. [bug=1825014,1862948] - Fall back to in-memory credentials store if no keyring backend is available. [bug=1864204] 1.10.10 (2020-02-04) ==================== - Fix AccessToken.from_string crash on Python 3.8. [bug=1861873] 1.10.9 (2019-11-28) =================== - Explicitly install version.txt; launchpadlib requires it. 1.10.8 (2019-11-26) =================== - Squash a deprecation warning on Python >= 3.7 in launchpadlib.testing.launchpad. - Switch from buildout to tox. - Weaken hosted-files test slightly to avoid problems with zope.publisher >= 4.2.2. 1.10.7 (2019-05-22) =================== - Change 'dev' URLs from launchpad.dev to launchpad.test. 1.10.6 (2018-03-08) =================== - Fix saving of credentials in python3 with gnome-keyring. [bug=1685962] 1.10.5 (2017-02-02) =================== - Fix AccessToken.from_string crash on Python 3. [bug=1471927] - Fix fallback if authorizing a token with a browser raises webbrowser.Error. - Stop introduction.txt doctest from writing to $HOME. 1.10.4 (2016-07-12) =================== - Fix _bad_oauth_token crash on Python 3. [bug=1471894] - Time out make_end_user_authorize_token after 15 minutes. - Ignore PendingDeprecationWarning from lazr.restfulclient. [bug=1473577] - Ask forgiveness rather than permission when creating cache directories. - Fix browser token authorization on OS X. [bug=1516080] 1.10.3 (2014-12-05) =================== - Port to Python3. - Detect proxies from the environment by default. 1.10.2 (2012-07-05) =================== - Typo in the doctest fix, discovered when trying to integrate with launchpad itself. [bug=1020667] 1.10.1 (2012-07-04) =================== - Fix a doctest in introduction.txt so that the test suite runs with python-2.7 (note the doctests only run when running integrated with launchpad's test suite itself). [bug=1020667] 1.10.0 (2012-06-19) =================== - Add environment variable, LP_DISABLE_SSL_CERTIFICATE_VALIDATION, to disable SSL certificate checks. Most useful when testing against development servers. 1.9.12 (2011-12-05) =================== - Move keyring base64 encoding to KeyringCredential and be more defensive about decoding. [bug=900307] 1.9.11 (2011-11-21) =================== - 1.9.10 was a bad release due to incomplete NEWS entries. - Add fake Launchpad web service for unit test. - Improve HACKING documentation. - Improve launchpadlib directory discovery on Windows. - Added script to delete spurious bugtasks or split a bugtask from a bug. - Properly handle Unicode passwords if returned by the keyring. - Base 64 encode serialized credentials before putting in keyring/wallet. 1.9.10 (2011-11-21) =================== - Base 64 encode serialized credentials before putting in keyring/wallet. 1.9.9 (2011-07-27) ================== - Fix a failing test for lazr.restfulclient 0.12.0. 1.9.8 (2011-02-28) ================== - Detect the error Launchpad sends when it doesn't recognize an access token, and get a new token. 1.9.7 (2011-02-15) ================== - Slightly tweaked the behavior of EDGE_SERVICE_ROOT, and improved tests. 1.9.6 (2011-02-14) ================== - Added EDGE_SERVICE_ROOT and the 'edge' alias back, though they both operate on production behind the scenes. Using the 'edge' alias will cause a deprecation warning. 1.9.5 (2011-02-08) ================== - Fixed a bug that prevented the deprecated get_token_and_login code from working, and that required that users of get_token_and_login get a new token on every usage. 1.9.4 (2011-01-18) ================== - Removed references to the 'edge' service root, which is being phased out. - Fixed a minor bug in the upload_release_tarball contrib script which was causing tarballs to be uploaded with the wrong media type. - The XSLT stylesheet for converting the Launchpad WADL into HTML documentation has been moved back into Launchpad. 1.9.3 (2011-01-10) ================== - The keyring package import is now delayed until the keyring needs to be accessed. This reduces launchapdlib users' exposure to unintended side effects of importing keyring (KWallet authorization dialogs and the registration of a SIGCHLD handler). 1.9.2 (2011-01-07) ================== - Added a missing import. 1.9.1 (2011-01-06) ================== - Corrected a test failure. 1.9.0 (2011-01-05) ================== - When an authorization token expires or becomes invalid, attempt to acquire a new one, even in the middle of a session, rather than crashing. - The HTML generated by wadl-to-refhtml.xsl now validates. - Most of the helper login methods have been deprecated. There are now only two helper methods: * Launchpad.login_anonymously, for anonymous credential-free access. * Launchpad.login_with, for programs that need a credential. 1.8.0 (2010-11-15) ================== - Store authorization tokens in the Gnome keyring or KDE wallet, when available. The credentials_file parameter of Launchpad.login_with() is now ignored. - By default, Launchpad.login_with() now asks Launchpad for desktop-wide integration. This removes the need for each individual application to get its own OAuth token. 1.7.0 (2010-09-23) ================== - Removed "fake Launchpad browser" code that didn't work and was misleading developers. - Added support for http://qastaging.launchpad.net by adding astaging to the uris. 1.6.5 (2010-08-23) ================== - Make launchpadlib compatible with the latest lazr.restfulclient. 1.6.4 (2010-08-18) ================== - Test fixes. 1.6.3 (2010-08-12) ================== - Instead of making the end-user hit Enter after authorizing an application to access their Launchpad account, launchpadlib will automatically poll Launchpad until the user makes a decision. - launchpadlib now raises a more helpful exception when the end-user explicitly denies access to a launchpadlib application. - Improved the XSLT stylesheet to reflect Launchpad's more complex top-level structure. [bug=286941] - Test fixes. [bug=488448,616055] 1.6.2 (2010-06-21) ================== - Extended the optimization from version 1.6.1 to apply to Launchpad's top-level collection of people. 1.6.1 (2010-06-16) ================== - Added an optimization that lets launchpadlib avoid making an HTTP request in some situations. 1.6.0 (2010-04-07) ================== - Fixed a test to work against the latest version of Launchpad. 1.5.8 (2010-03-25) ================== - Use version 1.0 of the Launchpad web service by default. 1.5.7 (2010-03-16) ================== - Send a Referer header whenever making requests to the Launchpad website (as opposed to the web service) to avoid falling afoul of new cross-site-request-forgery countermeasures. 1.5.6 (2010-03-04) ================== - Fixed a minor bug when using login_with() to access a version of the Launchpad web service other than the default. - Added a check to catch old client code that would cause newer versions of launchpadlib to make nonsensical requests to https://api.launchpad.dev/beta/beta/, and raise a helpful exception telling the developer how to fix it. 1.5.5 ===== - Added the ability to access different versions of the Launchpad web service. 1.5.4 (2009-12-17) ================== - Made it easy to get anonymous access to a Launchpad instance. - Made it easy to plug in different clients that take the user's Launchpad login and password for purposes of authorizing a request token. The most secure technique is still the default: to open the user's web browser to the appropriate Launchpad page. - Introduced a command-line script bin/launchpad-credentials-console, which takes the user's Launchpad login and password, and authorizes a request token on their behalf. - Introduced a command-line script bin/launchpad-request-token, which creates a request token on any Launchpad installation and dumps the JSON description of that token to standard output. - Shorthand service names like 'edge' should now be respected everywhere in launchpadlib. 1.5.3 (2009-10-22) ================== - Moved some more code from launchpadlib into the more generic lazr.restfulclient. 1.5.2 (2009-10-01) ================== - Added a number of new sample scripts from elsewhere. - Added a reference to the production Launchpad instance. - Made it easier to specify a Launchpad instance to run against. 1.5.1 (2009-07-16) ================== - Added a sample script for uploading a release tarball to Launchpad. 1.5.0 (2009-07-09) ================== - Most of launchpadlib's code has been moved to the generic lazr.restfulclient library. launchpadlib now contains only code specific to Launchpad. There should be no changes in functionality. - Moved bootstrap.py into the top-level directory. Having it in a subdirectory with a top-level symlink was breaking installation on Windows. - The notice to the end-user (that we're opening their web browser) is now better formatted. 1.0.1 (2009-05-30) ================== - Correct tests for new launchpad cache behavior in librarian - Remove build dependency on setuptools_bzr because it was causing bzr to be downloaded during installation of the package, which was unnecessary and annoying. 1.0 (2009-03-24) ================ - Initial release on PyPI Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Provides-Extra: docs Provides-Extra: test ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/README.rst0000644000175000017500000000370400000000000017501 0ustar00cjwatsoncjwatson00000000000000Script Launchpad through its web services interfaces. Officially supported. .. Copyright (C) 2008-2009 Canonical Ltd. This file is part of launchpadlib. launchpadlib is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. launchpadlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with launchpadlib. If not, see . Overview ======== launchpadlib is a standalone Python library for scripting Launchpad through its web services interface. It is the officially supported bindings to the Launchpad web service, but there may be third party bindings that provide scriptability for other languages. Launchpad (http://launchpad.net) is a a free software hosting and development website, making it easy to collaborate across multiple projects. For information on Launchpad itself, see https://help.launchpad.net More information on the Launchpad web service, such as user guides and reference documentation, are available at https://help.launchpad.net/API Client documentation for launchpadlib is available at https://help.launchpad.net/API/launchpadlib Please submit bug reports to https://bugs.launchpad.net/launchpadlib Credential storage ================== After authorizing an application to access Launchpad on a user's behalf, launchpadlib will attempt to store those credentials in the most system-appropriate way. That is, on Gnome it will store them in the Gnome keyring, on KDE it will store them in the KDE wallet and if neither of those is available it will store them on disk. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5232527 launchpadlib-1.10.13/setup.cfg0000644000175000017500000000004600000000000017627 0ustar00cjwatsoncjwatson00000000000000[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288570.0 launchpadlib-1.10.13/setup.py0000755000175000017500000000621200000000000017524 0ustar00cjwatsoncjwatson00000000000000#!/usr/bin/env python # Copyright 2008-2009 Canonical Ltd. # # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . """Setup for the launchpadlib library.""" import sys from setuptools import setup, find_packages # generic helpers primarily for the long_description def generate(*docname_or_string): marker = '.. pypi description ends here' res = [] for value in docname_or_string: if value.endswith('.rst'): with open(value) as f: value = f.read() idx = value.find(marker) if idx >= 0: value = value[:idx] res.append(value) if not value.endswith('\n'): res.append('') return '\n'.join(res) # end generic helpers with open("src/launchpadlib/version.txt") as version_file: __version__ = version_file.read().strip() install_requires = [ 'httplib2', 'keyring', 'lazr.restfulclient>=0.9.19', 'lazr.uri', 'setuptools', 'six', 'testresources', 'wadllib', ] if sys.version < "2.6": install_requires.append('simplejson') setup( name='launchpadlib', version=__version__, packages=find_packages('src'), package_dir={'':'src'}, package_data={'launchpadlib': ['version.txt']}, include_package_data=True, zip_safe=False, author='The Launchpad developers', author_email='launchpadlib@lists.launchpad.net', maintainer='LAZR Developers', maintainer_email='lazr-developers@lists.launchpad.net', download_url= 'https://launchpad.net/launchpadlib/+download', description=open('README.rst').readline().strip(), long_description=generate( 'src/launchpadlib/docs/index.rst', 'NEWS.rst'), license='LGPL v3', install_requires=install_requires, url='https://help.launchpad.net/API/launchpadlib', classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", ], extras_require={ 'docs': ['Sphinx'], 'test': ['mock; python_version < "3"'], }, test_suite='launchpadlib.tests', ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5152526 launchpadlib-1.10.13/src/0000755000175000017500000000000000000000000016575 5ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5152526 launchpadlib-1.10.13/src/launchpadlib/0000755000175000017500000000000000000000000021223 5ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1574442870.0 launchpadlib-1.10.13/src/launchpadlib/__init__.py0000644000175000017500000000143000000000000023332 0ustar00cjwatsoncjwatson00000000000000# Copyright 2008-2011 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . import pkg_resources __version__ = pkg_resources.resource_string( "launchpadlib", "version.txt").strip() ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1436278028.0 launchpadlib-1.10.13/src/launchpadlib/apps.py0000644000175000017500000000313100000000000022536 0ustar00cjwatsoncjwatson00000000000000# Copyright 2009 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . """Command-line applications for Launchpadlib. This module contains the code for various applications. The applications themselves are kept in bin/. """ __all__ = [ 'RequestTokenApp', ] try: import json except ImportError: import simplejson as json from launchpadlib.credentials import Credentials from launchpadlib.uris import lookup_web_root class RequestTokenApp(object): """An application that creates request tokens.""" def __init__(self, web_root, consumer_name, context): """Initialize.""" self.web_root = lookup_web_root(web_root) self.credentials = Credentials(consumer_name) self.context = context def run(self): """Get a request token and return JSON information about it.""" token = self.credentials.get_request_token( self.context, self.web_root, token_format=Credentials.DICT_TOKEN_FORMAT) return json.dumps(token) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587115752.0 launchpadlib-1.10.13/src/launchpadlib/credentials.py0000644000175000017500000007411000000000000024075 0ustar00cjwatsoncjwatson00000000000000# Copyright 2008 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . from __future__ import print_function """launchpadlib credentials and authentication support.""" __metaclass__ = type __all__ = [ 'AccessToken', 'AnonymousAccessToken', 'AuthorizeRequestTokenWithBrowser', 'CredentialStore', 'RequestTokenAuthorizationEngine', 'Consumer', 'Credentials', ] try: from cStringIO import StringIO except ImportError: from io import StringIO import httplib2 import os from select import select import stat from sys import stdin import time try: from urllib.parse import urlencode except ImportError: from urllib import urlencode try: from urllib.parse import urljoin except ImportError: from urlparse import urljoin import webbrowser from base64 import ( b64decode, b64encode, ) try: import json except ImportError: import simplejson as json from six.moves.urllib.parse import parse_qs if bytes is str: # Python 2 unicode_type = unicode else: unicode_type = str from lazr.restfulclient.errors import HTTPError from lazr.restfulclient.authorize.oauth import ( AccessToken as _AccessToken, Consumer, OAuthAuthorizer, SystemWideConsumer # Not used directly, just re-imported into here. ) from launchpadlib import uris request_token_page = '+request-token' access_token_page = '+access-token' authorize_token_page = '+authorize-token' access_token_poll_time = 1 access_token_poll_timeout = 15 * 60 EXPLOSIVE_ERRORS = (MemoryError, KeyboardInterrupt, SystemExit) def _ssl_certificate_validation_disabled(): """Whether the user has disabled SSL certificate connection. Some testing servers have broken certificates. Rather than raising an error, we allow an environment variable, ``LP_DISABLE_SSL_CERTIFICATE_VALIDATION`` to disable the check. """ # XXX: Copied from lazr/restfulclient/_browser.py. Once it appears in a # released version of lazr.restfulclient, depend on that new version and # delete this copy. return bool( os.environ.get('LP_DISABLE_SSL_CERTIFICATE_VALIDATION', False)) def _http_post(url, headers, params): """POST to ``url`` with ``headers`` and a body of urlencoded ``params``. Wraps it up to make sure we avoid the SSL certificate validation if our environment tells us to. Also, raises an error on non-200 statuses. """ cert_disabled = _ssl_certificate_validation_disabled() response, content = httplib2.Http( disable_ssl_certificate_validation=cert_disabled).request( url, method='POST', headers=headers, body=urlencode(params)) if response.status != 200: raise HTTPError(response, content) return response, content class Credentials(OAuthAuthorizer): """Standard credentials storage and usage class. :ivar consumer: The consumer (application) :type consumer: `Consumer` :ivar access_token: Access information on behalf of the user :type access_token: `AccessToken` """ _request_token = None URI_TOKEN_FORMAT = "uri" DICT_TOKEN_FORMAT = "dict" ITEM_SEPARATOR = '
' NEWLINE = '\n' def serialize(self): """Turn this object into a string. This should probably be moved into OAuthAuthorizer. """ sio = StringIO() self.save(sio) serialized = sio.getvalue() if isinstance(serialized, unicode_type): serialized = serialized.encode('utf-8') return serialized @classmethod def from_string(cls, value): """Create a `Credentials` object from a serialized string. This should probably be moved into OAuthAuthorizer. """ credentials = cls() if not isinstance(value, unicode_type): value = value.decode('utf-8') credentials.load(StringIO(value)) return credentials def get_request_token(self, context=None, web_root=uris.STAGING_WEB_ROOT, token_format=URI_TOKEN_FORMAT): """Request an OAuth token to Launchpad. Also store the token in self._request_token. This method must not be called on an object with no consumer specified or if an access token has already been obtained. :param context: The context of this token, that is, its scope of validity within Launchpad. :param web_root: The URL of the website on which the token should be requested. :token_format: How the token should be presented. URI_TOKEN_FORMAT means just return the URL to the page that authorizes the token. DICT_TOKEN_FORMAT means return a dictionary describing the token and the site's authentication policy. :return: If token_format is URI_TOKEN_FORMAT, the URL for the user to authorize the `AccessToken` provided by Launchpad. If token_format is DICT_TOKEN_FORMAT, a dict of information about the new access token. """ assert self.consumer is not None, "Consumer not specified." assert self.access_token is None, "Access token already obtained." web_root = uris.lookup_web_root(web_root) params = dict( oauth_consumer_key=self.consumer.key, oauth_signature_method='PLAINTEXT', oauth_signature='&') url = web_root + request_token_page headers = {'Referer': web_root} if token_format == self.DICT_TOKEN_FORMAT: headers['Accept'] = 'application/json' response, content = _http_post(url, headers, params) if isinstance(content, bytes): content = content.decode('utf-8') if token_format == self.DICT_TOKEN_FORMAT: params = json.loads(content) if context is not None: params["lp.context"] = context self._request_token = AccessToken.from_params(params) return params else: self._request_token = AccessToken.from_string(content) url = '%s%s?oauth_token=%s' % (web_root, authorize_token_page, self._request_token.key) if context is not None: self._request_token.context = context url += "&lp.context=%s" % context return url def exchange_request_token_for_access_token( self, web_root=uris.STAGING_WEB_ROOT): """Exchange the previously obtained request token for an access token. This method must not be called unless get_request_token() has been called and completed successfully. The access token will be stored as self.access_token. :param web_root: The base URL of the website that granted the request token. """ assert self._request_token is not None, ( "get_request_token() doesn't seem to have been called.") web_root = uris.lookup_web_root(web_root) params = dict( oauth_consumer_key=self.consumer.key, oauth_signature_method='PLAINTEXT', oauth_token=self._request_token.key, oauth_signature='&%s' % self._request_token.secret) url = web_root + access_token_page headers = {'Referer': web_root} response, content = _http_post(url, headers, params) self.access_token = AccessToken.from_string(content) class AccessToken(_AccessToken): """An OAuth access token.""" @classmethod def from_params(cls, params): """Create and return a new `AccessToken` from the given dict.""" key = params['oauth_token'] secret = params['oauth_token_secret'] context = params.get('lp.context') return cls(key, secret, context) @classmethod def from_string(cls, query_string): """Create and return a new `AccessToken` from the given string.""" if not isinstance(query_string, unicode_type): query_string = query_string.decode('utf-8') params = parse_qs(query_string, keep_blank_values=False) key = params['oauth_token'] assert len(key) == 1, ( "Query string must have exactly one oauth_token.") key = key[0] secret = params['oauth_token_secret'] assert len(secret) == 1, "Query string must have exactly one secret." secret = secret[0] context = params.get('lp.context') if context is not None: assert len(context) == 1, ( "Query string must have exactly one context") context = context[0] return cls(key, secret, context) class AnonymousAccessToken(_AccessToken): """An OAuth access token that doesn't authenticate anybody. This token can be used for anonymous access. """ def __init__(self): super(AnonymousAccessToken, self).__init__('','') class CredentialStore(object): """Store OAuth credentials locally. This is a generic superclass. To implement a specific way of storing credentials locally you'll need to subclass this class, and implement `do_save` and `do_load`. """ def __init__(self, credential_save_failed=None): """Constructor. :param credential_save_failed: A callback to be invoked if the save to local storage fails. You should never invoke this callback yourself! Instead, you should raise an exception from do_save(). """ self.credential_save_failed = credential_save_failed def save(self, credentials, unique_consumer_id): """Save the credentials and invoke the callback on failure. Do not override this method when subclassing. Override do_save() instead. """ try: self.do_save(credentials, unique_consumer_id) except EXPLOSIVE_ERRORS: raise except Exception as e: if self.credential_save_failed is None: raise e self.credential_save_failed() return credentials def do_save(self, credentials, unique_consumer_id): """Store newly-authorized credentials locally for later use. :param credentials: A Credentials object to save. :param unique_consumer_id: A string uniquely identifying an OAuth consumer on a Launchpad instance. """ raise NotImplementedError() def load(self, unique_key): """Retrieve credentials from a local store. This method is the inverse of `save`. There's no special behavior in this method--it just calls `do_load`. There _is_ special behavior in `save`, and this way, developers can remember to implement `do_save` and `do_load`, not `do_save` and `load`. :param unique_key: A string uniquely identifying an OAuth consumer on a Launchpad instance. :return: A `Credentials` object if one is found in the local store, and None otherise. """ return self.do_load(unique_key) def do_load(self, unique_key): """Retrieve credentials from a local store. This method is the inverse of `do_save`. :param unique_key: A string uniquely identifying an OAuth consumer on a Launchpad instance. :return: A `Credentials` object if one is found in the local store, and None otherise. """ raise NotImplementedError() class KeyringCredentialStore(CredentialStore): """Store credentials in the GNOME keyring or KDE wallet. This is a good solution for desktop applications and interactive scripts. It doesn't work for non-interactive scripts, or for integrating third-party websites into Launchpad. """ B64MARKER = b"" def __init__(self, credential_save_failed=None, fallback=False): super(KeyringCredentialStore, self).__init__(credential_save_failed) self._fallback = None if fallback: self._fallback = MemoryCredentialStore(credential_save_failed) @staticmethod def _ensure_keyring_imported(): """Ensure the keyring module is imported (postponing side effects). The keyring module initializes the environment-dependent backend at import time (nasty). We want to avoid that initialization because it may do things like prompt the user to unlock their password store (e.g., KWallet). """ if 'keyring' not in globals(): global keyring import keyring if 'NoKeyringError' not in globals(): global NoKeyringError try: from keyring.errors import NoKeyringError except ImportError: NoKeyringError = RuntimeError def do_save(self, credentials, unique_key): """Store newly-authorized credentials in the keyring.""" self._ensure_keyring_imported() serialized = credentials.serialize() # Some users have reported problems with corrupted keyrings, both in # Gnome and KDE, when newlines are included in the password. Avoid # this problem by base 64 encoding the serialized value. serialized = self.B64MARKER + b64encode(serialized) try: keyring.set_password( 'launchpadlib', unique_key, serialized.decode('utf-8')) except NoKeyringError as e: # keyring < 21.2.0 raises RuntimeError rather than anything more # specific. Make sure it's the exception we're interested in. if (NoKeyringError == RuntimeError and 'No recommended backend was available' not in str(e)): raise if self._fallback: self._fallback.save(credentials, unique_key) else: raise def do_load(self, unique_key): """Retrieve credentials from the keyring.""" self._ensure_keyring_imported() try: credential_string = keyring.get_password( 'launchpadlib', unique_key) except NoKeyringError as e: # keyring < 21.2.0 raises RuntimeError rather than anything more # specific. Make sure it's the exception we're interested in. if (NoKeyringError == RuntimeError and 'No recommended backend was available' not in str(e)): raise if self._fallback: return self._fallback.load(unique_key) else: raise if credential_string is not None: if isinstance(credential_string, unicode_type): credential_string = credential_string.encode('utf8') if credential_string.startswith(self.B64MARKER): try: credential_string = b64decode( credential_string[len(self.B64MARKER):]) except TypeError: # The credential_string should be base 64 but cannot be # decoded. return None try: credentials = Credentials.from_string(credential_string) return credentials except: # If any error occurs at this point the most reasonable thing # to do is return no credentials, which will require # re-authorization but the user will be able to proceed. return None return None class UnencryptedFileCredentialStore(CredentialStore): """Store credentials unencrypted in a file on disk. This is a good solution for scripts that need to run without any user interaction. """ def __init__(self, filename, credential_save_failed=None): super(UnencryptedFileCredentialStore, self).__init__( credential_save_failed) self.filename = filename def do_save(self, credentials, unique_key): """Save the credentials to disk.""" credentials.save_to_path(self.filename) def do_load(self, unique_key): """Load the credentials from disk.""" if (os.path.exists(self.filename) and not os.stat(self.filename)[stat.ST_SIZE] == 0): return Credentials.load_from_path(self.filename) return None class MemoryCredentialStore(CredentialStore): """CredentialStore that stores keys only in memory. This can be used to provide a CredentialStore instance without actually saving any key to persistent storage. """ def __init__(self, credential_save_failed=None): super(MemoryCredentialStore, self).__init__(credential_save_failed) self._credentials = {} def do_save(self, credentials, unique_key): """Store the credentials in our dict""" self._credentials[unique_key] = credentials def do_load(self, unique_key): """Retrieve the credentials from our dict""" return self._credentials.get(unique_key) class RequestTokenAuthorizationEngine(object): """The superclass of all request token authorizers. This base class does not implement request token authorization, since that varies depending on how you want the end-user to authorize a request token. You'll need to subclass this class and implement `make_end_user_authorize_token`. """ UNAUTHORIZED_ACCESS_LEVEL = "UNAUTHORIZED" def __init__(self, service_root, application_name=None, consumer_name=None, allow_access_levels=None): """Base class initialization. :param service_root: The root of the Launchpad instance being used. :param application_name: The name of the application that wants to use launchpadlib. This is used in conjunction with a desktop-wide integration. If you specify this argument, your values for consumer_name and allow_access_levels are ignored. :param consumer_name: The OAuth consumer name, for an application that wants its own point of integration into Launchpad. In almost all cases, you want to specify application_name instead and do a desktop-wide integration. The exception is when you're integrating a third-party website into Launchpad. :param allow_access_levels: A list of the Launchpad access levels to present to the user. ('READ_PUBLIC' and so on.) Your value for this argument will be ignored during a desktop-wide integration. :type allow_access_levels: A list of strings. """ self.service_root = uris.lookup_service_root(service_root) self.web_root = uris.web_root_for_service_root(service_root) if application_name is None and consumer_name is None: raise ValueError( "You must provide either application_name or consumer_name.") if application_name is not None and consumer_name is not None: raise ValueError( "You must provide only one of application_name and " "consumer_name. (You provided %r and %r.)" % ( application_name, consumer_name)) if consumer_name is None: # System-wide integration. Create a system-wide consumer # and identify the application using a separate # application name. allow_access_levels = ["DESKTOP_INTEGRATION"] consumer = SystemWideConsumer(application_name) else: # Application-specific integration. Use the provided # consumer name to create a consumer automatically. consumer = Consumer(consumer_name) application_name = consumer_name self.consumer = consumer self.application_name = application_name self.allow_access_levels = allow_access_levels or [] @property def unique_consumer_id(self): """Return a string identifying this consumer on this host.""" return self.consumer.key + '@' + self.service_root def authorization_url(self, request_token): """Return the authorization URL for a request token. This is the URL the end-user must visit to authorize the token. How exactly does this happen? That depends on the subclass implementation. """ page = "%s?oauth_token=%s" % (authorize_token_page, request_token) allow_permission = "&allow_permission=" if len(self.allow_access_levels) > 0: page += ( allow_permission + allow_permission.join(self.allow_access_levels)) return urljoin(self.web_root, page) def __call__(self, credentials, credential_store): """Authorize a token and associate it with the given credentials. If the credential store runs into a problem storing the credential locally, the `credential_save_failed` callback will be invoked. The callback will not be invoked if there's a problem authorizing the credentials. :param credentials: A `Credentials` object. If the end-user authorizes these credentials, this object will have its .access_token property set. :param credential_store: A `CredentialStore` object. If the end-user authorizes the credentials, they will be persisted locally using this object. :return: If the credentials are successfully authorized, the return value is the `Credentials` object originally passed in. Otherwise the return value is None. """ request_token_string = self.get_request_token(credentials) # Hand off control to the end-user. self.make_end_user_authorize_token(credentials, request_token_string) if credentials.access_token is None: # The end-user refused to authorize the application. return None # save() invokes the callback on failure. credential_store.save(credentials, self.unique_consumer_id) return credentials def get_request_token(self, credentials): """Get a new request token from the server. :param return: The request token. """ authorization_json = credentials.get_request_token( web_root=self.web_root, token_format=Credentials.DICT_TOKEN_FORMAT) return authorization_json['oauth_token'] def make_end_user_authorize_token(self, credentials, request_token): """Authorize the given request token using the given credentials. Your subclass must implement this method: it has no default implementation. Because an access token may expire or be revoked in the middle of a session, this method may be called at arbitrary points in a launchpadlib session, or even multiple times during a single session (with a different request token each time). In most cases, however, this method will be called at the beginning of a launchpadlib session, or not at all. """ raise NotImplementedError() class AuthorizeRequestTokenWithURL(RequestTokenAuthorizationEngine): """Authorize using a URL. This authorizer simply shows the URL for the user to open for authorization, and waits until the server responds. """ WAITING_FOR_USER = ( "Please open this authorization page:\n" " (%s)\n" "in your browser. Use your browser to authorize\n" "this program to access Launchpad on your behalf.") WAITING_FOR_LAUNCHPAD = ( "Press Enter after authorizing in your browser.") def output(self, message): """Display a message. By default, prints the message to standard output. The message does not require any user interaction--it's solely informative. """ print(message) def notify_end_user_authorization_url(self, authorization_url): """Notify the end-user of the URL.""" self.output(self.WAITING_FOR_USER % authorization_url) def check_end_user_authorization(self, credentials): """Check if the end-user authorized""" try: credentials.exchange_request_token_for_access_token( self.web_root) except HTTPError as e: if e.response.status == 403: # The user decided not to authorize this # application. raise EndUserDeclinedAuthorization(e.content) else: if e.response.status != 401: # There was an error accessing the server. print("Unexpected response from Launchpad:") print(e) # The user has not made a decision yet. raise EndUserNoAuthorization(e.content) return credentials.access_token is not None def wait_for_end_user_authorization(self, credentials): """Wait for the end-user to authorize""" self.output(self.WAITING_FOR_LAUNCHPAD) stdin.readline() self.check_end_user_authorization(credentials) def make_end_user_authorize_token(self, credentials, request_token): """Have the end-user authorize the token using a URL.""" authorization_url = self.authorization_url(request_token) self.notify_end_user_authorization_url(authorization_url) self.wait_for_end_user_authorization(credentials) class AuthorizeRequestTokenWithBrowser(AuthorizeRequestTokenWithURL): """Authorize using a URL that pops-up automatically in a browser. This authorizer simply opens up the end-user's web browser to a Launchpad URL and lets the end-user authorize the request token themselves. This is the same as its superclass, except this class also performs the browser automatic opening of the URL. """ WAITING_FOR_USER = ( "The authorization page:\n" " (%s)\n" "should be opening in your browser. Use your browser to authorize\n" "this program to access Launchpad on your behalf.") TIMEOUT_MESSAGE = "Press Enter to continue or wait (%d) seconds..." TIMEOUT = 5 TERMINAL_BROWSERS = ('www-browser', 'links', 'links2', 'lynx', 'elinks', 'elinks-lite', 'netrik', 'w3m') WAITING_FOR_LAUNCHPAD = ( "Waiting to hear from Launchpad about your decision...") def __init__(self, service_root, application_name, consumer_name=None, credential_save_failed=None, allow_access_levels=None): """Constructor. :param service_root: See `RequestTokenAuthorizationEngine`. :param application_name: See `RequestTokenAuthorizationEngine`. :param consumer_name: The value of this argument is ignored. If we have the capability to open the end-user's web browser, we must be running on the end-user's computer, so we should do a full desktop integration. :param credential_save_failed: See `RequestTokenAuthorizationEngine`. :param allow_access_levels: The value of this argument is ignored, for the same reason as consumer_name. """ # It doesn't look like we're doing anything here, but we # are discarding the passed-in values for consumer_name and # allow_access_levels. super(AuthorizeRequestTokenWithBrowser, self).__init__( service_root, application_name, None, credential_save_failed) def notify_end_user_authorization_url(self, authorization_url): """Notify the end-user of the URL.""" super(AuthorizeRequestTokenWithBrowser, self).notify_end_user_authorization_url(authorization_url) try: browser_obj = webbrowser.get() browser = getattr(browser_obj, "basename", None) console_browser = browser in self.TERMINAL_BROWSERS except webbrowser.Error: browser_obj = None console_browser = False if console_browser: self.output(self.TIMEOUT_MESSAGE % self.TIMEOUT) # Wait a little time before attempting to launch browser, # give users the chance to press a key to skip it anyway. rlist, _, _ = select([stdin], [], [], self.TIMEOUT) if rlist: stdin.readline() if browser_obj is not None: webbrowser.open(authorization_url) def wait_for_end_user_authorization(self, credentials): """Wait for the end-user to authorize""" self.output(self.WAITING_FOR_LAUNCHPAD) start_time = time.time() while credentials.access_token is None: time.sleep(access_token_poll_time) try: if self.check_end_user_authorization(credentials): break except EndUserNoAuthorization: pass if time.time() >= start_time + access_token_poll_timeout: raise TokenAuthorizationTimedOut( "Timed out after %d seconds." % access_token_poll_timeout) class TokenAuthorizationException(Exception): pass class RequestTokenAlreadyAuthorized(TokenAuthorizationException): pass class EndUserAuthorizationFailed(TokenAuthorizationException): """Superclass exception for all failures of end-user authorization""" pass class EndUserDeclinedAuthorization(EndUserAuthorizationFailed): """End-user declined authorization""" pass class EndUserNoAuthorization(EndUserAuthorizationFailed): """End-user did not perform any authorization""" pass class TokenAuthorizationTimedOut(EndUserNoAuthorization): """End-user did not perform any authorization in timeout period""" pass class ClientError(TokenAuthorizationException): pass class ServerError(TokenAuthorizationException): pass class NoLaunchpadAccount(TokenAuthorizationException): pass class TooManyAuthenticationFailures(TokenAuthorizationException): pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5192525 launchpadlib-1.10.13/src/launchpadlib/docs/0000755000175000017500000000000000000000000022153 5ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1574442870.0 launchpadlib-1.10.13/src/launchpadlib/docs/Makefile0000644000175000017500000000114100000000000023610 0ustar00cjwatsoncjwatson00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build SPHINXPROJ = launchpadlib SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288690.0 launchpadlib-1.10.13/src/launchpadlib/docs/NEWS.rst0000644000175000017500000002305400000000000023465 0ustar00cjwatsoncjwatson00000000000000===================== NEWS for launchpadlib ===================== 1.10.13 (2020-04-19) ==================== - Fix test runs under sudo. 1.10.12 (2020-04-17) ==================== - Postpone keyring.errors import in the same way that we postpone importing keyring itself. 1.10.11 (2020-04-14) ==================== - Don't store credentials or open a browser window when running under sudo. [bug=1825014,1862948] - Fall back to in-memory credentials store if no keyring backend is available. [bug=1864204] 1.10.10 (2020-02-04) ==================== - Fix AccessToken.from_string crash on Python 3.8. [bug=1861873] 1.10.9 (2019-11-28) =================== - Explicitly install version.txt; launchpadlib requires it. 1.10.8 (2019-11-26) =================== - Squash a deprecation warning on Python >= 3.7 in launchpadlib.testing.launchpad. - Switch from buildout to tox. - Weaken hosted-files test slightly to avoid problems with zope.publisher >= 4.2.2. 1.10.7 (2019-05-22) =================== - Change 'dev' URLs from launchpad.dev to launchpad.test. 1.10.6 (2018-03-08) =================== - Fix saving of credentials in python3 with gnome-keyring. [bug=1685962] 1.10.5 (2017-02-02) =================== - Fix AccessToken.from_string crash on Python 3. [bug=1471927] - Fix fallback if authorizing a token with a browser raises webbrowser.Error. - Stop introduction.txt doctest from writing to $HOME. 1.10.4 (2016-07-12) =================== - Fix _bad_oauth_token crash on Python 3. [bug=1471894] - Time out make_end_user_authorize_token after 15 minutes. - Ignore PendingDeprecationWarning from lazr.restfulclient. [bug=1473577] - Ask forgiveness rather than permission when creating cache directories. - Fix browser token authorization on OS X. [bug=1516080] 1.10.3 (2014-12-05) =================== - Port to Python3. - Detect proxies from the environment by default. 1.10.2 (2012-07-05) =================== - Typo in the doctest fix, discovered when trying to integrate with launchpad itself. [bug=1020667] 1.10.1 (2012-07-04) =================== - Fix a doctest in introduction.txt so that the test suite runs with python-2.7 (note the doctests only run when running integrated with launchpad's test suite itself). [bug=1020667] 1.10.0 (2012-06-19) =================== - Add environment variable, LP_DISABLE_SSL_CERTIFICATE_VALIDATION, to disable SSL certificate checks. Most useful when testing against development servers. 1.9.12 (2011-12-05) =================== - Move keyring base64 encoding to KeyringCredential and be more defensive about decoding. [bug=900307] 1.9.11 (2011-11-21) =================== - 1.9.10 was a bad release due to incomplete NEWS entries. - Add fake Launchpad web service for unit test. - Improve HACKING documentation. - Improve launchpadlib directory discovery on Windows. - Added script to delete spurious bugtasks or split a bugtask from a bug. - Properly handle Unicode passwords if returned by the keyring. - Base 64 encode serialized credentials before putting in keyring/wallet. 1.9.10 (2011-11-21) =================== - Base 64 encode serialized credentials before putting in keyring/wallet. 1.9.9 (2011-07-27) ================== - Fix a failing test for lazr.restfulclient 0.12.0. 1.9.8 (2011-02-28) ================== - Detect the error Launchpad sends when it doesn't recognize an access token, and get a new token. 1.9.7 (2011-02-15) ================== - Slightly tweaked the behavior of EDGE_SERVICE_ROOT, and improved tests. 1.9.6 (2011-02-14) ================== - Added EDGE_SERVICE_ROOT and the 'edge' alias back, though they both operate on production behind the scenes. Using the 'edge' alias will cause a deprecation warning. 1.9.5 (2011-02-08) ================== - Fixed a bug that prevented the deprecated get_token_and_login code from working, and that required that users of get_token_and_login get a new token on every usage. 1.9.4 (2011-01-18) ================== - Removed references to the 'edge' service root, which is being phased out. - Fixed a minor bug in the upload_release_tarball contrib script which was causing tarballs to be uploaded with the wrong media type. - The XSLT stylesheet for converting the Launchpad WADL into HTML documentation has been moved back into Launchpad. 1.9.3 (2011-01-10) ================== - The keyring package import is now delayed until the keyring needs to be accessed. This reduces launchapdlib users' exposure to unintended side effects of importing keyring (KWallet authorization dialogs and the registration of a SIGCHLD handler). 1.9.2 (2011-01-07) ================== - Added a missing import. 1.9.1 (2011-01-06) ================== - Corrected a test failure. 1.9.0 (2011-01-05) ================== - When an authorization token expires or becomes invalid, attempt to acquire a new one, even in the middle of a session, rather than crashing. - The HTML generated by wadl-to-refhtml.xsl now validates. - Most of the helper login methods have been deprecated. There are now only two helper methods: * Launchpad.login_anonymously, for anonymous credential-free access. * Launchpad.login_with, for programs that need a credential. 1.8.0 (2010-11-15) ================== - Store authorization tokens in the Gnome keyring or KDE wallet, when available. The credentials_file parameter of Launchpad.login_with() is now ignored. - By default, Launchpad.login_with() now asks Launchpad for desktop-wide integration. This removes the need for each individual application to get its own OAuth token. 1.7.0 (2010-09-23) ================== - Removed "fake Launchpad browser" code that didn't work and was misleading developers. - Added support for http://qastaging.launchpad.net by adding astaging to the uris. 1.6.5 (2010-08-23) ================== - Make launchpadlib compatible with the latest lazr.restfulclient. 1.6.4 (2010-08-18) ================== - Test fixes. 1.6.3 (2010-08-12) ================== - Instead of making the end-user hit Enter after authorizing an application to access their Launchpad account, launchpadlib will automatically poll Launchpad until the user makes a decision. - launchpadlib now raises a more helpful exception when the end-user explicitly denies access to a launchpadlib application. - Improved the XSLT stylesheet to reflect Launchpad's more complex top-level structure. [bug=286941] - Test fixes. [bug=488448,616055] 1.6.2 (2010-06-21) ================== - Extended the optimization from version 1.6.1 to apply to Launchpad's top-level collection of people. 1.6.1 (2010-06-16) ================== - Added an optimization that lets launchpadlib avoid making an HTTP request in some situations. 1.6.0 (2010-04-07) ================== - Fixed a test to work against the latest version of Launchpad. 1.5.8 (2010-03-25) ================== - Use version 1.0 of the Launchpad web service by default. 1.5.7 (2010-03-16) ================== - Send a Referer header whenever making requests to the Launchpad website (as opposed to the web service) to avoid falling afoul of new cross-site-request-forgery countermeasures. 1.5.6 (2010-03-04) ================== - Fixed a minor bug when using login_with() to access a version of the Launchpad web service other than the default. - Added a check to catch old client code that would cause newer versions of launchpadlib to make nonsensical requests to https://api.launchpad.dev/beta/beta/, and raise a helpful exception telling the developer how to fix it. 1.5.5 ===== - Added the ability to access different versions of the Launchpad web service. 1.5.4 (2009-12-17) ================== - Made it easy to get anonymous access to a Launchpad instance. - Made it easy to plug in different clients that take the user's Launchpad login and password for purposes of authorizing a request token. The most secure technique is still the default: to open the user's web browser to the appropriate Launchpad page. - Introduced a command-line script bin/launchpad-credentials-console, which takes the user's Launchpad login and password, and authorizes a request token on their behalf. - Introduced a command-line script bin/launchpad-request-token, which creates a request token on any Launchpad installation and dumps the JSON description of that token to standard output. - Shorthand service names like 'edge' should now be respected everywhere in launchpadlib. 1.5.3 (2009-10-22) ================== - Moved some more code from launchpadlib into the more generic lazr.restfulclient. 1.5.2 (2009-10-01) ================== - Added a number of new sample scripts from elsewhere. - Added a reference to the production Launchpad instance. - Made it easier to specify a Launchpad instance to run against. 1.5.1 (2009-07-16) ================== - Added a sample script for uploading a release tarball to Launchpad. 1.5.0 (2009-07-09) ================== - Most of launchpadlib's code has been moved to the generic lazr.restfulclient library. launchpadlib now contains only code specific to Launchpad. There should be no changes in functionality. - Moved bootstrap.py into the top-level directory. Having it in a subdirectory with a top-level symlink was breaking installation on Windows. - The notice to the end-user (that we're opening their web browser) is now better formatted. 1.0.1 (2009-05-30) ================== - Correct tests for new launchpad cache behavior in librarian - Remove build dependency on setuptools_bzr because it was causing bzr to be downloaded during installation of the package, which was unnecessary and annoying. 1.0 (2009-03-24) ================ - Initial release on PyPI ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1558535650.0 launchpadlib-1.10.13/src/launchpadlib/docs/command-line.rst0000644000175000017500000000224200000000000025250 0ustar00cjwatsoncjwatson00000000000000******************** Command-line scripts ******************** Launchpad includes one command-line script to make Launchpad integration easier for third-party libraries that aren't written in Python. This file tests the workflow underlying the command-line script as best it can. RequestTokenApp =============== This class is called by the command-line script launchpad-request-token. It creates a request token on a given Launchpad installation, and returns a JSON description of the request token and the available access levels. >>> try: ... import json ... except ImportError: ... import simplejson as json >>> from launchpadlib.apps import RequestTokenApp >>> web_root = "http://launchpad.test:8085/" >>> consumer_name = "consumer" >>> token_app = RequestTokenApp(web_root, consumer_name, "context") >>> token_json = json.loads(token_app.run()) >>> for param in sorted(token_json.keys()): ... print(param) access_levels lp.context oauth_token oauth_token_consumer oauth_token_secret >>> print token_json['lp.context'] context >>> print token_json['oauth_token_consumer'] consumer ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1574442870.0 launchpadlib-1.10.13/src/launchpadlib/docs/conf.py0000644000175000017500000001231100000000000023450 0ustar00cjwatsoncjwatson00000000000000# -*- coding: utf-8 -*- # # launchpadlib documentation build configuration file, created by # sphinx-quickstart on Tue Nov 5 23:48:15 2019. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. with open('../version.txt') as version_file: _version = version_file.read().strip() # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. project = u'launchpadlib' copyright = u'2008-2019, Canonical Ltd.' author = u'LAZR Developers ' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = _version # The full version, including alpha/beta/rc tags. release = _version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'alabaster' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. # # This is required for the alabaster theme # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars html_sidebars = { '**': [ 'relations.html', # needs 'show_related': True theme option to display 'searchbox.html', ] } # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. htmlhelp_basename = 'launchpadlibdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'launchpadlib.tex', u'launchpadlib Documentation', u'LAZR Developers \\textless{}lazr-developers@lists.launchpad.net\\textgreater{}', 'manual'), ] # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'launchpadlib', u'launchpadlib Documentation', [author], 1) ] # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'launchpadlib', u'launchpadlib Documentation', author, 'launchpadlib', 'One line description of project.', 'Miscellaneous'), ] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5192525 launchpadlib-1.10.13/src/launchpadlib/docs/files/0000755000175000017500000000000000000000000023255 5ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/src/launchpadlib/docs/files/mugshot.png0000644000175000017500000000432400000000000025454 0ustar00cjwatsoncjwatson00000000000000‰PNG  IHDRÀÀݾûPsRGB®Îé pHYs  šœtIMEØ ;æÉœtEXtCommentCreated with GIMPWAIDATxÚíÜ]HSmÀñ3?pËe[.‘™í`)")§’é>ÂaA7 Þ9*S éCHA˜HdD”}@B7•Q4ð˜u¡žYŠJæ°QjÐދýe:ç«çÃÿï*Úˆçü÷ì<ÏÙ²D"ˆUC€@@€@@ €€@@ @@  €€@@€@@ @@  ¦—ÀK(RE–å`0(‚Çã‘$IE‡ÃA@XºžÎÎή®.Y–EAEI’JJJ¼^¯& Áê¹råŠ,Ë?ÿRù— š4” çñÒÕ\­9EQÔ¹çχdYîêê’$I’$Òé\­9Y–¬ç×G H¿sµæ‚Á zø›ŸÔ©šeüÒsõ"ãŠj®^‡§Êãñˆ¢ø·GEQôx<¤ß¹Zs‹_#kr-°m ¢(–””,X‰º¼Xd~Z_Ñê\ý·IH«¹Zs‡Ãëõ ‚ÀFbTsõßÒj®ÖOC’$q+cé¹ZÝEÔÏ\­Ÿ†tõН««ÓÛY­Võ-e±XfggC¡ZÕþýûËËË×íF¢>Y"‘ˆ>_·2æÇ2€€@@€@@ €€@@ @@ €€@@ €€@@ @@  „†ÀXB¡¢(²,ƒAA<$I¢(:2üh®öÁ ´µµõööއB!A¶mÛ¶{÷î’’¯×«ÉQ'z@;;;»ººdYVEQ%IÒp4Wõ`ÛÛÛ[ZZÞ¾};??ÿóïGFFFFFÔÃ׿¨#Æ4==ÝÚÚ*IÒŸG”žž^]]===1 õ`srr9^¯·¯¯oí_›Q/¢EQçž?¿xñbSS“:É›€¢(CCC‹===ú·J^^ž­©©‰¦‹ÅRZZªÕ¶…QRª®®^Ötëv»¯_¿®ÿ-¢?žŸ>¹ÌÚPOOOVVVôŸeêžJnnîÝ»wWãÊ4www»\®˜ë±ÛíµµµzÛ}0g@jC7oÞܾ}ûrÏSFFFccãÿ{žÂáðùóç—µÁóÛ…šËåjoo×áþ§iR¯Uý~47ícµZ?ÞßßÿÕÓÜÜœ’’C:‰‰‰‡£¡¡!ès-‘HÄÄ_ R¿‹~éÒ¥‘‘‘å©Õjݱc‡ÛíÎÊÊÊÏÏß»wo ¿÷˜ŸŸ¿qãFUUU8^îm»´´´êêꢢ¢ÞkÆä© Ý»w¯¾¾~%ßø´Ùl›7ov:™™™333N§szz:555'%%ÍÍÍ ‚ þÁn·OMM©Op:>|úöíÛ²¾5°oß¾²²2QõœŽ±¿ÃgYvv¶ÎÏ…Ýn7ÜïIâëêê³³Z­ÙÙÙ[¶lùñãÇäääìì¬_drrree¥Ïç3Ö/ÚÌÿöëg™¢(OŸ>íèèèííýþý»~^[JJÊéÓ§=j¼ïÿGÖuYà •·µµ­ýý8–ñ+jèÉ“'»víŠò[«$..îСC­gý¤êïﯨ¨ˆyoåÊËËÇÇÇ =†ë: uöðáõ¯§¨¨hµo½ÐnllLKK[›tòóó_¾|i‚¡# ÿdä÷ûsssWqÑk±Øl¶Ã‡›£óßʈyµÿâÅ‹@ Ðßß?66633óõë×þ³‰‰‰6l$©¢¢¢¸¸Øè?×_û@1ÇÞ¼y355õéÓ'«ÕúóNÅ’·2RSSggg].WjjjAAAaa¡ùþ÷4ÂÊv"€€@@€@@ @@  ‚Ñý}ŒðÖ‚°*LIEND®B`‚././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1574787433.0 launchpadlib-1.10.13/src/launchpadlib/docs/hosted-files.rst0000644000175000017500000000555700000000000025307 0ustar00cjwatsoncjwatson00000000000000************ Hosted files ************ The Launchpad web service sets restrictions on what kinds of documents can be written to a particular file. This test shows what happens when you try to upload a non-image for a field that expects an image. >>> from launchpadlib.testing.helpers import salgado_with_full_permissions >>> launchpad = salgado_with_full_permissions.login() >>> from launchpadlib.errors import HTTPError >>> mugshot = launchpad.me.mugshot >>> file_handle = mugshot.open("w", "image/png", "nonimage.txt") >>> file_handle.content_type 'image/png' >>> file_handle.filename 'nonimage.txt' >>> file_handle.write("Not an image.") >>> try: ... file_handle.close() ... except HTTPError, e: ... print e.content The file uploaded was not recognized as an image; please check it and retry. Of course, uploading an image works fine. >>> import os >>> def load_image(filename): ... image_file = os.path.join( ... os.path.dirname(__file__), 'files', filename) ... return open(image_file).read() >>> image = load_image("mugshot.png") >>> len(image) 2260 >>> file_handle = mugshot.open("w", "image/png", "a-mugshot.png") >>> file_handle.write(image) >>> file_handle.close() == Error handling == The server may set restrictions on what kinds of documents can be written to a particular file. >>> file_handle = mugshot.open("w", "image/png", "nonimage.txt") >>> file_handle.content_type 'image/png' >>> file_handle.filename 'nonimage.txt' >>> file_handle.write("Not an image.") >>> file_handle.close() Traceback (most recent call last): ... BadRequest: HTTP Error 400: Bad Request ... == Caching == Hosted file resources implement the normal server-side caching mechanism. >>> file_handle = mugshot.open("w", "image/png", "image.png") >>> file_handle.write(image) >>> file_handle.close() >>> import httplib2 >>> httplib2.debuglevel = 1 >>> launchpad = salgado_with_full_permissions.login() connect: ... >>> mugshot = launchpad.me.mugshot send: ... The first request for a file retrieves the file from the server. >>> len(mugshot.open().read()) send: ... reply: 'HTTP/1.1 303 See Other... reply: 'HTTP/1.1 200 OK... 2260 The second request retrieves the file from the cache. After receiving the 303 request with its Location header, no further HTTP requests are issued because the Librarian's Cache-Control: headers tell us we already have a fresh copy. >>> len(mugshot.open().read()) send: ... reply: 'HTTP/1.1 303 See Other... header: Location: http://.../image.png ... 2260 Finally, some cleanup code that deletes the mugshot. >>> mugshot.delete() send: 'DELETE... reply: 'HTTP/1.1 200... >>> httplib2.debuglevel = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1574442870.0 launchpadlib-1.10.13/src/launchpadlib/docs/index.rst0000644000175000017500000000160400000000000024015 0ustar00cjwatsoncjwatson00000000000000.. This file is part of launchpadlib. launchpadlib is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. launchpadlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with launchpadlib. If not, see . launchpadlib ************ See https://help.launchpad.net/API/launchpadlib . .. pypi description ends here .. toctree:: :glob: introduction operations toplevel people hosted-files command-line NEWS ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1558535650.0 launchpadlib-1.10.13/src/launchpadlib/docs/introduction.rst0000644000175000017500000003236600000000000025440 0ustar00cjwatsoncjwatson00000000000000************ launchpadlib ************ launchpadlib is the standalone Python language bindings to Launchpad's web services API. It is officially supported by Canonical, although third party packages may be available to provide bindings to other programming languages. Set up ====== launchpadlib writes to $HOME, so isolate ourselves. >>> from fixtures import ( ... EnvironmentVariable, ... TempDir, ... ) >>> tempdir_fixture = TempDir() >>> tempdir_fixture.setUp() >>> home_fixture = EnvironmentVariable('HOME', tempdir_fixture.path) >>> home_fixture.setUp() OAuth authentication ==================== The Launchpad API requires user authentication via OAuth, and launchpadlib provides a high level interface to OAuth for the most common use cases. Several pieces of information are necessary to complete the OAuth request: * A consumer key, which is unique to the application using the API * An access token, which represents the user to the web service * An access token secret, essentially a password for the token Consumer keys are hard-baked into the application. They are generated by the application developer and registered with Launchpad independently of the use of the application. Since consumer keys are arbitrary, a registered consumer key can be paired with a secret, but most open source applications will forgo this since it's not really a secret anyway. The access token cannot be provided directly. Instead, the application generates an unauthenticated request token, exchanging this for an access token and a secret after obtaining approval to do so from the user. This permission is typically gained by redirecting the user through their trusted web browser, then back to the application. This entire exchange is managed by launchpadlib's credentials classes. Credentials can be stored in a file, though the security of this depends on the implementation of the file object. In the simplest case, the application will request a new access token every time. >>> from launchpadlib.credentials import Consumer >>> consumer = Consumer('launchpad-library') >>> consumer.key 'launchpad-library' >>> consumer.secret '' Salgado has full access to the Launchpad API. Out of band, the application itself obtains Salgado's approval to access the Launchpad API on his behalf. How the application does this is up to the application, provided it conforms to the OAuth protocol. Once this happens, we have Salgado's credentials for accessing Launchpad. >>> from launchpadlib.credentials import AccessToken >>> access_token = AccessToken('salgado-change-anything', 'test') And now these credentials are used to access the root service on Salgado's behalf. >>> from launchpadlib.credentials import Credentials >>> credentials = Credentials( ... consumer_name=consumer.key, consumer_secret=consumer.secret, ... access_token=access_token) >>> from launchpadlib.testing.helpers import ( ... TestableLaunchpad as Launchpad) >>> launchpad = Launchpad(credentials=credentials) >>> sorted(launchpad.people) [...] >>> sorted(launchpad.bugs) [...] If available, the Gnome keyring or KDE wallet will be used to store access tokens. If a keyring/wallet is not available, the application can store the credentials on the file system, so that the next time Salgado interacts with the application, he won't have to go through the whole OAuth request dance. >>> import os >>> import tempfile >>> fd, path = tempfile.mkstemp('.credentials') >>> os.close(fd) Once Salgado's credentials are obtained for the first time, just set the appropriate instance variables and use the save() method. >>> credentials.consumer = consumer >>> credentials.access_token = access_token >>> credentials_file = open(path, 'w') >>> credentials.save(credentials_file) >>> credentials_file.close() And the credentials are perfectly valid for accessing Launchpad. >>> launchpad = Launchpad(credentials=credentials) >>> sorted(launchpad.people) [...] >>> sorted(launchpad.bugs) [...] The credentials can also be retrieved from the file, so that the OAuth request dance can be avoided. >>> credentials = Credentials() >>> credentials_file = open(path) >>> credentials.load(credentials_file) >>> credentials_file.close() >>> credentials.consumer.key 'launchpad-library' >>> credentials.consumer.secret '' >>> credentials.access_token.key 'salgado-change-anything' >>> credentials.access_token.secret 'test' These credentials too, are perfectly usable to access Launchpad. >>> launchpad = Launchpad(credentials=credentials) >>> sorted(launchpad.people) [...] >>> sorted(launchpad.bugs) [...] The security of the stored credentials is left up to the file-like object. Here, the application decides to use a dubious encryption algorithm to hide Salgado's credentials. >>> from StringIO import StringIO >>> from codecs import EncodedFile >>> encrypted_file = StringIO() >>> stream = EncodedFile(encrypted_file, 'rot_13', 'ascii') >>> credentials.save(stream) >>> stream.seek(0, 0) >>> print ''.join(sorted(encrypted_file)) [1] npprff_frperg = grfg npprff_gbxra = fnytnqb-punatr-nalguvat pbafhzre_frperg = pbafhzre_xrl = ynhapucnq-yvoenel >>> stream.seek(0) >>> credentials = Credentials() >>> credentials.load(stream) >>> credentials.consumer.key 'launchpad-library' >>> credentials.consumer.secret '' >>> credentials.access_token.key 'salgado-change-anything' >>> credentials.access_token.secret 'test' Anonymous access ================ An anonymous access token doesn't authenticate any particular user. Using it will give a client read-only access to the public parts of the Launchpad dataset. >>> from launchpadlib.credentials import AnonymousAccessToken >>> anonymous_token = AnonymousAccessToken() >>> from launchpadlib.credentials import Credentials >>> credentials = Credentials( ... consumer_name="a consumer", access_token=anonymous_token) >>> launchpad = Launchpad(credentials=credentials) >>> salgado = launchpad.people['salgado'] >>> print salgado.display_name Guilherme Salgado An anonymous client can't modify the dataset, or read any data that's permission-controlled or scoped to a particular user. >>> launchpad.me Traceback (most recent call last): ... Unauthorized: HTTP Error 401: Unauthorized ... >>> salgado.display_name = "This won't work." >>> salgado.lp_save() Traceback (most recent call last): ... Unauthorized: HTTP Error 401: Unauthorized ... Convenience =========== When you want anonymous access, a convenience method is available for setting up a web service connection in one function call. All you have to provide is the consumer name. >>> launchpad = Launchpad.login_anonymously( ... 'launchpad-library', service_root="test_dev") >>> sorted(launchpad.people) [...] >>> launchpad.me Traceback (most recent call last): ... Unauthorized: HTTP Error 401: Unauthorized ... Otherwise, the application should obtain authorization from the user and get a new set of credentials directly from Launchpad. Unfortunately, we can't test this entire process because it requires opening up a web browser, but we can test the first step, which is to get a request token. >>> import launchpadlib.credentials >>> credentials = Credentials('consumer') >>> authorization_url = credentials.get_request_token( ... context='firefox', web_root='test_dev') >>> print(authorization_url) http://launchpad.test:8085/+authorize-token?oauth_token=...&lp.context=firefox We use 'test_dev' as a shorthand for the root URL of the Launchpad installation. It's defined in the 'uris' module as 'http://launchpad.test:8085/', and the launchpadlib code knows how to dereference it before using it as a URL. Information about the request token is kept in the _request_token attribute of the Credentials object. >>> credentials._request_token.key is not None True >>> credentials._request_token.secret is not None True >>> print credentials._request_token.context firefox Now the user must authorize that token, and this is the part we can't test--it requires opening a web browser. Once the token is authorized on the server side, we can call exchange_request_token_for_access_token() on our Credentials object, which will then be ready to use. The dictionary request token ============================ By default, get_request_token returns the URL that the user needs to use when granting access to the token. But you can specify a different token_format and get a dictionary instead. >>> credentials = Credentials('consumer') >>> dictionary = credentials.get_request_token( ... context='firefox', web_root='test_dev', ... token_format=Credentials.DICT_TOKEN_FORMAT) The dictionary has useful information about the token and about the levels of authentication Launchpad offers. >>> for param in sorted(dictionary.keys()): ... print(param) access_levels lp.context oauth_token oauth_token_consumer oauth_token_secret The _request_token attribute of the Credentials object has the same fields set as if you had asked for the default URI token format. >>> credentials._request_token.key is not None True >>> credentials._request_token.secret is not None True >>> print credentials._request_token.context firefox Credentials file errors ======================= If the credentials file is empty, loading it raises an exception. >>> credentials = Credentials() >>> credentials.load(StringIO()) Traceback (most recent call last): ... CredentialsFileError: No configuration for version 1 It is an error to save a credentials file when no consumer or access token is available. >>> credentials.consumer = None >>> credentials.save(StringIO()) Traceback (most recent call last): ... CredentialsFileError: No consumer >>> credentials.consumer = consumer >>> credentials.access_token = None >>> credentials.save(StringIO()) Traceback (most recent call last): ... CredentialsFileError: No access token The credentials file is not intended to be edited, but because it's human readable, that's of course possible. If the credentials file gets corrupted, an error is raised. >>> credentials_file = StringIO("""\ ... [1] ... #consumer_key: aardvark ... consumer_secret: badger ... access_token: caribou ... access_secret: dingo ... """) >>> credentials.load(credentials_file) Traceback (most recent call last): ... NoOptionError: No option 'consumer_key' in section: '1' >>> credentials_file = StringIO("""\ ... [1] ... consumer_key: aardvark ... #consumer_secret: badger ... access_token: caribou ... access_secret: dingo ... """) >>> credentials.load(credentials_file) Traceback (most recent call last): ... NoOptionError: No option 'consumer_secret' in section: '1' >>> credentials_file = StringIO("""\ ... [1] ... consumer_key: aardvark ... consumer_secret: badger ... #access_token: caribou ... access_secret: dingo ... """) >>> credentials.load(credentials_file) Traceback (most recent call last): ... NoOptionError: No option 'access_token' in section: '1' >>> credentials_file = StringIO("""\ ... [1] ... consumer_key: aardvark ... consumer_secret: badger ... access_token: caribou ... #access_secret: dingo ... """) >>> credentials.load(credentials_file) Traceback (most recent call last): ... NoOptionError: No option 'access_secret' in section: '1' Bad credentials =============== The application is not allowed to access Launchpad with a bad access token. >>> access_token = AccessToken('bad', 'no-secret') >>> credentials = Credentials( ... consumer_name=consumer.key, consumer_secret=consumer.secret, ... access_token=access_token) >>> launchpad = Launchpad(credentials=credentials) Traceback (most recent call last): ... Unauthorized: HTTP Error 401: Unauthorized ... The application is not allowed to access Launchpad with a consumer name that doesn't match the credentials. >>> access_token = AccessToken('salgado-change-anything', 'test') >>> credentials = Credentials( ... consumer_name='not-the-launchpad-library', ... access_token=access_token) >>> launchpad = Launchpad(credentials=credentials) Traceback (most recent call last): ... Unauthorized: HTTP Error 401: Unauthorized ... The application is not allowed to access Launchpad with a bad access secret. >>> access_token = AccessToken('hgm2VK35vXD6rLg5pxWw', 'bad-secret') >>> credentials = Credentials( ... consumer_name=consumer.key, consumer_secret=consumer.secret, ... access_token=access_token) >>> launchpad = Launchpad(credentials=credentials) Traceback (most recent call last): ... Unauthorized: HTTP Error 401: Unauthorized ... Clean up ======== >>> os.remove(path) >>> home_fixture.cleanUp() >>> tempdir_fixture.cleanUp() ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/src/launchpadlib/docs/operations.rst0000644000175000017500000000153200000000000025071 0ustar00cjwatsoncjwatson00000000000000**************** Named operations **************** launchpadlib can transparently determine the size of the list even when the size is not directly provided, but is only available through a link. >>> from launchpadlib.testing.helpers import salgado_with_full_permissions >>> launchpad = salgado_with_full_permissions.login(version="devel") >>> results = launchpad.people.find(text='s') >>> 'total_size' in results._wadl_resource.representation.keys() False >>> 'total_size_link' in results._wadl_resource.representation.keys() True >>> len(results) > 1 True Of course, launchpadlib can also determine the size when the size _is_ directly provided. >>> results = launchpad.people.find(text='salgado') >>> 'total_size' in results._wadl_resource.representation.keys() True >>> len(results) == 1 True ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1574442870.0 launchpadlib-1.10.13/src/launchpadlib/docs/people.rst0000644000175000017500000001417300000000000024177 0ustar00cjwatsoncjwatson00000000000000**************** People and Teams **************** The Launchpad web service, like Launchpad itself, exposes a unified interface to people and teams. In other words, people and teams occupy the same namespace. You treat people and teams as the same type of object, and need to inspect the object to know whether you're dealing with a person or a team. People ====== You can access Launchpad people through the web service interface. The list of people is available from the service root. >>> from launchpadlib.testing.helpers import salgado_with_full_permissions >>> launchpad = salgado_with_full_permissions.login() >>> people = launchpad.people The list of people is not fetched until you actually use data. >>> print people._wadl_resource.representation None >>> len(people) 4 >>> print people._wadl_resource.representation {...} The 'me' attribute is also available from the service root. It's a quick way to get a reference to your own user account. >>> me = launchpad.me >>> me.name u'salgado' You can find a person by name. >>> salgado = launchpad.people['salgado'] >>> salgado.name u'salgado' >>> salgado.display_name u'Guilherme Salgado' >>> salgado.is_team False But if no person by that name is registered, you get the expected KeyError. >>> launchpad.people['not-a-registered-person'] Traceback (most recent call last): ... KeyError: 'not-a-registered-person' It's not possible to slice a single person from the top-level collection of people. launchpadlib will try to use the value you pass in as a person's name, which will almost always fail. >>> launchpad.people[1] Traceback (most recent call last): ... KeyError: 1 You can find a person by email. >>> email = salgado.preferred_email_address.email >>> salgado = launchpad.people.getByEmail(email=email) >>> salgado.name u'salgado' Besides a name and a display name, a person has many other attributes that you can read. XXX 05-Jun-2008 BarryWarsaw Some of these attributes are links to further collections and are not yet tested. Tests will be added in future branches. >>> salgado.karma 0 >>> print salgado.homepage_content None >>> #salgado.mugshot >>> #salgado.languages >>> salgado.hide_email_addresses False >>> salgado.date_created datetime.datetime(2005, 6, 6, 8, 59, 51, 596025, ...) >>> print salgado.time_zone UTC >>> salgado.is_valid True >>> #salgado.wiki_names >>> #salgado.irc_nicknames >>> #salgado.jabber_ids >>> #salgado.team_memberships >>> #salgado.open_membership_invitations >>> #salgado.teams_participated_in >>> #salgado.teams_indirectly_participated_in >>> #salgado.confirmed_email_addresses >>> #salgado.preferred_email_address >>> salgado.mailing_list_auto_subscribe_policy u'Ask me when I join a team' >>> salgado.visibility u'Public' Teams ===== You also access teams using the same interface. >>> team = launchpad.people['ubuntu-team'] >>> team.name u'ubuntu-team' >>> team.display_name u'Ubuntu Team' >>> team.is_team True Regular people have team attributes, but they're not used. >>> print salgado.team_owner None You can find out how a person has membership in a team. # XXX: salgado, 2008-08-01: Commented because method has been Unexported; # it should be re-enabled after the operation is exported again. # >>> path = salgado.findPathToTeam( # ... team=launchpad.people['mailing-list-experts']) # >>> [team.name for team in path] # [u'admins', u'mailing-list-experts'] You can create a new team through the web interface. The simplest case of this requires only the new team's name, owner and display name. >>> launchpad.people['bassists'] Traceback (most recent call last): ... KeyError: 'bassists' >>> bassists = launchpad.people.newTeam( ... name='bassists', display_name='Awesome Rock Bass Players') >>> bassists.name u'bassists' >>> bassists.display_name u'Awesome Rock Bass Players' >>> bassists.is_team True And of course, that team is now accessible directly. >>> bassists = launchpad.people['bassists'] >>> bassists.name u'bassists' >>> bassists.display_name u'Awesome Rock Bass Players' You cannot create the same team twice. >>> launchpad.people.newTeam(name='bassists', display_name='Bass Gods') Traceback (most recent call last): ... BadRequest: HTTP Error 400: Bad Request ... Actually, the exception contains other useful information. >>> from launchpadlib.errors import HTTPError >>> try: ... launchpad.people.newTeam( ... name='bassists', display_name='Bass Gods') ... except HTTPError, error: ... pass >>> error.response['status'] '400' >>> error.content 'name: bassists is already in use by another person or team.' Besides a name and a display name, a team has many other attributes that you can read. >>> bassists.karma 0 >>> print bassists.homepage_content None >>> bassists.hide_email_addresses False >>> bassists.date_created datetime.datetime(...) >>> print bassists.time_zone UTC >>> bassists.is_valid True >>> #bassists.team_memberships >>> #bassists.open_membership_invitations >>> #bassists.teams_participated_in >>> #bassists.teams_indirectly_participated_in >>> #bassists.confirmed_email_addresses >>> #bassists.team_owner >>> #bassists.preferred_email_address >>> #bassists.members >>> #bassists.admins >>> #bassists.participants >>> #bassists.deactivated_members >>> #bassists.expired_members >>> #bassists.invited_members >>> #bassists.member_memberships >>> #bassists.proposed_members >>> bassists.visibility u'Public' >>> print bassists.team_description None >>> bassists.subscription_policy u'Moderated Team' >>> bassists.renewal_policy u'invite them to apply for renewal' >>> print bassists.default_membership_period None >>> print bassists.default_renewal_period None ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1574442870.0 launchpadlib-1.10.13/src/launchpadlib/docs/toplevel.rst0000644000175000017500000000642200000000000024543 0ustar00cjwatsoncjwatson00000000000000********************* Top-level collections ********************* The launchpad web service's top-level collections provide access to Launchpad-wide objects like projects and people. >>> import httplib2 >>> httplib2.debuglevel = 1 >>> from launchpadlib.testing.helpers import salgado_with_full_permissions >>> launchpad = salgado_with_full_permissions.login() connect: ... ... It's possible to do key-based lookups on the top-level collections. The bug collection does lookups by bug ID. >>> bug = launchpad.bugs[1] send: 'GET /.../bugs/1 ...' ... To avoid triggering an HTTP request when simply looking up an object, you can use a different syntax: >>> bug = launchpad.bugs(1) The HTTP request will happen when you need information that can only be obtained from the web service. >>> print bug.id send: 'GET /.../bugs/1 ...' ... 1 Let's look at some more collections. The project collection does lookups by project name. >>> project = launchpad.projects('firefox') >>> print project.name send: 'GET /.../firefox ...' ... firefox The project group collection does lookups by project group name. >>> group = launchpad.project_groups('gnome') >>> print group.name send: 'GET /.../gnome ...' ... gnome The distribution collection does lookups by distribution name. >>> distribution = launchpad.distributions('ubuntu') >>> print distribution.name send: 'GET /.../ubuntu ...' ... ubuntu The person collection does lookups by a person's Launchpad name. >>> person = launchpad.people('salgado') >>> print person.name send: 'GET /.../~salgado ...' ... salgado >>> team = launchpad.people('rosetta-admins') >>> print team.name send: 'GET /1.0/~rosetta-admins ...' ... rosetta-admins How does launchpadlib know that 'salgado' is a person and 'rosetta-admins' is a team? >>> print person.resource_type_link http://.../1.0/#person >>> 'default_membership_period' in person.lp_attributes False >>> print team.resource_type_link http://.../1.0/#team >>> 'default_membership_period' in team.lp_attributes True The truth is that it doesn't know, not before making that HTTP request. Until an HTTP request is made, launchpadlib assumes everything in launchpad.people[] is a team (since a team has strictly more capabilities than a person). >>> person2 = launchpad.people('salgado') >>> 'default_membership_period' in person2.lp_attributes True But accessing any attribute of an object--even trying to see what kind of object 'salgado' is--will trigger the HTTP request that will determine that 'salgado' is actually a person. >>> print person2.resource_type_link send: 'GET /.../~salgado ...' ... http://.../1.0/#person >>> 'default_membership_period' in person2.lp_attributes False Accessing an attribute of an object that might be a team will trigger the HTTP request, and then cause an error if the object turns out not to be a team. >>> person3 = launchpad.people('salgado') >>> person3.default_membership_period Traceback (most recent call last): AttributeError: ...api.launchpad.../~salgado object has no attribute 'default_membership_period' Cleanup. >>> httplib2.debuglevel = None ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/src/launchpadlib/errors.py0000644000175000017500000000142100000000000023107 0ustar00cjwatsoncjwatson00000000000000# Copyright 2008 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . """Reimport errors from restfulclient for convenience's sake.""" from lazr.restfulclient.errors import * ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288295.0 launchpadlib-1.10.13/src/launchpadlib/launchpad.py0000644000175000017500000006731300000000000023546 0ustar00cjwatsoncjwatson00000000000000# Copyright 2008-2009 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . """Root Launchpad API class.""" __metaclass__ = type __all__ = [ 'Launchpad', ] import errno import os try: from urllib.parse import urlsplit except: from urlparse import urlsplit import warnings try: from httplib2 import proxy_info_from_environment except ImportError: from httplib2 import ProxyInfo proxy_info_from_environment = ProxyInfo.from_environment from lazr.restfulclient.resource import ( CollectionWithKeyBasedLookup, HostedFile, # Re-import for client convenience ScalarValue, # Re-import for client convenience ServiceRoot, ) from lazr.restfulclient.authorize.oauth import SystemWideConsumer from lazr.restfulclient._browser import RestfulHttp from launchpadlib.credentials import ( AccessToken, AnonymousAccessToken, AuthorizeRequestTokenWithBrowser, AuthorizeRequestTokenWithURL, Consumer, Credentials, MemoryCredentialStore, KeyringCredentialStore, UnencryptedFileCredentialStore, ) from launchpadlib import uris # Import old constants for backwards compatibility from launchpadlib.uris import STAGING_SERVICE_ROOT, EDGE_SERVICE_ROOT OAUTH_REALM = 'https://api.launchpad.net' class PersonSet(CollectionWithKeyBasedLookup): """A custom subclass capable of person lookup by username.""" def _get_url_from_id(self, key): """Transform a username into the URL to a person resource.""" return str(self._root._root_uri.ensureSlash()) + '~' + str(key) # The only way to determine whether a string corresponds to a # person or a team object is to ask the server, so looking up an # entry from the PersonSet always requires making an HTTP request. collection_of = 'team' class BugSet(CollectionWithKeyBasedLookup): """A custom subclass capable of bug lookup by bug ID.""" def _get_url_from_id(self, key): """Transform a bug ID into the URL to a bug resource.""" return str(self._root._root_uri.ensureSlash()) + 'bugs/' + str(key) collection_of = 'bug' class PillarSet(CollectionWithKeyBasedLookup): """A custom subclass capable of lookup by pillar name. Projects, project groups, and distributions are all pillars. """ def _get_url_from_id(self, key): """Transform a project name into the URL to a project resource.""" return str(self._root._root_uri.ensureSlash()) + str(key) # The subclasses for projects, project groups, and distributions # all define this property differently. collection_of = None class ProjectSet(PillarSet): """A custom subclass for accessing the collection of projects.""" collection_of = 'project' class ProjectGroupSet(PillarSet): """A custom subclass for accessing the collection of project groups.""" collection_of = 'project_group' class DistributionSet(PillarSet): """A custom subclass for accessing the collection of project groups.""" collection_of = 'distribution' class LaunchpadOAuthAwareHttp(RestfulHttp): """Detects expired/invalid OAuth tokens and tries to get a new token.""" def __init__(self, launchpad, authorization_engine, *args): self.launchpad = launchpad self.authorization_engine = authorization_engine super(LaunchpadOAuthAwareHttp, self).__init__(*args) def _bad_oauth_token(self, response, content): """Helper method to detect an error caused by a bad OAuth token.""" return (response.status == 401 and (content.startswith(b"Expired token") or content.startswith(b"Invalid token") or content.startswith(b"Unknown access token"))) def _request(self, *args): response, content = super( LaunchpadOAuthAwareHttp, self)._request(*args) return self.retry_on_bad_token(response, content, *args) def retry_on_bad_token(self, response, content, *args): """If the response indicates a bad token, get a new token and retry. Otherwise, just return the response. """ if (self._bad_oauth_token(response, content) and self.authorization_engine is not None): # This access token is bad. Scrap it and create a new one. self.launchpad.credentials.access_token = None self.authorization_engine( self.launchpad.credentials, self.launchpad.credential_store) # Retry the request with the new credentials. return self._request(*args) return response, content class Launchpad(ServiceRoot): """Root Launchpad API class. :ivar credentials: The credentials instance used to access Launchpad. :type credentials: `Credentials` """ DEFAULT_VERSION = '1.0' RESOURCE_TYPE_CLASSES = { 'bugs': BugSet, 'distributions': DistributionSet, 'people': PersonSet, 'project_groups': ProjectGroupSet, 'projects': ProjectSet, } RESOURCE_TYPE_CLASSES.update(ServiceRoot.RESOURCE_TYPE_CLASSES) def __init__(self, credentials, authorization_engine, credential_store, service_root=uris.STAGING_SERVICE_ROOT, cache=None, timeout=None, proxy_info=proxy_info_from_environment, version=DEFAULT_VERSION): """Root access to the Launchpad API. :param credentials: The credentials used to access Launchpad. :type credentials: `Credentials` :param authorization_engine: The object used to get end-user input for authorizing OAuth request tokens. Used when an OAuth access token expires or becomes invalid during a session, or is discovered to be invalid once launchpadlib starts up. :type authorization_engine: `RequestTokenAuthorizationEngine` :param service_root: The URL to the root of the web service. :type service_root: string """ service_root = uris.lookup_service_root(service_root) if (service_root.endswith(version) or service_root.endswith(version + '/')): error = ("It looks like you're using a service root that " "incorporates the name of the web service version " '("%s"). Please use one of the constants from ' "launchpadlib.uris instead, or at least remove " "the version name from the root URI." % version) raise ValueError(error) self.credential_store = credential_store # We already have an access token, but it might expire or # become invalid during use. Store the authorization engine in # case we need to authorize a new token during use. self.authorization_engine = authorization_engine super(Launchpad, self).__init__( credentials, service_root, cache, timeout, proxy_info, version) def httpFactory(self, credentials, cache, timeout, proxy_info): return LaunchpadOAuthAwareHttp( self, self.authorization_engine, credentials, cache, timeout, proxy_info) @classmethod def _is_sudo(cls): return (set(['SUDO_USER', 'SUDO_UID', 'SUDO_GID']) & set(os.environ.keys())) @classmethod def authorization_engine_factory(cls, *args): if cls._is_sudo(): # Do not try to open browser window under sudo; # we probably don't have access to the X session, # and some browsers (e.g. chromium) won't run as root # LP: #1825014 return AuthorizeRequestTokenWithURL(*args) return AuthorizeRequestTokenWithBrowser(*args) @classmethod def credential_store_factory(cls, credential_save_failed): if cls._is_sudo(): # Do not try to store credentials under sudo; # it can be problematic with shared sudo access, # and we may not have access to the normal keyring provider # LP: #1862948 return MemoryCredentialStore(credential_save_failed) return KeyringCredentialStore(credential_save_failed, fallback=True) @classmethod def login(cls, consumer_name, token_string, access_secret, service_root=uris.STAGING_SERVICE_ROOT, cache=None, timeout=None, proxy_info=proxy_info_from_environment, authorization_engine=None, allow_access_levels=None, max_failed_attempts=None, credential_store=None, credential_save_failed=None, version=DEFAULT_VERSION): """Convenience method for setting up access credentials. When all three pieces of credential information (the consumer name, the access token and the access secret) are available, this method can be used to quickly log into the service root. This method is deprecated as of launchpadlib version 1.9.0. You should use Launchpad.login_anonymously() for anonymous access, and Launchpad.login_with() for all other purposes. :param consumer_name: the application name. :type consumer_name: string :param token_string: the access token, as appropriate for the `AccessToken` constructor :type token_string: string :param access_secret: the access token's secret, as appropriate for the `AccessToken` constructor :type access_secret: string :param service_root: The URL to the root of the web service. :type service_root: string :param authorization_engine: See `Launchpad.__init__`. If you don't provide an authorization engine, a default engine will be constructed using your values for `service_root` and `credential_save_failed`. :param allow_access_levels: This argument is ignored, and only present to preserve backwards compatibility. :param max_failed_attempts: This argument is ignored, and only present to preserve backwards compatibility. :return: The web service root :rtype: `Launchpad` """ cls._warn_of_deprecated_login_method("login") access_token = AccessToken(token_string, access_secret) credentials = Credentials( consumer_name=consumer_name, access_token=access_token) if authorization_engine is None: authorization_engine = cls.authorization_engine_factory( service_root, consumer_name, allow_access_levels) if credential_store is None: credential_store = cls.credential_store_factory( credential_save_failed) return cls(credentials, authorization_engine, credential_store, service_root, cache, timeout, proxy_info, version) @classmethod def get_token_and_login(cls, consumer_name, service_root=uris.STAGING_SERVICE_ROOT, cache=None, timeout=None, proxy_info=proxy_info_from_environment, authorization_engine=None, allow_access_levels=[], max_failed_attempts=None, credential_store=None, credential_save_failed=None, version=DEFAULT_VERSION): """Get credentials from Launchpad and log into the service root. This method is deprecated as of launchpadlib version 1.9.0. You should use Launchpad.login_anonymously() for anonymous access and Launchpad.login_with() for all other purposes. :param consumer_name: Either a consumer name, as appropriate for the `Consumer` constructor, or a premade Consumer object. :type consumer_name: string :param service_root: The URL to the root of the web service. :type service_root: string :param authorization_engine: See `Launchpad.__init__`. If you don't provide an authorization engine, a default engine will be constructed using your values for `service_root` and `credential_save_failed`. :param allow_access_levels: This argument is ignored, and only present to preserve backwards compatibility. :return: The web service root :rtype: `Launchpad` """ cls._warn_of_deprecated_login_method("get_token_and_login") return cls._authorize_token_and_login( consumer_name, service_root, cache, timeout, proxy_info, authorization_engine, allow_access_levels, credential_store, credential_save_failed, version) @classmethod def _authorize_token_and_login( cls, consumer_name, service_root, cache, timeout, proxy_info, authorization_engine, allow_access_levels, credential_store, credential_save_failed, version): """Authorize a request token. Log in with the resulting access token. This is the private, non-deprecated implementation of the deprecated method get_token_and_login(). Once get_token_and_login() is removed, this code can be streamlined and moved into its other call site, login_with(). """ if isinstance(consumer_name, Consumer): consumer = consumer_name else: # Create a system-wide consumer. lazr.restfulclient won't # do this automatically, but launchpadlib's default is to # do a desktop-wide integration. consumer = SystemWideConsumer(consumer_name) # Create the credentials with no Consumer, then set its .consumer # property directly. credentials = Credentials(None) credentials.consumer = consumer if authorization_engine is None: authorization_engine = cls.authorization_engine_factory( service_root, consumer_name, None, allow_access_levels) if credential_store is None: credential_store = cls.credential_store_factory( credential_save_failed) else: # A credential store was passed in, so we won't be using # any provided value for credential_save_failed. But at # least make sure we weren't given a conflicting value, # since that makes the calling code look confusing. cls._assert_login_argument_consistency( "credential_save_failed", credential_save_failed, credential_store.credential_save_failed, "credential_store") # Try to get the credentials out of the credential store. cached_credentials = credential_store.load( authorization_engine.unique_consumer_id) if cached_credentials is None: # They're not there. Acquire new credentials using the # authorization engine. credentials = authorization_engine(credentials, credential_store) else: # We acquired credentials. But, the application name # wasn't stored along with the credentials, because in a # desktop integration scenario, a single set of # credentials may be shared by many applications. We need # to set the application name for this specific instance # of the credentials. credentials = cached_credentials credentials.consumer.application_name = ( authorization_engine.application_name) return cls(credentials, authorization_engine, credential_store, service_root, cache, timeout, proxy_info, version) @classmethod def login_anonymously( cls, consumer_name, service_root=uris.STAGING_SERVICE_ROOT, launchpadlib_dir=None, timeout=None, proxy_info=proxy_info_from_environment, version=DEFAULT_VERSION): """Get access to Launchpad without providing any credentials.""" (service_root, launchpadlib_dir, cache_path, service_root_dir) = cls._get_paths(service_root, launchpadlib_dir) token = AnonymousAccessToken() credentials = Credentials(consumer_name, access_token=token) return cls(credentials, None, None, service_root=service_root, cache=cache_path, timeout=timeout, proxy_info=proxy_info, version=version) @classmethod def login_with(cls, application_name=None, service_root=uris.STAGING_SERVICE_ROOT, launchpadlib_dir=None, timeout=None, proxy_info=proxy_info_from_environment, authorization_engine=None, allow_access_levels=None, max_failed_attempts=None, credentials_file=None, version=DEFAULT_VERSION, consumer_name=None, credential_save_failed=None, credential_store=None): """Log in to Launchpad, possibly acquiring and storing credentials. Use this method to get a `Launchpad` object. If the end-user has no cached Launchpad credential, their browser will open and they'll be asked to log in and authorize a desktop integration. The authorized Launchpad credential will be stored securely: in the GNOME keyring, the KDE Wallet, or in an encrypted file on disk. The next time your program (or any other program run by that user on the same computer) invokes this method, the end-user will be prompted to unlock their keyring (or equivalent), and the credential will be retrieved from local storage and reused. You can customize this behavior in three ways: 1. Pass in a filename to `credentials_file`. The end-user's credential will be written to that file, and on subsequent runs read from that file. 2. Subclass `CredentialStore` and pass in an instance of the subclass as `credential_store`. This lets you change how the end-user's credential is stored and retrieved locally. 3. Subclass `RequestTokenAuthorizationEngine` and pass in an instance of the subclass as `authorization_engine`. This lets you change change what happens when the end-user needs to authorize the Launchpad credential. :param application_name: The application name. This is *not* the OAuth consumer name. Unless a consumer_name is also provided, the OAuth consumer will be a system-wide consumer representing the end-user's computer as a whole. :type application_name: string :param service_root: The URL to the root of the web service. :type service_root: string. Can either be the full URL to a service or one of the short service names. :param launchpadlib_dir: The directory used to store cached data obtained from Launchpad. The cache is shared by all consumers, and each Launchpad service root has its own cache. :type launchpadlib_dir: string :param authorization_engine: A strategy for getting the end-user to authorize an OAuth request token, for exchanging the request token for an access token, and for storing the access token locally so that it can be reused. By default, launchpadlib will open the end-user's web browser to have them authorize the request token. :type authorization_engine: `RequestTokenAuthorizationEngine` :param allow_access_levels: The acceptable access levels for this application. This argument is used to construct the default `authorization_engine`, so if you pass in your own `authorization_engine` any value for this argument will be ignored. This argument will also be ignored unless you also specify `consumer_name`. :type allow_access_levels: list of strings :param max_failed_attempts: Ignored; only present for backwards compatibility. :param credentials_file: The path to a file in which to store this user's OAuth access token. :param version: The version of the Launchpad web service to use. :param consumer_name: The consumer name, as appropriate for the `Consumer` constructor. You probably don't want to provide this, since providing it will prevent you from taking advantage of desktop-wide integration. :type consumer_name: string :param credential_save_failed: a callback that is called upon a failure to save the credentials locally. This argument is used to construct the default `credential_store`, so if you pass in your own `credential_store` any value for this argument will be ignored. :type credential_save_failed: A callable :param credential_store: A strategy for storing an OAuth access token locally. By default, tokens are stored in the GNOME keyring (or equivalent). If `credentials_file` is provided, then tokens are stored unencrypted in that file. :type credential_store: `CredentialStore` :return: A web service root authorized as the end-user. :rtype: `Launchpad` """ (service_root, launchpadlib_dir, cache_path, service_root_dir) = cls._get_paths(service_root, launchpadlib_dir) if (application_name is None and consumer_name is None and authorization_engine is None): raise ValueError( "At least one of application_name, consumer_name, or " "authorization_engine must be provided.") if credentials_file is not None and credential_store is not None: raise ValueError( "At most one of credentials_file and credential_store " "must be provided.") if credential_store is None: if credentials_file is not None: # The end-user wants credentials stored in an # unencrypted file. credential_store = UnencryptedFileCredentialStore( credentials_file, credential_save_failed) else: credential_store = cls.credential_store_factory( credential_save_failed) else: # A credential store was passed in, so we won't be using # any provided value for credential_save_failed. But at # least make sure we weren't given a conflicting value, # since that makes the calling code look confusing. cls._assert_login_argument_consistency( 'credential_save_failed', credential_save_failed, credential_store.credential_save_failed, "credential_store") credential_store = credential_store if authorization_engine is None: authorization_engine = cls.authorization_engine_factory( service_root, application_name, consumer_name, allow_access_levels) else: # An authorization engine was passed in, so we won't be # using any provided values for application_name, # consumer_name, or allow_access_levels. But at least make # sure we weren't given conflicting values, since that # makes the calling code look confusing. cls._assert_login_argument_consistency( "application_name", application_name, authorization_engine.application_name) cls._assert_login_argument_consistency( "consumer_name", consumer_name, authorization_engine.consumer.key) cls._assert_login_argument_consistency( "allow_access_levels", allow_access_levels, authorization_engine.allow_access_levels) return cls._authorize_token_and_login( authorization_engine.consumer, service_root, cache_path, timeout, proxy_info, authorization_engine, allow_access_levels, credential_store, credential_save_failed, version) @classmethod def _warn_of_deprecated_login_method(cls, name): warnings.warn( ("The Launchpad.%s() method is deprecated. You should use " "Launchpad.login_anonymous() for anonymous access and " "Launchpad.login_with() for all other purposes.") % name, DeprecationWarning) @classmethod def _assert_login_argument_consistency( cls, argument_name, argument_value, object_value, object_name="authorization engine"): """Helper to find conflicting values passed into the login methods. Many of the arguments to login_with are used to build other objects--the authorization engine or the credential store. If these objects are provided directly, many of the arguments become redundant. We'll allow redundant arguments through, but if a argument *conflicts* with the corresponding value in the provided object, we raise an error. """ inconsistent_value_message = ( "Inconsistent values given for %s: " "(%r passed in, versus %r in %s). " "You don't need to pass in %s if you pass in %s, " "so just omit that argument.") if (argument_value is not None and argument_value != object_value): raise ValueError(inconsistent_value_message % ( argument_name, argument_value, object_value, object_name, argument_name, object_name)) @classmethod def _get_paths(cls, service_root, launchpadlib_dir=None): """Locate launchpadlib-related user paths and ensure they exist. This is a helper function used by login_with() and login_anonymously(). :param service_root: The service root the user wants to connect to. This may be an alias (which will be dereferenced to a URL and returned) or a URL (which will be returned as is). :param launchpadlib_dir: The user's base launchpadlib directory, if known. This may be modified, expanded, or determined from the environment if missing. A definitive value will be returned. :return: A 4-tuple: (service_root_uri, launchpadlib_dir, cache_dir, service_root_dir) """ if launchpadlib_dir is None: launchpadlib_dir = os.path.join('~', '.launchpadlib') launchpadlib_dir = os.path.expanduser(launchpadlib_dir) if launchpadlib_dir[:1] == '~': raise ValueError("Must set $HOME or pass 'launchpadlib_dir' to " "indicate location to store cached data") try: os.makedirs(launchpadlib_dir, 0o700) except OSError as err: if err.errno != errno.EEXIST: raise os.chmod(launchpadlib_dir, 0o700) # Determine the real service root. service_root = uris.lookup_service_root(service_root) # Each service root has its own cache and credential dirs. scheme, host_name, path, query, fragment = urlsplit(service_root) service_root_dir = os.path.join(launchpadlib_dir, host_name) cache_path = os.path.join(service_root_dir, 'cache') try: os.makedirs(cache_path, 0o700) except OSError as err: if err.errno != errno.EEXIST: raise return (service_root, launchpadlib_dir, cache_path, service_root_dir) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5192525 launchpadlib-1.10.13/src/launchpadlib/testing/0000755000175000017500000000000000000000000022700 5ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/src/launchpadlib/testing/__init__.py0000644000175000017500000000000000000000000024777 0ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587115752.0 launchpadlib-1.10.13/src/launchpadlib/testing/helpers.py0000644000175000017500000001474100000000000024723 0ustar00cjwatsoncjwatson00000000000000# Copyright 2008 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # launchpadlib is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with launchpadlib. If not, see # . """launchpadlib testing helpers.""" __metaclass__ = type __all__ = [ 'BadSaveKeyring', 'fake_keyring', 'FauxSocketModule', 'InMemoryKeyring', 'NoNetworkAuthorizationEngine', 'NoNetworkLaunchpad', 'TestableLaunchpad', 'nopriv_read_nonprivate', 'salgado_read_nonprivate', 'salgado_with_full_permissions', ] from contextlib import contextmanager import launchpadlib from launchpadlib.launchpad import Launchpad from launchpadlib.credentials import ( AccessToken, Credentials, RequestTokenAuthorizationEngine, ) missing = object() def assert_keyring_not_imported(): assert getattr(launchpadlib.credentials, 'keyring', missing) is missing, ( 'During tests the real keyring module should never be imported.') class NoNetworkAuthorizationEngine(RequestTokenAuthorizationEngine): """An authorization engine that doesn't open a web browser. You can use this to test the creation of Launchpad objects and the storing of credentials. You can't use it to interact with the web service, since it only pretends to authorize its OAuth request tokens. """ ACCESS_TOKEN_KEY = "access_key:84" def __init__(self, *args, **kwargs): super(NoNetworkAuthorizationEngine, self).__init__(*args, **kwargs) # Set up some instrumentation. self.request_tokens_obtained = 0 self.access_tokens_obtained = 0 def get_request_token(self, credentials): """Pretend to get a request token from the server. We do this by simply returning a static token ID. """ self.request_tokens_obtained += 1 return "request_token:42" def make_end_user_authorize_token(self, credentials, request_token): """Pretend to exchange a request token for an access token. We do this by simply setting the access_token property. """ credentials.access_token = AccessToken( self.ACCESS_TOKEN_KEY, 'access_secret:168') self.access_tokens_obtained += 1 class NoNetworkLaunchpad(Launchpad): """A Launchpad instance for tests with no network access. It's only useful for making sure that certain methods were called. It can't be used to interact with the API. """ def __init__(self, credentials, authorization_engine, credential_store, service_root, cache, timeout, proxy_info, version): self.credentials = credentials self.authorization_engine = authorization_engine self.credential_store = credential_store self.passed_in_args = dict( service_root=service_root, cache=cache, timeout=timeout, proxy_info=proxy_info, version=version) @classmethod def authorization_engine_factory(cls, *args): return NoNetworkAuthorizationEngine(*args) class TestableLaunchpad(Launchpad): """A base class for talking to the testing root service.""" def __init__(self, credentials, authorization_engine=None, credential_store=None, service_root="test_dev", cache=None, timeout=None, proxy_info=None, version=Launchpad.DEFAULT_VERSION): """Provide test-friendly defaults. :param authorization_engine: Defaults to None, since a test environment can't use an authorization engine. :param credential_store: Defaults to None, since tests generally pass in fully-formed Credentials objects. :param service_root: Defaults to 'test_dev'. """ super(TestableLaunchpad, self).__init__( credentials, authorization_engine, credential_store, service_root=service_root, cache=cache, timeout=timeout, proxy_info=proxy_info, version=version) @contextmanager def fake_keyring(fake): """A context manager which injects a testing keyring implementation.""" # The real keyring package should never be imported during tests. assert_keyring_not_imported() launchpadlib.credentials.keyring = fake launchpadlib.credentials.NoKeyringError = RuntimeError try: yield finally: del launchpadlib.credentials.keyring del launchpadlib.credentials.NoKeyringError class FauxSocketModule: """A socket module replacement that provides a fake hostname.""" def gethostname(self): return 'HOSTNAME' class BadSaveKeyring: """A keyring that generates errors when saving passwords.""" def get_password(self, service, username): return None def set_password(self, service, username, password): raise RuntimeError class InMemoryKeyring: """A keyring that saves passwords only in memory.""" def __init__(self): self.data = {} def set_password(self, service, username, password): self.data[service, username] = password def get_password(self, service, username): return self.data.get((service, username)) class KnownTokens: """Known access token/secret combinations.""" def __init__(self, token_string, access_secret): self.token_string = token_string self.access_secret = access_secret self.token = AccessToken(token_string, access_secret) self.credentials = Credentials( consumer_name="launchpad-library", access_token=self.token) def login(self, cache=None, timeout=None, proxy_info=None, version=Launchpad.DEFAULT_VERSION): """Create a Launchpad object using these credentials.""" return TestableLaunchpad( self.credentials, cache=cache, timeout=timeout, proxy_info=proxy_info, version=version) salgado_with_full_permissions = KnownTokens('salgado-change-anything', 'test') salgado_read_nonprivate = KnownTokens('salgado-read-nonprivate', 'secret') nopriv_read_nonprivate = KnownTokens('nopriv-read-nonprivate', 'mystery') ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/src/launchpadlib/testing/launchpad-wadl.xml0000644000175000017500000547714000000000000026330 0ustar00cjwatsoncjwatson00000000000000 ]> The Launchpad web service allows automated clients to access most of the functionality available on the Launchpad web site. For help getting started, see the help wiki. This version of the web service removes unnecessary named operations. It was introduced in March 2010, and its end-of-life date is April 2015, the same as the server version of the Ubuntu release "Lucid Lynx". The root of the web service. The link to the WADL description of this resource. Interface representing the set of branches.

Finds branches by URL.

Either from the external specified in Branch.url, from the URL on http://bazaar.launchpad.net/, or from the lp: URL.

This is a frontend shim to IBranchLookup.getByUrls to allow it to be exported over the API. If you want to call this from within the Launchpad app, use the IBranchLookup version instead.

param urls:An iterable of URLs expressed as strings.
return:A dictionary mapping URLs to branches. If the URL has no associated branch, the URL will map to None.
The name of the operation being invoked.

A list of URLs of branches

These can be URLs external to Launchpad, lp: URLs, or http://bazaar.launchpad.net/ URLs, or any mix of all these different kinds.

Find a branch by its ~owner/product/name unique name.

Return None if no match was found.

The name of the operation being invoked. Branch unique name

Find a branch by URL.

Either from the external specified in Branch.url, from the URL on http://bazaar.launchpad.net/ or the lp: URL.

This is a frontend shim to IBranchLookup.getByUrl to allow it to be exported over the API. If you want to call this from within the Launchpad app, use the IBranchLookup version instead.

Return None if no match was found.

The name of the operation being invoked. Branch URL

A set of IBugTracker's.

Each BugTracker is a distinct instance of a bug tracking tool. For example, bugzilla.mozilla.org is distinct from bugzilla.gnome.org.

Return one or None BugTracker's by baseurl The name of the operation being invoked. The base URL of the bug tracker

Get a BugTracker by its name.

If no tracker with the given name exists, return default.

The name of the operation being invoked. The bug tracker name

Make sure that there is a bugtracker for the given base url.

If not, create one using the given attributes.

The name of the operation being invoked.

Name

A URL-friendly name for the bug tracker, such as "mozilla-bugs".

Title

A descriptive label for this tracker to show in listings.

Bug Tracker Type

Location

The top-level URL for the bug tracker, or an upstream email address. This must be accurate so that Launchpad can link to external bug reports.

Summary

A brief introduction or overview of this bug tracker instance.

Contact details

The contact details for the external bug tracker (so that, for example, its administrators can be contacted about a security breach).

Collections of builders.

IBuilderSet provides access to all Builders in the system, and also acts as a Factory to allow the creation of new Builders. Methods on this interface should deal with the set of Builders: methods that affect a single Builder should be on IBuilder.

Retrieve a builder by name The name of the operation being invoked. Builder name
A container for countries. Return a country by its code. The name of the operation being invoked. Code Return a country by its name. The name of the operation being invoked. Name The set of ICve objects. Interface for DistrosSet

The collection of languages.

The standard get method will return only the visible languages. If you want to access all languages known to Launchpad, use the getAllLanguages method.

Return a result set of all ILanguages from Launchpad. The name of the operation being invoked.
Application root for malone.

Create a bug (with an appropriate bugtask) and return it.

param target:The Product, Distribution or DistributionSourcePackage affected by this bug.

Things to note when using this factory:

  • the owner will be subscribed to the bug
  • distribution, product and package contacts (whichever ones are applicable based on the bug report target) will be subscribed to all public bugs only
  • for public upstreams bugs where there is no upstream bug contact, the product owner will be subscribed instead
The name of the operation being invoked. This bug is a security vulnerability. The project, distribution or source package that has this bug.

Tags

Space-separated keywords for classifying this bug report.

Summary

A one-line summary of the problem.

This bug report should be private

Private bug reports are visible only to their subscribers.

Description

A detailed description of the problem,
including the steps required to reproduce it.
An interface for multiple package sets.

Get the package sets that include this source package.

Return all package sets that directly or indirectly include the given source package name.

param sourcepackagename:
 the included source package name; can be either a string or a ISourcePackageName.
param distroseries:
 the IDistroSeries in which to look for sets. If omitted, matching package sets from all series will be returned.
param direct_inclusion:
 if this flag is set to True, then only package sets that directly include this source package name will be considered.
raises NoSuchSourcePackageName:
 if a source package with the given name cannot be found.
return:A (potentially empty) sequence of IPackageset instances.
The name of the operation being invoked. Source package name

Distribution series

The distroseries to which this package set is related.

Return the single package set with the given name (if any).

param name:the name of the package set sought.
param distroseries:
 the distroseries to which the new packageset is related. Defaults to the current Ubuntu series.
return:An IPackageset instance.
raise NoSuchPackageSet:
 if no package set is found.
The name of the operation being invoked.

Distroseries

The distribution series to which the packageset is related.

Package set name

Return the package sets associated with the given distroseries.

param distroseries:
 A DistroSeries.
return:An iterable collection of IPackageset instances.
The name of the operation being invoked.

Distribution series

The distroseries to which this package set is related.

Create a new package set.

param name:the name of the package set to be created.
param description:
 the description for the package set to be created.
param owner:the owner of the package set to be created.
param distroseries:
 the distroseries to which the new packageset is related. Defaults to the current Ubuntu series.
param related_set:
 the newly created package set is to be related to related_set (by being placed in the same package group).
raises DuplicatePackagesetName:
 if a package set with the same name exists in distroseries already.
return:a newly created IPackageset.
The name of the operation being invoked.

Person

The person who owns this package set.

Distroseries

The distribution series to which the packageset is related.

Package set description Valid package set name

Related package set

The new package set will share the package set group with this one.

The set of Persons.

Return all non-merged Persons with at least one email address whose name, displayname or email address match <text>.

If text is an empty string, all persons with at least one email address will be returned.

The results will be ordered using the default ordering specified in Person._defaultOrder.

If exclude_inactive_accounts is True, any accounts whose account_status is any of INACTIVE_ACCOUNT_STATUSES will not be in the returned set.

If must_have_email is True, only people with one or more email addresses are returned.

While we don't have Full Text Indexes in the emailaddress table, we'll be trying to match the text only against the beginning of an email address.

If created_before or created_after are not None, they are used to restrict the search to the dates provided.

The name of the operation being invoked. Search text Created before Created after

Return the person with the given email address.

Return None if there is no person with the given email address.

The name of the operation being invoked.

Return all non-merged Persons and Teams whose name, displayname or email address match <text>.

The results will be ordered using the default ordering specified in Person._defaultOrder.

While we don't have Full Text Indexes in the emailaddress table, we'll be trying to match the text only against the beginning of an email address.

The name of the operation being invoked. Search text

Return all Teams whose name, displayname or email address match <text>.

The results will be ordered using the default ordering specified in Person._defaultOrder.

While we don't have Full Text Indexes in the emailaddress table, we'll be trying to match the text only against the beginning of an email address.

The name of the operation being invoked. Search text
Create and return a new Team with given arguments. The name of the operation being invoked.

Display Name

Your name as you would like it displayed throughout Launchpad. Most people use their full name here.

Name

A short unique name, beginning with a lower-case letter or number, and containing only letters, numbers, dots, hyphens, or plus signs.

Subscription period

Number of days a new subscription lasts before expiring. You can customize the length of an individual subscription when approving it. Leave this empty or set to 0 for subscriptions to never expire.

Team Description

Details about the team's work, highlights, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages.

Renewal period

Number of days a subscription lasts after being renewed. The number can be from 1 to 3650 (10 years). You can customize the lengths of individual renewals, but this is what's used for auto-renewed and user-renewed memberships.

Subscription policy
Operations related to ProcessorFamily instances. Operations related to Processor instances.

Search through the Registry database for products that match the query terms. text is a piece of text in the title / summary / description fields of product.

This call eager loads data appropriate for web API; caution may be needed for other callers.

The name of the operation being invoked. Search text
Return an iterator over products that need to be reviewed. The name of the operation being invoked. Subscription modified after License info is empty Search text Is the project license reviewed Subscription expires after Is the project active Subscription modified before Created after date Licenses Subscription expired before Created before date Has zero licenses

Return the latest projects registered in Launchpad.

If the quantity is not specified or is a value that is not 'None' then the set of projects returned is limited to that value (the default quantity is 5). If quantity is 'None' then all projects are returned. For the web service it is not possible to specify the quantity, so all projects are returned, latest first.

The name of the operation being invoked.

Create and return a brand new Product.

See IProduct for a description of the parameters.

The name of the operation being invoked.

Wiki URL

The full URL of this project's wiki, if it has
one. Please include the http://

Download URL

The full URL where downloads for this project
are located, if available. Please include the http://

Display Name

The name of the project as it would appear in a
paragraph.

Description

Details about the project's work, highlights, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages. Don't repeat the Summary.

Title

The project title. Should be just a few words.

Project reviewed

Whether or not this project has been reviewed. If you looked at the project and how it uses Launchpad, you reviewed it.

Summary

A short paragraph to introduce the project's work.

Part of

Project group. This is an overarching initiative that includes several related projects. For example, the Mozilla Project produces Firefox, Thunderbird and Gecko. This information is used to group those projects in a coherent way. If you make this project part of a group, the group preferences and decisions around bug tracking, translation and security policy will apply to this project.

Licenses

Freshmeat Project

The Freshmeat project name for
this project, if it is in freshmeat.

Sourceforge Project

The SourceForge project name for
this project, if it is in sourceforge.

Programming Languages

A comma delimited list of programming
languages used for this project.

Screenshots URL

The full URL for screenshots of this project,
if available. Please include the http://

Description of additional licenses

Description of licenses that do not appear in the list above.

Homepage URL

The project home page. Please include
the http://

Registrant

This person registered the project in Launchpad.

Name

At least one lowercase letter or number, followed by letters, numbers, dots, hyphens or pluses. Keep this name short; it is used in URLs as shown above.

The collection of projects. Search through the Registry database for projects that match the query terms. text is a piece of text in the title / summary / description fields of project (and possibly product). soyuz, bazaar, malone etc are hints as to whether the search should be limited to projects that are active in those Launchpad applications. The name of the operation being invoked. Search text A utility that contain all the questions published in Launchpad. A tool to create temporary blobs. Retrieve a TemporaryBlobStorage by uuid. The name of the operation being invoked. UUID A container for translation groups. A set of files to be imported into Rosetta.

Return all entries this import queue has.

arg target:IPerson, IProduct, IProductSeries, IDistribution, IDistroSeries or ISourcePackage the import entries are attached to or None to get all entries available.
arg import_status:
 RosettaImportStatus entry.
arg file_extensions:
 Sequence of filename suffixes to match, usually 'po' or 'pot'.

If any of target, status or file_extension are given, the returned entries are filtered based on those values.

The name of the operation being invoked. The status of the import.

List Product`s and `DistroSeries with pending imports.

arg status:Filter by RosettaImportStatus.

All returned items will implement IHasTranslationImports.

The name of the operation being invoked. The status of the import.

Return the first entry of the queue ready to be imported.

param target:IPerson, IProduct, IProductSeries, IDistribution, IDistroSeries or ISourcePackage the import entries are attached to or None to get all entries available.
The name of the operation being invoked.
ArchiveDependency interface. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Target archive

The archive affected by this dependecy.

Component name Instant when the dependency was created. The archive set as a dependency. Pocket Archive dependency title.
Main Archive interface.

True if the person is allowed to upload the given source package.

Return True if there exists a permission that combines
  • this archive
  • a package set that includes the given source package name
  • the given person or a team he is a member of

If the source package name is included by any package set with an explicit permission then only such explicit permissions will be considered.

param sourcepackagename:
 the source package name; can be either a string or a ISourcePackageName.
param person:An IPerson for whom you want to find out which package sets he has access to.
param distroseries:
 The IDistroSeries for which to check permissions. If none is supplied then currentseries in Ubuntu is assumed.
raises NoSuchSourcePackageName:
 if a source package with the given name could not be found.
return:True if the person is allowed to upload the source package.
The distro series Source package name

Return a dictionary containing the build counters for an archive.

This is necessary currently because the IArchive.failed_builds etc. counters are not in use.

The returned dictionary contains the follwoing keys and values:

  • 'total': total number of builds (includes SUPERSEDED);
  • 'pending': number of builds in BUILDING or NEEDSBUILD state;
  • 'failed': number of builds in FAILEDTOBUILD, MANUALDEPWAIT, CHROOTWAIT and FAILEDTOUPLOAD state;
  • 'succeeded': number of SUCCESSFULLYBUILT builds.
  • 'superseded': number of SUPERSEDED builds.
param include_needsbuild:
 Indicates whether to include builds with the status NEEDSBUILD in the pending and total counts. This is useful in situations where a build that hasn't started isn't considered a build by the user.
type include_needsbuild:
 bool
return:a dictionary with the 4 keys specified above.
rtype:dict.
Include builds with state NEEDSBUILD

Return IArchivePermission for the person's queue admin components.

param person:An IPerson.
return:A list of IArchivePermission records.
Wrapper around checkUpload for the web service API. The distro series Component Strict component

Pocket

The pocket into which this entry is published

Source package name

Return the IArchiveDependency object for the given dependency.

param dependency:
 is an IArchive object.
return:IArchiveDependency or None if a corresponding object could not be found.

All ISourcePackagePublishingHistory target to this archive.

param name:source name filter (exact match or SQL LIKE controlled by 'exact_match' argument). Name can be a single string or a list of strings.
param version:source version filter (always exact match).
param status:PackagePublishingStatus filter, can be a sequence.
param distroseries:
 IDistroSeries filter.
param pocket:PackagePublishingPocket filter. This may be an iterable of more than one pocket or a single pocket.
param exact_match:
 either or not filter source names by exact matching.
param created_since_date:
 Only return results whose date_created is greater than or equal to this date.
return:SelectResults containing ISourcePackagePublishingHistory, ordered by name. If there are multiple results for the same name then they are sub-ordered newest first.

Package Publishing Status

The status of this publishing record

Source package name Distroseries name

Exact Match

Whether or not to filter source names by exact matching.

Pocket

The pocket into which this entry is published

Version

Created Since Date

Return entries whose date_created is greater than or equal to this date.

The ArchivePermission records for uploaders to the package set.

param packageset:
 An IPackageset.
param direct_permissions:
 If True, only consider permissions granted directly for the package set at hand. Otherwise, include any uploaders for package sets that include this one.
return:ArchivePermission records for all the uploaders who are authorized to upload to the named source package set.
Package set Ignore package set hierarchy

All package set based permissions for the given source.

This method is meant to aid the process of "debugging" package set based archive permission since It allows the listing of permissions for the given source package in this archive (irrespective of the principal).

param sourcepackagename:
 the source package name; can be either a string or a ISourcePackageName.
param direct_permissions:
 If set only package sets that directly include the given source will be considered.
raises NoSuchSourcePackageName:
 if a source package with the given name could not be found.
return:ArchivePermission records for the package sets that include the given source package name and apply to the archive in question.
Source package name Ignore package set hierarchy

Return build records in the context it is implemented.

It excludes build records generated by Gina (imported from a external repository), where IBuild.datebuilt is null and IBuild.buildstate is BuildStatus.FULLYBUILT.

The result is simply not filtered if the optional filters are omitted by call sites.

param build_state:
 optional BuildStatus value for filtering build records;
param name:optional string for filtering build source package name. Sub-string matching is allowed via SQL LIKE.
param pocket:optional PackagePublishingPocket value for filtering build records;
param arch_tag:optional string for filtering build source packages by their architecture tag;
param user:optional IPerson corresponding to the user performing the request. It will filter out build records for which the user have no 'view' permission.
param binary_only:
 optional boolean indicating whether only BinaryPackageBuild objects should be returned, or more general PackageBuild objects (which may include, for example, SourcePackageRecipeBuild objects.
return:a result set containing IPackageBuild records ordered by descending IPackageBuild.date_finished except when builds are filtered by BuildStatus.NEEDSBUILD, in this case records are ordered by descending BuildQueue.lastscore (dispatching order).

Pocket

The pocket into which this entry is published

Build status

The status of this build record

Source package name

All IBinaryPackagePublishingHistory target to this archive.

param:name: binary name filter (exact match or SQL LIKE controlled by 'exact_match' argument).
param:version: binary version filter (always exact match).
param:status: PackagePublishingStatus filter, can be a list.
param:distroarchseries: IDistroArchSeries filter, can be a list.
param:pocket: PackagePublishingPocket filter.
param:exact_match: either or not filter source names by exact matching.
return:A collection containing BinaryPackagePublishingHistory.

Package Publishing Status

The status of this publishing record

Binary Package Name Whether or not to filter binary names by exact matching.

Pocket

The pocket into which this entry is published

Version Distro Arch Series

Return IArchivePermission records for the component's uploaders.

param component_name:
 An IComponent or textual name for the component.
return:A list of IArchivePermission records.
Component Name

Return IArchivePermission records for the package's uploaders.

param source_package_name:
 An ISourcePackageName or textual name for the source package.
return:A list of IArchivePermission records.
Source Package Name

Return a dictionary containing a summary of the build statuses.

Only information for sources belonging to the current archive will be returned. See IPublishingSet.getBuildStatusSummariesForSourceIdsAndArchive() for details.

param source_ids:
 A list of source publishing history record ids.
type source_ids:
 list
return:A dict consisting of the overall status summaries for the given ids that belong in the archive.
A list of source publishing history record ids.

Return IArchivePermission records for authorised queue admins.

param component_name:
 An IComponent or textual name for the component.
return:A list of IArchivePermission records.
Component Name

Return the IArchivePermission records applicable to the person.

param person:An IPerson
return:A list of IArchivePermission records.

The package set based permissions for a given source and uploader.

Return the IArchivePermission records that
  • apply to this archive

  • relate to
    • package sets that include the given source package name
    • the given person
param sourcepackagename:
 the source package name; can be either a string or a ISourcePackageName.
param person:An IPerson for whom you want to find out which package sets he has access to.
raises NoSuchSourcePackageName:
 if a source package with the given name could not be found.
return:ArchivePermission records for the package sets that include the given source package name and to which the given person may upload.
Source package name

The ArchivePermission records for the person's package sets.

param person:An IPerson for whom you want to find out which package sets he has access to.
return:ArchivePermission records for all the package sets that 'person' is allowed to upload to.

Synchronise (copy) a single named source into this archive.

Copy a specific version of a named source to the destination archive if necessary.

param source_name:
 a string name of the package to copy.
param version:the version of the package to copy.
param from_archive:
 the source archive from which to copy.
param to_pocket:
 the target pocket (as a string).
param to_series:
 the target distroseries (as a string).
param include_binaries:
 optional boolean, controls whether or not the published binaries for each given source should also be copied along with the source.
param person:the IPerson who requests the sync.
raises NoSuchSourcePackageName:
 if the source name is invalid
raises PocketNotFound:
 if the pocket name is invalid
raises NoSuchDistroSeries:
 if the distro series name is invalid
raises CannotCopy:
 if there is a problem copying.
Distroseries name Source package name Version Pocket name

Include Binaries

Whether or not to copy binaries already built for this source

Revoke permission for the person to administer distroseries queues.

The supplied person will lose permission to administer the distroseries queue for packages in the supplied component.

param person:An IPerson whose permission should be revoked.
param component:
 An IComponent or textual component name.
Component Name

Add permission for a person to upload to a component.

param person:An IPerson whom should be given permission.
param component:
 An IComponent or textual component name.
return:An IArchivePermission which is the newly-created permission.
raises InvalidComponent:
 if this archive is a PPA and the component is not 'main'.
Component Name

Synchronise (copy) named sources into this archive from another.

It will copy the most recent PUBLISHED versions of the named sources to the destination archive if necessary.

This operation will only succeeds when all requested packages are synchronised between the archives. If any of the requested copies cannot be performed, the whole operation will fail. There will be no partial changes of the destination archive.

param source_names:
 a list of string names of packages to copy.
param from_archive:
 the source archive from which to copy.
param to_pocket:
 the target pocket (as a string).
param to_series:
 the target distroseries (as a string).
param include_binaries:
 optional boolean, controls whether or not the published binaries for each given source should also be copied along with the source.
param person:the IPerson who requests the sync.
raises NoSuchSourcePackageName:
 if the source name is invalid
raises PocketNotFound:
 if the pocket name is invalid
raises NoSuchDistroSeries:
 if the distro series name is invalid
raises CannotCopy:
 if there is a problem copying.
Distroseries name Pocket name Source package names

Include Binaries

Whether or not to copy binaries already built for this source

Revoke permission for the person to upload the package.

param person:An IPerson whose permission should be revoked.
param source_package_name:
 An ISourcePackageName or textual package name.
Source Package Name

Revoke upload permissions for a person.

param person:An IPerson for whom you want to revoke permission.
param packageset:
 An IPackageset.
param explicit:The value of the 'explicit' flag for the permission to be revoked.
Package set Explicit

Add permisson for a person to upload a package to this archive.

param person:An IPerson whom should be given permission.
param source_package_name:
 An ISourcePackageName or textual package name.
return:An IArchivePermission which is the newly-created permission.
Source Package Name

Revoke permission for the person to upload to the component.

param person:An IPerson whose permission should be revoked.
param component:
 An IComponent or textual component name.
Component Name

Add a package set based permission for a person.

param person:An IPerson for whom you want to add permission.
param packageset:
 An IPackageset.
param explicit:True if the package set in question requires specialist skills for proper handling.
return:The new ArchivePermission, or the existing one if it already exists.
Package set Explicit

Create a new subscribtion to this archive.

Create an ArchiveSubscriber record which allows an IPerson to access a private repository.

param subscriber:
 An IPerson who is allowed to access the repository for this archive.
param registrant:
 An IPerson who created this subscription.
param date_expires:
 When the subscription should expire; None if it should not expire (default).
param description:
 An option textual description of the subscription being created.
return:The IArchiveSubscriber that was created.

Subscriber

The person who is subscribed.

Date of Expiration

The timestamp when the subscription will expire.

Description

Free text describing this subscription.

Add permission for a person to administer a distroseries queue.

The supplied person will gain permission to administer the distroseries queue for packages in the supplied component.

param person:An IPerson whom should be given permission.
param component:
 An IComponent or textual component name.
return:An IArchivePermission which is the newly-created permission.
Component Name
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Commercial

Display the archive in Software Center's commercial listings. Only private archives can be commercial.

Archive dependencies recorded for this archive.

Description

A short description of the archive. URLs are allowed and will be rendered as links.

Display name

A short title for the archive.

The distribution that uses or is used by this archive.

External dependencies

Newline-separated list of repositories to be used to retrieve any external build dependencies when building packages in the archive, in the format: deb http[s]://[user:pass@]<host>[/path] %(series)s[-pocket] [components] The series variable is replaced with the series name of the context build. NOTE: This is for migration of OEM PPAs only!

Name

At least one lowercase letter or number, followed by letters, numbers, dots, hyphens or pluses. Keep this name short; it is used in URLs.

Owner

The archive owner.

Private

Restrict access to the archive to its owner and subscribers. This can only be changed if the archive has never had any sources published.

Require virtualized builders

Only build the archive's packages on virtual builders.

Archive signing key fingerprint

A OpenPGP signing key fingerprint (40 chars) for this PPA or None if there is no signing key available.

Commercial

Display the archive in Software Center's commercial listings. Only private archives can be commercial.

Description

A short description of the archive. URLs are allowed and will be rendered as links.

Display name

A short title for the archive.

The distribution that uses or is used by this archive.

External dependencies

Newline-separated list of repositories to be used to retrieve any external build dependencies when building packages in the archive, in the format: deb http[s]://[user:pass@]<host>[/path] %(series)s[-pocket] [components] The series variable is replaced with the series name of the context build. NOTE: This is for migration of OEM PPAs only!

Name

At least one lowercase letter or number, followed by letters, numbers, dots, hyphens or pluses. Keep this name short; it is used in URLs.

Owner

The archive owner.

Private

Restrict access to the archive to its owner and subscribers. This can only be changed if the archive has never had any sources published.

Require virtualized builders

Only build the archive's packages on virtual builders.

Archive signing key fingerprint

A OpenPGP signing key fingerprint (40 chars) for this PPA or None if there is no signing key available.

The interface for ArchivePermission. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Archive

The archive that this permission is for.

Component Name

Date Created

The timestamp when the permission was created.

The name of the distro series associated with the package set.

Explicit

Set this flag for package sets with high-profile packages requiring specialist skills for proper handling.

Package set name The permission type being granted.

Person

The person or team being granted the permission.

Source Package Name

Archive

The archive that this permission is for.

Component Name

Date Created

The timestamp when the permission was created.

The name of the distro series associated with the package set.

Explicit

Set this flag for package sets with high-profile packages requiring specialist skills for proper handling.

Package set name The permission type being granted.

Person

The person or team being granted the permission.

Source Package Name
An interface for archive subscribers. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Archive

The archive for this subscription.

Date Created

The timestamp when the subscription was created.

Date of Expiration

The timestamp when the subscription will expire.

Description

Free text describing this subscription.

Registrant

The person who registered this subscription.

Status

The status of this subscription.

Subscriber

The person who is subscribed.

Date of Expiration

The timestamp when the subscription will expire.

Description

Free text describing this subscription.

Status

The status of this subscription.

A Build interface

Restore the build record to its initial state.

Build record loses its history, is moved to NEEDSBUILD and a new non-scored BuildQueue entry is created for it.

Change the build's score. Score
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Architecture tag

Archive

The Archive context for this build.

Build Log URL

A URL for the build log. None if there is no log available.

Status

The current status of the job.

Can Be Rescored

Whether or not this build record can be rescored manually.

Can Be Retried

Whether or not this build record can be retried.

Changes File URL

The URL for the changes file for this build. Will be None if the build was imported by Gina.

Source publication

The current source publication for this build.

Date finished

The actual build start time. Set when the build is dispatched the first time and not changed in subsequent build attempts.

Date finished

The timestamp when the build farm job was finished.

Date created

The timestamp when the build farm job was created.

Dependencies

Debian-like dependency line that must be satisfied before attempting to build this request.

Distribution

Shortcut for its distribution.

Pocket

The build targeted pocket.

Score of the related job (if any) Title

Upload Log URL

A URL for failed upload logs.Will be None if there was no failure.

Architecture tag

Build Log URL

A URL for the build log. None if there is no log available.

Status

The current status of the job.

Changes File URL

The URL for the changes file for this build. Will be None if the build was imported by Gina.

Dependencies

Debian-like dependency line that must be satisfied before attempting to build this request.

Distribution

Shortcut for its distribution.

Pocket

The build targeted pocket.

Title

Upload Log URL

A URL for failed upload logs.Will be None if there was no failure.

A binary package publishing record.

Get detailed download counts for this binary.

param start_date:
 The optional first date to return.
param end_date:The optional last date to return.
Start date End date

Get the daily download counts for this binary.

param start_date:
 The optional first date to return.
param end_date:The optional last date to return.
Start date End date

Get the download count of this binary package in this archive.

This is currently only meaningful for PPAs.

Delete this source and its binaries.

param removed_by:
 IPerson responsible for the removal.
param removal_comment:
 optional text describing the removal reason.
Removal comment
The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Architecture Specific

Archive

The context archive for this publication.

Binary Package Name Binary Package Version Component Name

Date Created

The date on which this record was created

Date Made Pending

The date on which this record was set as pending removal

Date Published

The date on which this record was published

Date Removed

The date on which this record was removed from the published set

Date Superseded

The date on which this record was marked superseded

Display Name

Text representation of the current record.

Distro Arch Series

The distroarchseries being published into

Pocket

The pocket into which this entry is published

Priority Name

Removal Comment

Reason why this publication is going to be removed.

Removed By

The Person responsible for the removal

Scheduled Deletion Date

The date on which this record is scheduled for deletion

Section Name

Status

The status of this publishing record

Date Created

The date on which this record was created

Date Made Pending

The date on which this record was set as pending removal

Date Published

The date on which this record was published

Date Removed

The date on which this record was removed from the published set

Date Superseded

The date on which this record was marked superseded

Display Name

Text representation of the current record.

Distro Arch Series

The distroarchseries being published into

Removal Comment

Reason why this publication is going to be removed.

Removed By

The Person responsible for the removal

Scheduled Deletion Date

The date on which this record is scheduled for deletion

Status

The status of this publishing record

Daily download count of a binary package release in an archive. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Archive Binary package name Binary package version Number of downloads Country Day of the downloads A Bazaar branch. Return the BranchSubscription for this person. The person to unsubscribe

Can this branch be deleted in its current state.

A branch is considered deletable if it has no revisions, is not linked to any bugs, specs, productseries, or code imports, and has no subscribers.

Return true if the reviewer is a trusted reviewer.

The reviewer is trusted if they are either own the branch, or are in the team that owns the branch, or they are in the review team for the branch.

A person for which the reviewer status is in question.
Return matching BranchMergeProposals. A list of merge proposal statuses to filter by.

Return a public URL for the branch using the given protocol.

param scheme:a protocol name accepted by the public code-hosting API. (As a legacy issue, 'sftp' is also accepted).
URL scheme

Link an ISpecification to a branch.

param spec:ISpecification to link.
param registrant:
 IPerson unlinking the spec.
Request that this branch be mirrored on the next run of the branch puller.

Link a bug to this branch.

param bug:IBug to link.
param registrant:
 IPerson linking the bug.

Set the target of the branch to be project or source_package.

Only one of project or source_package can be set, and if neither is set, the branch gets moved into the junk namespace of the branch owner.

raise:BranchTargetError if both project and source_package are set, or if either the project or source_package fail to be adapted to an IBranchTarget.
The project the branch belongs to. The source package the branch belongs to.

Unlink a bug to this branch.

param bug:IBug to unlink.
param user:IPerson unlinking the bug.

Subscribe this person to the branch.

param person:The Person to subscribe.
param notification_level:
 The kinds of branch changes that cause notification.
param max_diff_lines:
 The maximum number of lines of diff that may appear in a notification.
param code_review_level:
 The kinds of code review activity that cause notification.
param subscribed_by:
 The person who is subscribing the subscriber. Most often the subscriber themselves.
return:new or existing BranchSubscription.
The level of code review notification emails. The level of notification to subscribe to. The max number of lines for diff email. The person to subscribe.

Unlink an ISpecification to a branch.

param spec:ISpecification to unlink.
param user:IPerson unlinking the spec.

Remove the person's subscription to this branch.

param person:The person or team to unsubscribe from the branch.
param unsubscribed_by:
 The person doing the unsubscribing.
The person to unsubscribe
Set the owner of the branch to be new_owner. The new owner of the branch.

Create a new BranchMergeProposal with this branch as the source.

Both the target_branch and the prerequisite_branch, if it is there, must be branches with the same target as the source branch.

Personal branches (a.k.a. junk branches) cannot specify landing targets.

Needs review

If True the proposal needs review.Otherwise, it will be work in progress.

Initial comment

Registrant's initial description of proposal.

Commit message

Message to use when committing this merge.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Branch Format Branch Type

Bazaar Identity

The bzr branch path as accessed by Launchpad. If the branch is associated with a product as the primary development focus, then the result should be lp:product. If the branch is related to a series, then lp:product/series. Otherwise the result is lp:~user/product/branch-name.

The associated CodeImport, if any. Control Directory Date Created Date Last Modified

Dependent Branches

A collection of the merge proposals that are dependent on this branch.

Description

A short description of the changes in this branch.

Display name

The branch unique_name.

Keep branch confidential

Make this branch visible only to its subscribers.

Landing Candidates

A collection of the merge proposals where this branch is the target branch.

Landing Targets

A collection of the merge proposals where this branch is the source branch.

Last time a mirror of this branch was attempted. Last time this branch was successfully mirrored. Last time this branch was successfully scanned.

Last scanned revision ID

The head revision ID of the branch when last successfully scanned.

Status The bugs linked to this branch.

Branch Merge Queue

The branch merge queue that manages merges for this branch.

Name

A JSON string of configuration values to send to a branch merge robot.

The last message we got when mirroring this branch.

Name

Keep very short, unique, and descriptive, because it will be used in URLs. Examples: main, devel, release-1.0, gnome-vfs.

Owner

Either yourself or a team you are a member of. This controls who can modify the branch.

Branch is confidential

This branch is visible only to its subscribers.

Project

The project this branch belongs to.

All recipes associated with the object. The user that registered the branch. Repository Format

Review Team

The reviewer of a branch is the person or team that is responsible for reviewing proposals and merging into this branch.

Revision count

The revision number of the tip of the branch.

The ISourcePackage that this branch belongs to. None if not a package branch. Specification linked to this branch. Persons subscribed to this branch. BranchSubscriptions associated to this branch.

Unique name

Unique name of the branch, including the owner and project names.

Branch URL

The external location where the Bazaar branch is hosted. It is None when the branch is hosted by Launchpad.

Whiteboard

Notes on the current status of the branch.

The associated CodeImport, if any. Date Last Modified

Description

A short description of the changes in this branch.

Keep branch confidential

Make this branch visible only to its subscribers.

Status

Branch Merge Queue

The branch merge queue that manages merges for this branch.

Name

A JSON string of configuration values to send to a branch merge robot.

Name

Keep very short, unique, and descriptive, because it will be used in URLs. Examples: main, devel, release-1.0, gnome-vfs.

Review Team

The reviewer of a branch is the person or team that is responsible for reviewing proposals and merging into this branch.

Branch URL

The external location where the Bazaar branch is hosted. It is None when the branch is hosted by Launchpad.

Whiteboard

Notes on the current status of the branch.

Branch merge proposals show intent of landing one branch on another. Return the CodeReviewComment with the specified ID. A CodeReviewComment ID.

Set the specified person as a reviewer.

If they are not already a reviewer, a vote is created. Otherwise, the details are updated.

A reviewer.

Update the preview diff for this proposal.

If there is not an existing preview diff, one will be created.

param diff_content:
 The raw bytes of the diff content to be put in the librarian.
param diff_stat:
 Text describing the files added, remove or modified.
param source_revision_id:
 The revision id that was used from the source branch.
param target_revision_id:
 The revision id that was used from the target branch.
param prerequisite_revision_id:
 The revision id that was used from the prerequisite branch.
param conflicts:
 Text describing the conflicts if any.

Create an ICodeReviewComment associated with this merge proposal.

param owner:The person who the message is from.
param subject:The subject line to use for the message.
param content:The text to use for the message content. If unspecified, the text of the merge proposal is used.
param parent:The previous CodeReviewComment in the thread. If unspecified, the root message is used.

Set the state of the merge proposal to the specified status.

param status:The new status of the merge proposal.
param user:The user making the change.
param revision_id:
 The revision id to provide to the underlying status change method.
The new status of the merge proposal. An optional parameter for specifying the revision of the branch for the status change.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

The email address for this proposal.

Any emails sent to this address will resultin comments being added.

All messages discussing this merge proposal

Commit Message

The commit message that should be used when merging the source branch.

Date Created

Date Merged

The date that the source branch was merged into the target branch

Date Queued Date Review Requested Date Reviewed

Description

A detailed description of the changes that are being addressed by the branch being proposed to be merged.

Merge Reporter

The user that marked the branch as merged.

Merged Revision Number

The revision number on the target branch which contains the merge from the source branch.

Prerequisite Branch

The branch that the source branch branched from. If this branch is the same as the target branch, then leave this field blank.

The current diff of the source branch against the target branch.

Proposal is confidential

If True, this proposal is visible only to subscribers.

Queue Position

The position in the queue.

Status

The current state of the proposal.

Queued Revision ID

The revision id that has been queued for landing.

Queuer

The person that queued up the branch.

Person

The person who registered the merge proposal.

The revision id that has been approved by the reviewer.

Review person or team

The person that accepted (or rejected) the code for merging.

Source Branch

The branch that has code to land.

Superseded By

The branch merge proposal that supersedes this one.

Supersedes

The branch merge proposal that this one supersedes.

Target Branch

The branch that the source branch will be merged into.

The votes cast or expected for this proposal

Commit Message

The commit message that should be used when merging the source branch.

Description

A detailed description of the changes that are being addressed by the branch being proposed to be merged.

The revision id that has been approved by the reviewer.
An interface for managing branch merges. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Dependent Branches

A collection of branches that this queue manages.

Configuration

A JSON string of configuration values.

Date Created

Description

A short description of the purpose of this merge queue.

Name

Keep very short, unique, and descriptive, because it will be used in URLs. Examples: main, devel, release-1.0, gnome-vfs.

Owner

The owner of the merge queue.

The user that registered the branch.

Configuration

A JSON string of configuration values.

Description

A short description of the purpose of this merge queue.

Name

Keep very short, unique, and descriptive, because it will be used in URLs. Examples: main, devel, release-1.0, gnome-vfs.

The relationship between a person and a branch. Can the user unsubscribe the subscriber from the branch? The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Branch ID

Generated Diff Size Limit

Diffs greater than the specified number of lines will not be sent to the subscriber. The subscriber will still receive an email with the new revision details even if the diff is larger than the specified number of lines.

Notification Level

Attribute notifications are sent when branch details are changed such as lifecycle status and name. Revision notifications are generated when new branch revisions are found due to the branch being updated through either pushes to the hosted branches or the mirrored branches being updated.

Person

Enter the launchpad id, or email address of the person you wish to subscribe to this branch. If you are unsure, use the "Choose..." option to find the person in Launchpad. You can only subscribe someone who is a registered user of the system.

Code review Level

Control the kind of review activity that triggers notifications.

Subscribed by

The person who created this subscription.

Generated Diff Size Limit

Diffs greater than the specified number of lines will not be sent to the subscriber. The subscriber will still receive an email with the new revision details even if the diff is larger than the specified number of lines.

Notification Level

Attribute notifications are sent when branch details are changed such as lifecycle status and name. Revision notifications are generated when new branch revisions are found due to the branch being updated through either pushes to the hosted branches or the mirrored branches being updated.

Code review Level

Control the kind of review activity that triggers notifications.

A log of all things that have happened to a bug. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Bug

Date Changed

The date on which this activity occurred.

Message

Additional information about what changed.

New Value

The value after the change.

Old Value

The value before the change.

Person

The person's Launchpad ID or e-mail address.

What Changed

The property of the bug that changed.

A file attachment to an IBug.

Launchpadlib example of accessing content of an attachment:

for attachment in bug.attachments:
    buffer = attachment.data.open()
    for line in buffer:
        print line
    buffer.close()

Launchpadlib example of accessing metadata about an attachment:

attachment = bug.attachments[0]
print "title:", attachment.title
print "ispatch:", attachment.type

For information about the file-like object returned by attachment.data.open() see lazr.restfulclient's documentation of the HostedFile object.

Details about the message associated with an attachment can be found on the "message" attribute:

message = attachment.message
print "subject:", message.subject.encode('utf-8')
print "owner:", message.owner.display_name.encode('utf-8')
print "created:", message.date_created
Remove the attachment from the bug.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The bug the attachment belongs to. The attachment content. The message that was created when we added this attachment.

Title

A short and descriptive description of the attachment

Attachment Type

The type of the attachment, for example Patch or Unspecified.

The bug the attachment belongs to. The message that was created when we added this attachment.

Title

A short and descriptive description of the attachment

Attachment Type

The type of the attachment, for example Patch or Unspecified.

A branch linked to a bug. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Branch Bug # Branch The core bug entry.

Return a list of all IBugNominations for this bug.

The list is ordered by IBugNominations.target.bugtargetdisplayname.

param target:An IProduct or IDistribution. Only nominations for this target are returned.
param nominations:
 The list of nominations to search through. If none is given, the bug's nominations are looked through. This can be useful when having to call this method multiple times, to avoid getting the list of nominations each time.
Nominations to search through. Target

Return HWDB submissions linked to this bug.

return:A sequence of HWDB submissions linked to this bug.
param user:The user making the request.

Only those submissions are returned which the user can access. Public submissions are always included; private submisisons only if the user is the owner or an admin.

Can this bug nominated for this target?

nomination_target:
 An IDistroSeries or IProductSeries.

Returns True or False.

Target

Is this bug eligible for expiration and was it last updated more than X days ago?

If days_old is None the default number of days without activity is used.

Returns True or False.

Number of days of inactivity for which to check.
Rertun the linked to this bug that are visible by user.

Return the IBugNomination for the target.

If no nomination is found, a NotFoundError is raised.

param nomination_target:
 An IDistroSeries or IProductSeries.
Target
Set the visible attribute on a bug comment. This is restricted to Launchpad admins, and will return a HTTP Error 401: Unauthorized error for non-admin callers. Show this comment? The number of the comment in the list of messages.

Attach a file to this bug.

owner:An IPerson.
data:A file-like object, or a str.
description:A brief description of the attachment.
comment:An IMessage or string.
filename:A string.
is_patch:A boolean.

Associate a branch with this bug.

param branch:The branch being linked to.
param registrant:
 The user linking the branch.
Link a HWSubmission to this bug. A HWDB submission Create a new watch for this bug on the given remote bug and bug tracker, owned by the person given as the owner.

Bug System

You can register new bug trackers from the Launchpad Bugs home page.

Remote Bug

The bug number of this bug in the remote bug tracker.

Remove this person's subscription to this bug. Person

Unlink a branch from this bug.

param branch:The branch being unlinked from.
param user:The user unlinking the branch.
Mark :user: as affected by this bug. Does this bug affect you? Create a new message, and link it to this object. Message Subject

Nominate a bug for an IDistroSeries or IProductSeries.

owner:An IPerson.
target:An IDistroSeries or IProductSeries.

This method creates and returns a BugNomination. (See lp.bugs.model.bugnomination.BugNomination.)

Target

Subscribe person to the bug.

param person:the subscriber.
param subscribed_by:
 the person who created the subscription.
param suppress_notify:
 a flag to suppress notify call.
param level:The BugNotificationLevel for the new subscription.
return:an IBugSubscription.
Person Level
Ensure that this CVE is linked to this bug. CVE Ensure that any links between this bug and the given CVE are removed. CVE Remove this person's subscription from all dupes of this bug. Person Is :user: marked as affected by this bug? Create a new bug task on this bug.

Target

The software in which this bug should be fixed.

Remove a link to a HWSubmission. A HWDB submission
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Log of activity that has occurred on this bug. List of bug attachments. BugTasks on this bug, sorted upstream, then by ubuntu, then by other distroseries. All bug watches associated with this bug. Can the Incomplete bug expire? Expiration may happen when the bug permits expiration, and a bugtask cannot be confirmed. CVE entries related to this bug. Date Created Date of last bug message Date Last Updated Date Made Private

Description

A detailed description of the problem,
including the steps required to reproduce it.
Duplicate Of MultiJoin of bugs which are dupes of this one. The 'heat' of the bug Bug ID Date when the most recent patch was uploaded. Branches associated with this bug, usually branches on which this bug is being fixed. The number of comments on this bug The messages related to this object, in reverse order of creation (so newest first).

Nickname

A short and unique name.
Add one only if you often need to retype the URL but have trouble remembering the bug number.
The number of bugs marked as duplicates of this bug The owner's IPerson

This bug report should be private

Private bug reports are visible only to their subscribers.

This bug is a security vulnerability. Subscriptions

Tags

Space-separated keywords for classifying this bug report.

Summary

A one-line summary of the problem.

The number of users affected by this bug (not including duplicates) The number of users affected by this bug (not including duplicates) The number of users affected by this bug (including duplicates) Users affected (including duplicates) Users explicitly marked as unaffected (not including duplicates) The number of users unaffected by this bug

Who Made Private

The person who set this bug private.

Description

A detailed description of the problem,
including the steps required to reproduce it.
Duplicate Of

Nickname

A short and unique name.
Add one only if you often need to retype the URL but have trouble remembering the bug number.

This bug report should be private

Private bug reports are visible only to their subscribers.

This bug is a security vulnerability.

Tags

Space-separated keywords for classifying this bug report.

Summary

A one-line summary of the problem.

An entity which can be linked to bugs.

Examples include an ISpecification.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

A nomination for a bug to be fixed in a specific series.

A nomination can apply to an IDistroSeries or an IProductSeries.

Is this person allowed to approve the nomination?

Decline this bug for fixing in a series.

decliner:The IPerson that declines this nomination.

The status is set to DECLINED.

If called on a nomination that is in APPROVED state, a BugNominationStatusError is raised. If the nomination was already DECLINED, this method is a noop.

Approve this bug for fixing in a series.

approver:The IPerson that approves this nomination and that will own the created bugtasks.

The status is set to APPROVED and the appropriate IBugTask(s) are created for the nomination target.

A nomination in any state can be approved. If the nomination is /already/ approved, this method is a noop.

The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Date Submitted

The date on which this nomination was submitted.

Date Decided

The date on which this nomination was approved or declined.

Decided By Series Submitter Series Status The IProductSeries or IDistroSeries of this nomination.
The IProductSeries or IDistroSeries of this nomination. The relationship between a person and a bug. Can the user unsubscribe the subscriber from the bug? The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Bug Date subscribed

Person

The person's Launchpad ID or e-mail address.

Subscribed by

The person who created this subscription.

A bug subscription filter. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Bug notification level

The volume and type of bug notifications this subscription will generate.

A short description of this filter

Find all tags

If enabled, all tags must match, else at least one tag must match.

The importances interested in (empty for all) The statuses interested in (empty for all) Structural subscription The tags interested in

Bug notification level

The volume and type of bug notifications this subscription will generate.

A short description of this filter

Find all tags

If enabled, all tags must match, else at least one tag must match.

The importances interested in (empty for all) The statuses interested in (empty for all) The tags interested in

An entity on which a bug can be reported.

Examples include an IDistribution, an IDistroSeries and an IProduct.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

A bug needing fixing in a particular product or package. Return the list of possible duplicates for this BugTask. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Assigned to Bug The short, descriptive name of the target The target as presented in mail notifications

Remote Bug Details

Select the bug watch that represents this task in the relevant bug tracker. If none of the bug watches represents this particular bug task, leave it as (None). Linking the remote bug watch with the task in this way means that a change in the remote bug status will change the status of this bug task in Launchpad.

Date Assigned

The date on which this task was assigned to someone.

Date Closed

The date on which this task was marked either Won't Fix, Invalid or Fix Released.

Date Confirmed

The date on which this task was marked Confirmed.

Date Created

The date on which this task was created.

Date Fix Committed

The date on which this task was marked Fix Committed.

Date Fix Released

The date on which this task was marked Fix Released.

Date In Progress

The date on which this task was marked In Progress.

Date Incomplete

The date on which this task was marked Incomplete.

Date left closed

The date on which this task was last reopened.

Date left new

The date on which this task was marked with a status higher than New.

Date Triaged

The date on which this task was marked Triaged.

Importance True or False depending on whether or not there is more work required on this bug task. Milestone The owner IBugTasks related to this one, namely other IBugTasks on the same IBug. Status

Target

The software in which this bug should be fixed.

The title of the bug related to this bugtask
Assigned to

Remote Bug Details

Select the bug watch that represents this task in the relevant bug tracker. If none of the bug watches represents this particular bug task, leave it as (None). Linking the remote bug watch with the task in this way means that a change in the remote bug status will change the status of this bug task in Launchpad.

Importance Milestone Status

Target

The software in which this bug should be fixed.

The software component in the remote bug tracker.

Most bug trackers organize bug reports by the software 'component' they affect. This class provides a mapping of this upstream component to the corresponding source package in the distro.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Component Group

Distribution Source Package

The distribution source package object that should be linked to this component.

Is Visible?

Should the component be shown in the Launchpad web interface?

Name

The name of a software component as shown in Launchpad.

Component Group

Distribution Source Package

The distribution source package object that should be linked to this component.

Is Visible?

Should the component be shown in the Launchpad web interface?

Name

The name of a software component as shown in Launchpad.

A collection of components in a remote bug tracker.

Some bug trackers organize sets of components into higher level groups, such as Bugzilla's 'product'.

Adds a component to be tracked as part of this component group The name of the remote software component to be added
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. BugTracker Components.

Name

The name of the bug tracker product.

BugTracker

Name

The name of the bug tracker product.

A remote bug system.

Launchpadlib example: What bug tracker is used for a distro source package?

product = source_package.upstream_product
if product:
    tracker = product.bug_tracker
    if not tracker:
        project = product.project_group
        if project:
            tracker = project.bug_tracker
if tracker:
    print "%s at %s" %(tracker.bug_tracker_type, tracker.base_url)
Return collection of all component groups for this bug tracker

Retrieve a given component group registered with the bug tracker.

param component_group_name:
 Name of the component group to retrieve.
The name of the remote component group
Adds a new component group to the bug tracker The name of the remote component group
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Updates for this bug tracker are enabled

Location

The top-level URL for the bug tracker, or an upstream email address. This must be accurate so that Launchpad can link to external bug reports.

Location aliases

A list of URLs or email addresses that all lead to the same bug tracker, or commonly seen typos, separated by whitespace.

Bug Tracker Type

Contact details

The contact details for the external bug tracker (so that, for example, its administrators can be contacted about a security breach).

This bug tracker has a Launchpad plugin installed.

Name

A URL-friendly name for the bug tracker, such as "mozilla-bugs".

Owner

Summary

A brief introduction or overview of this bug tracker instance.

Title

A descriptive label for this tracker to show in listings.

The remote watches on this bug tracker.
Updates for this bug tracker are enabled

Location

The top-level URL for the bug tracker, or an upstream email address. This must be accurate so that Launchpad can link to external bug reports.

Location aliases

A list of URLs or email addresses that all lead to the same bug tracker, or commonly seen typos, separated by whitespace.

Bug Tracker Type

Contact details

The contact details for the external bug tracker (so that, for example, its administrators can be contacted about a security breach).

This bug tracker has a Launchpad plugin installed.

Name

A URL-friendly name for the bug tracker, such as "mozilla-bugs".

Owner

Summary

A brief introduction or overview of this bug tracker instance.

Title

A descriptive label for this tracker to show in listings.

A bug on a remote system. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Bug The tasks which this watch will affect. In Launchpad, a bug watch can be linked to one or more tasks, and if it is linked and we notice a status change in the watched bug then we will try to update the Launchpad bug task accordingly.

Bug System

You can register new bug trackers from the Launchpad Bugs home page.

Date Created Last Changed Last Checked Next Check Last Error Type Owner

Remote Bug

The bug number of this bug in the remote bug tracker.

Remote Importance Remote Status Bug watch title The URL at which to view the remote bug.

Bug System

You can register new bug trackers from the Launchpad Bugs home page.

Last Changed Last Checked Next Check Last Error Type

Remote Bug

The bug number of this bug in the remote bug tracker.

Remote Importance Remote Status

Build-slave information and state.

Builder instance represents a single builder slave machine within the Launchpad Auto Build System. It should specify a 'processor' on which the machine is based and is able to build packages for; a URL, by which the machine is accessed through an XML-RPC interface; name, title, description for entity identification and browsing purposes; an LP-like owner which has unrestricted access to the instance; the build slave machine status representation, including the field/properties: virtualized, builderok, status, failnotes and currentjob.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Publicly Visible

Whether or not to present the builder publicly.

Builder State OK

Whether or not the builder is ok

Description

The builder slave description, may be several paragraphs of text, giving the highlights and details.

Failure Notes

The reason for a builder not being ok

Failure Count

Number of consecutive failures for this builder.

Manual Mode

The auto-build system does not dispatch jobs automatically for slaves in manual mode.

Name

Builder Slave Name used for reference proposes

Owner

Builder owner, a Launchpad member which will be responsible for this device.

Title

The builder slave title. Should be just a few words.

URL

The URL to the build machine, used as a unique identifier. Includes protocol, host and port only, e.g.: http://farm.com:8221/

Virtualized

Whether or not the builder is a virtual Xen instance.

Virtual Machine Host

The machine hostname hosting the virtual buildd-slave, e.g.: foobar-host.ppa

Publicly Visible

Whether or not to present the builder publicly.

Builder State OK

Whether or not the builder is ok

Description

The builder slave description, may be several paragraphs of text, giving the highlights and details.

Failure Notes

The reason for a builder not being ok

Failure Count

Number of consecutive failures for this builder.

Manual Mode

The auto-build system does not dispatch jobs automatically for slaves in manual mode.

Name

Builder Slave Name used for reference proposes

Owner

Builder owner, a Launchpad member which will be responsible for this device.

Title

The builder slave title. Should be just a few words.

URL

The URL to the build machine, used as a unique identifier. Includes protocol, host and port only, e.g.: http://farm.com:8221/

Virtualized

Whether or not the builder is a virtual Xen instance.

Virtual Machine Host

The machine hostname hosting the virtual buildd-slave, e.g.: foobar-host.ppa

A code import to a Bazaar Branch.

Request that an import be tried soon.

This method will schedule an import to happen soon for this branch.

The import must be in the Reviewed state, if not then a CodeImportNotInReviewedState error will be thrown. If using the API then a status code of 400 will result.

If the import is already running then a CodeImportAlreadyRunning error will be thrown. If using the API then a status code of 400 will result.

The two cases can be distinguished over the API by seeing if the exception names appear in the body of the response.

If used over the API and the request has already been made then this method will silently do nothing. If called internally then the error_if_already_requested parameter controls whether a CodeImportAlreadyRequested exception will be thrown in that situation.

return:None
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Branch

The Bazaar branch produced by the import system.

Module

The path to import within the repository. Usually, it is the name of the project.

Repository

The CVSROOT. Example: :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome

Last successful

Type of RCS

The version control system to import from. Can be CVS or Subversion.

Review Status

Only reviewed imports are processed.

URL

The URL of the VCS branch.

A link between a merge proposal and a message. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The message as quoted in email. Comment Author The branch merge proposal Date Created

DB ID

The tracking number for this comment.

The body of the code review message. The title of the comment Review Vote tag
The title of the comment Review Vote tag

A reference to a vote on a IBranchMergeProposal.

There is at most one reference to a vote for each reviewer on a given branch merge proposal.

Reassign a pending review to someone else.

Pending reviews can be reassigned to someone else.

param reviewer:The person to assign the pending review to.
raises ReviewNotPending:
 If the review is not pending.
raises ReassignReviewFailed:
 If the reviewer is an individual and already has a personal review.
The person or team to assign to do the review.

Change a pending review into a review for claimant.

Pending team reviews can be claimed by members of that team. This allows reviews to be moved of the general team todo list, and onto a personal todo list.

param claimant:The person claiming the team review.
raises ClaimReviewFailed:
 If the claimant already has a personal review, if the reviewer is not a team, if the claimant is not in the reviewer team, or if the review is not pending.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The merge proposal that is the subject of this vote The code review comment that contains the most recent vote. Date Created Is the pending? The person who originally registered this vote

Review type

Lowercase keywords describing the type of review.

Reviewer

A person who you want to review this.

The merge proposal that is the subject of this vote The code review comment that contains the most recent vote. The person who originally registered this vote

Review type

Lowercase keywords describing the type of review.

Reviewer

A person who you want to review this.

A Commercial Subscription for a Product.

If the product has a license which does not qualify for free hosting, a subscription needs to be purchased.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Date Created

The date the first subscription was applied.

Expiration Date

The expiration date of the subscription.

Date Modified

The date the subscription was modified.

Beginning of Subscription

The date the subscription starts.

Active

Whether this subscription is active.

Product which has commercial subscription

Project for which this commercial subscription is applied.

Purchaser

Person who purchased the voucher.

Registrant

Person who redeemed the voucher.

Expiration Date

The expiration date of the subscription.

Date Modified

The date the subscription was modified.

Beginning of Subscription

The date the subscription starts.

The country description. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Description iso3166code2 iso3166code3 Country name Country title Description Country name Country title A single CVE database entry. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Bugs related to this CVE entry. Date Created Date Modified

Title

A description of the CVE issue. This will be updated regularly from the CVE database.

Display Name

A very brief name describing the ref and state.

CVE Sequence Number

Should take the form XXXX-XXXX, all digits.

Current CVE State

Whether or not the vulnerability has been reviewed and assigned a full CVE number, or is still considered a Candidate, or is deprecated.

Title

A title for the CVE

URL

Return a URL to the site that has the CVE data for this CVE reference.

Date Modified

Title

A description of the CVE issue. This will be updated regularly from the CVE database.

Display Name

A very brief name describing the ref and state.

CVE Sequence Number

Should take the form XXXX-XXXX, all digits.

Current CVE State

Whether or not the vulnerability has been reviewed and assigned a full CVE number, or is still considered a Candidate, or is deprecated.

Title

A title for the CVE

URL

Return a URL to the site that has the CVE data for this CVE reference.

An operating system distribution.

Launchpadlib example: retrieving the current version of a package in a particular distroseries.

ubuntu = launchpad.distributions["ubuntu"]
archive = ubuntu.main_archive
series = ubuntu.current_series
print archive.getPublishedSources(exact_match=True,
    source_name="apport",
    distro_series=series)[0].source_package_version

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Return build records in the context it is implemented.

It excludes build records generated by Gina (imported from a external repository), where IBuild.datebuilt is null and IBuild.buildstate is BuildStatus.FULLYBUILT.

The result is simply not filtered if the optional filters are omitted by call sites.

param build_state:
 optional BuildStatus value for filtering build records;
param name:optional string for filtering build source package name. Sub-string matching is allowed via SQL LIKE.
param pocket:optional PackagePublishingPocket value for filtering build records;
param arch_tag:optional string for filtering build source packages by their architecture tag;
param user:optional IPerson corresponding to the user performing the request. It will filter out build records for which the user have no 'view' permission.
param binary_only:
 optional boolean indicating whether only BinaryPackageBuild objects should be returned, or more general PackageBuild objects (which may include, for example, SourcePackageRecipeBuild objects.
return:a result set containing IPackageBuild records ordered by descending IPackageBuild.date_finished except when builds are filtered by BuildStatus.NEEDSBUILD, in this case records are ordered by descending BuildQueue.lastscore (dispatching order).

Pocket

The pocket into which this entry is published

Build status

The status of this build record

Source package name

Return all the subscriptions with the specified levels.

return:A sequence of IStructuralSubscription.

Return the series with the name or version given.

param name_or_version:
 The IDistroSeries.name or IDistroSeries.version.
Name or version

Return the distribution archive with the given name.

Only distribution archives are considered -- PPAs will not be found.

param name:The name of the archive, e.g. 'partner'
Archive name
Return a DistributionSourcePackage with the given name for this distribution, or None. Package name

Search for source packages that correspond to the given text.

This method just decorates the result of searchSourcePackageCaches() to return DistributionSourcePackages.

Source package name substring match
Is user subscribed, directly or via a team, to bug mail?

Return all commercial PPAs.

Commercial PPAs are private, but explicitly flagged up as commercial so that they are discoverable by people who wish to buy items from them.

Return the country DNS mirror for a country and content type.

Location

The country in which this mirror is based.

Content

Choose "CD Image" if this mirror contains CD images of this distribution. Choose "Archive" if this is a mirror of packages for this distribution.

Return entries in the translation import queue for this entity.

arg import_status:
 RosettaImportStatus DB Schema entry.
arg file_extension:
 String with the file type extension, usually 'po' or 'pot'.

If one of both of 'import_status' or 'file_extension' are given, the returned entries are filtered based on those values.

Filename extension

Show only entries with this filename suffix

Status

Show only entries with this status

Return the mirror with the given name for this distribution or None if it's not found. Name Return the subscription for person, if it exists. Return the DistroSeries which are marked as in development. Return a milestone with the given name for this object, or None. Name Remove tag from the official bug tags of this target. The official bug tag

Add a bug subscription filter for this structure.

This method is used to create a new IBugSubscriptionFilter for the target. It will initially allow all notifications to be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription filter.
Person to subscribe. If omitted, the requesting user will be subscribed.

Add a bug subscription for this structure.

This method is used to create a new IStructuralSubscription for the target. This initially has a single filter which will allow all notifications will be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription.
Person to subscribe. If omitted, the requesting user will be subscribed.

Remove a subscription to bugs from this structure.

This will delete all associated filters.

subscriber:The IPerson who will be unsubscribed. If omitted, unsubscribed_by will be used.
unsubscribed_by:
 The IPerson removing the subscription.
Person to unsubscribe. If omitted, the requesting user will be unsubscribed.
Add tag to the official bug tags of this target. The official bug tag
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Active

Whether or not this item is active.

The visible and active milestones associated with this object, ordered by date expected. All milestones associated with this object, ordered by date expected. All enabled and official ARCHIVE mirrors of this Distribution. A sequence of the distribution's primary, partner and debug archives.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

Bug Supervisor

The Launchpad id of the person or team (preferred) responsible for bug management. Mail about all bug activity will be sent to the supervisor by default. The bug supervisor can change the bug mail rules to limit the volume of email.

All enabled and official RELEASE mirrors of this Distribution.

Current series

The current development series of this distribution. Note that all maintainerships refer to the current series. When people ask about the state of packages in the distribution, we should interpret that query in the context of the currentseries.

Date created

The date this distribution was registered.

This Distribution's derivatives

Description

Details about the distributions's work, highlights, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages. Don't repeat the Summary.

Display Name

The displayable name of the distribution.

Domain name

The distro's domain name.

Driver

The person or team responsible for decisions about features and bugs that will be targeted for any series in this distribution. Note that you can also specify a driver on each series whose permissions will be limited to that specific series.

Homepage Content

The content of this distribution's home page. Edit this and it will be displayed for all the world to see. It is NOT a wiki so you cannot undo changes.

Icon

A small image of exactly 14x14 pixels and at most 5kb in size, that can be used to identify this distribution. The icon will be displayed everywhere we list the distribution and link to it.

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to this distribution. It should be no bigger than 50kb in size.

Distribution Main Archive.

Mirror Administrator

The person or team that has the rights to review and mark this distribution's mirrors as official.

Brand

A large image of exactly 192x192 pixels, that will be displayed on this distribution's home page in Launchpad. It should be no bigger than 100kb in size.

Name

The distro's name.

Official Bug Tags

The list of bug tags defined as official.

Owner

The distro's owner.

Registrant

The distro's registrant.

Security Contact

The Launchpad id of the person or team (preferred) who handles security-related bug reports. The security contact will be subscribed to all bugs marked as a security vulnerability and will receive email about all activity on all security bugs.

DistroSeries inside this Distribution

Summary

A short paragraph to introduce the goals and highlights of the distribution.

Title

The distro's title.

Active

Whether or not this item is active.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

Bug Supervisor

The Launchpad id of the person or team (preferred) responsible for bug management. Mail about all bug activity will be sent to the supervisor by default. The bug supervisor can change the bug mail rules to limit the volume of email.

Current series

The current development series of this distribution. Note that all maintainerships refer to the current series. When people ask about the state of packages in the distribution, we should interpret that query in the context of the currentseries.

Date created

The date this distribution was registered.

Description

Details about the distributions's work, highlights, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages. Don't repeat the Summary.

Display Name

The displayable name of the distribution.

Domain name

The distro's domain name.

Driver

The person or team responsible for decisions about features and bugs that will be targeted for any series in this distribution. Note that you can also specify a driver on each series whose permissions will be limited to that specific series.

Homepage Content

The content of this distribution's home page. Edit this and it will be displayed for all the world to see. It is NOT a wiki so you cannot undo changes.

Icon

A small image of exactly 14x14 pixels and at most 5kb in size, that can be used to identify this distribution. The icon will be displayed everywhere we list the distribution and link to it.

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to this distribution. It should be no bigger than 50kb in size.

Mirror Administrator

The person or team that has the rights to review and mark this distribution's mirrors as official.

Brand

A large image of exactly 192x192 pixels, that will be displayed on this distribution's home page in Launchpad. It should be no bigger than 100kb in size.

Name

The distro's name.

Official Bug Tags

The list of bug tags defined as official.

Owner

The distro's owner.

Security Contact

The Launchpad id of the person or team (preferred) who handles security-related bug reports. The security contact will be subscribed to all bugs marked as a security vulnerability and will receive email about all activity on all security bugs.

Summary

A short paragraph to introduce the goals and highlights of the distribution.

Title

The distro's title.

A mirror of a given distribution. Return True if this is an official mirror. Verify if a mirror can be set as a country mirror or return False.

Return this mirror's overall freshness.

For ARCHIVE mirrors, the overall freshness is the worst freshness of all of this mirror's content objects (MirrorDistroArchSeries, MirrorDistroSeriesSource or MirrorCDImageDistroSeriess).

For RELEASE mirrors, the overall freshness is either UPTODATE, if the mirror contains all ISO images that it should or UNKNOWN if it doesn't contain one or more ISO images.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Content

Choose "CD Image" if this mirror contains CD images of this distribution. Choose "Archive" if this is a mirror of packages for this distribution.

Location

The country in which this mirror is based.

Country DNS Mirror

Whether this is a country mirror in DNS.

Date Created

The date on which this mirror was registered.

Date reviewed

The date on which this mirror was last reviewed by a mirror admin.

Description

Organisation

The name of the organization hosting this mirror.

Distribution

The distribution that is mirrored

This mirror was probed successfully.

FTP URL

e.g.: ftp://archive.ubuntu.com/ubuntu/

HTTP URL

e.g.: http://archive.ubuntu.com/ubuntu/

Name

A short and unique name for this mirror.

Apply to be an official mirror of this distribution

Owner

The person who is set as the current administrator of thismirror.

Reviewer

The person who last reviewed this mirror.

Rsync URL

e.g.: rsync://archive.ubuntu.com/ubuntu/

Link Speed

Status

The current status of a mirror's registration.

Whiteboard

Notes on the current status of the mirror (only visible to admins and the mirror's registrant).

Content

Choose "CD Image" if this mirror contains CD images of this distribution. Choose "Archive" if this is a mirror of packages for this distribution.

Location

The country in which this mirror is based.

Country DNS Mirror

Whether this is a country mirror in DNS.

Description

Organisation

The name of the organization hosting this mirror.

FTP URL

e.g.: ftp://archive.ubuntu.com/ubuntu/

HTTP URL

e.g.: http://archive.ubuntu.com/ubuntu/

Name

A short and unique name for this mirror.

Apply to be an official mirror of this distribution

Owner

The person who is set as the current administrator of thismirror.

Rsync URL

e.g.: rsync://archive.ubuntu.com/ubuntu/

Link Speed

Status

The current status of a mirror's registration.

Whiteboard

Notes on the current status of the mirror (only visible to admins and the mirror's registrant).

Represents a source package in a distribution.

Create IDistributionSourcePackages by invoking IDistribution.getSourcePackage().

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Bug tasks on this source package, sorted newest first.

If needed, you can limit the number of bugtasks you are interested in using the quantity parameter.

The maximum number of bug tasks to return

Returns all merge proposals of a given status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
returns:A list of IBranchMergeProposal.
A list of merge proposal statuses to filter by.

Return all the subscriptions with the specified levels.

return:A sequence of IStructuralSubscription.

Returns all branches with the given lifecycle status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
param modified_since:
 If set, filters the branches being returned to those that have been modified since the specified date/time.
param eager_load:
 If True load related objects for the whole collection.
returns:A list of IBranch.
Limit the branches to those modified since this date. A list of branch lifecycle statuses to filter by.
Is user subscribed, directly or via a team, to bug mail? Return the subscription for person, if it exists.

Add a bug subscription for this structure.

This method is used to create a new IStructuralSubscription for the target. This initially has a single filter which will allow all notifications will be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription.
Person to subscribe. If omitted, the requesting user will be subscribed.

Remove a subscription to bugs from this structure.

This will delete all associated filters.

subscriber:The IPerson who will be unsubscribed. If omitted, unsubscribed_by will be used.
unsubscribed_by:
 The IPerson removing the subscription.
Person to unsubscribe. If omitted, the requesting user will be unsubscribed.

Add a bug subscription filter for this structure.

This method is used to create a new IBugSubscriptionFilter for the target. It will initially allow all notifications to be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription filter.
Person to subscribe. If omitted, the requesting user will be subscribed.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

Display name for this package. The distribution. The source package name as text

Official Bug Tags

The list of bug tags defined as official.

Title for this package. The upstream product to which this package is linked.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

The distribution.
DistroArchSeries Table Interface The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Architecture Tag

The architecture tag, or short piece of text that identifies this architecture. All binary packages in the archive will use this tag in their filename. Please get it correct. It should really never be changed!

Build chroot URL

The URL to the current build chroot for this distroarchseries.

Display name

The display name of this distroarchseries.

The context distroseries

Is Nominated Arch Independent

True if this distroarchseries is the NominatedArchIndep one.

Main Archive

The main archive of the distroarchseries.

Official Support

Indicate whether or not this port has official support from the vendor of the distribution.

The person who registered this port.

Package Count

A cache of the number of packages published in the RELEASE pocket of this port.

PPA support available

Indicate whether or not this port has support for building PPA packages.

Title

The title of this distroarchseries.

Architecture Tag

The architecture tag, or short piece of text that identifies this architecture. All binary packages in the archive will use this tag in their filename. Please get it correct. It should really never be changed!

Display name

The display name of this distroarchseries.

The context distroseries

Is Nominated Arch Independent

True if this distroarchseries is the NominatedArchIndep one.

Main Archive

The main archive of the distroarchseries.

Official Support

Indicate whether or not this port has official support from the vendor of the distribution.

The person who registered this port.

Package Count

A cache of the number of packages published in the RELEASE pocket of this port.

PPA support available

Indicate whether or not this port has support for building PPA packages.

Title

The title of this distroarchseries.

A comment for a distroseries difference record. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Comment text

The comment text for the related distro series difference.

The author of the comment. Comment date.

Source package name

Name of the source package that this comment is for.

An interface for a package difference between two distroseries.

Blacklist this version or all versions of this source package and adds a comment on this difference.

param commenter:
 The requestor IPerson.
param comment:The comment string.
param all:Indicates whether all versions of this package should be blacklisted or just the current (default).
return:The created DistroSeriesDifferenceComment object.
Comment text All

Removes this difference from the blacklist and adds a comment on this difference.

The status will be updated based on the versions.

param commenter:
 The requestor IPerson.
param comment:The comment string.
return:The created DistroSeriesDifferenceComment object.
Comment text

Requests IPackageDiffs for the derived and parent version.

raises DistroSeriesDifferenceError:
 When package diffs cannot be requested.
Add a comment on this difference. Comment text
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Base version

The common base version of the package for differences with different versions in the parent and derived series.

Derived series

The distribution series which identifies the derived series with the difference.

Package diff status

The status of the diff between the base version and the derived version.

Package diff url

The url for the diff between the base version and the derived version.

Parent package diff status

The status of the diff between the base version and the parent version.

Parent package diff url

The url for the diff between the base version and the parent version.

Parent series

The distribution series which identifies the parent series with the difference.

Parent source version

The version of the most recent source publishing in the parent series.

Source version

The version of the most recent source publishing in the derived series.

Source Package Name

Distro series difference status.

The current status of this difference.

A series of an operating system distribution.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Return build records in the context it is implemented.

It excludes build records generated by Gina (imported from a external repository), where IBuild.datebuilt is null and IBuild.buildstate is BuildStatus.FULLYBUILT.

The result is simply not filtered if the optional filters are omitted by call sites.

param build_state:
 optional BuildStatus value for filtering build records;
param name:optional string for filtering build source package name. Sub-string matching is allowed via SQL LIKE.
param pocket:optional PackagePublishingPocket value for filtering build records;
param arch_tag:optional string for filtering build source packages by their architecture tag;
param user:optional IPerson corresponding to the user performing the request. It will filter out build records for which the user have no 'view' permission.
param binary_only:
 optional boolean indicating whether only BinaryPackageBuild objects should be returned, or more general PackageBuild objects (which may include, for example, SourcePackageRecipeBuild objects.
return:a result set containing IPackageBuild records ordered by descending IPackageBuild.date_finished except when builds are filtered by BuildStatus.NEEDSBUILD, in this case records are ordered by descending BuildQueue.lastscore (dispatching order).

Pocket

The pocket into which this entry is published

Build status

The status of this build record

Source package name

Return all the subscriptions with the specified levels.

return:A sequence of IStructuralSubscription.

Get package upload records for this distribution series.

param status:Filter results by this PackageUploadStatus, or list of statuses.
param created_since_date:
 If specified, only returns items uploaded since the timestamp supplied.
param archive:Filter results for this IArchive.
param pocket:Filter results by this PackagePublishingPocket or a list of PackagePublishingPocket.
param custom_type:
 Filter results by this PackageUploadCustomFormat.
param name:Filter results by this file name or package name.
param version:Filter results by this version number string.
param exact_match:
 If True, look for exact string matches on the name and version filters. If False, look for a substring match so that e.g. a package "kspreadsheetplusplus" would match the search string "spreadsheet". Defaults to False.
return:A result set containing IPackageUpload.

Pocket

Return only items targeted to this pocket

Package Upload Status

Return only items that have this status.

Created Since Timestamp

Return items that are more recent than this timestamp.

Archive

Return only items for this archive.

Custom Type

Return only items with custom files of this type.

Get all DistroSeries derived from this one.

Return a source package in this distro series by name.

The name given may be a string or an ISourcePackageName-providing object. The source package may not be published in the distro series.

The name of the source package
Is user subscribed, directly or via a team, to bug mail? Return the distroarchseries for this distroseries with the given architecturetag. The architecture tag

Return an iterator over all its translation templates.

The returned templates are either obsolete or current.

return:A sequence of IPOTemplate.

Return entries in the translation import queue for this entity.

arg import_status:
 RosettaImportStatus DB Schema entry.
arg file_extension:
 String with the file type extension, usually 'po' or 'pot'.

If one of both of 'import_status' or 'file_extension' are given, the returned entries are filtered based on those values.

Filename extension

Show only entries with this filename suffix

Status

Show only entries with this status

Return the subscription for person, if it exists. Get all parent DistroSeries.

Add a bug subscription filter for this structure.

This method is used to create a new IBugSubscriptionFilter for the target. It will initially allow all notifications to be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription filter.
Person to subscribe. If omitted, the requesting user will be subscribed.

Initialize this series from parents.

This method performs checks and then creates a job to populate the new distroseries.

param parents:The list of parent ids this series will derive from.
param architectures:
 The architectures to copy to the derived series. If not specified, all of the architectures are copied.
param packagesets:
 The packagesets to copy to the derived series. If not specified, all of the packagesets are copied.
param rebuild:Whether binaries will be copied to the derived series. If it's true, they will not be, and if it's false, they will be.
param overlays:A list of booleans indicating, for each parent, if the parent/child relationship should be an overlay.
param overlay_pockets:
 The list of pockets names to use for overlay relationships.
param overlay_components:
 The list of components names to use for overlay relationships.
The list of overlay pockets. The list of overlay components. If binaries will be copied to the derived distroseries. The list of parents to derive from. The list of architectures to copy to the derived distroseries. The list of packagesets to copy to the derived distroseries The list of booleans indicating, for each parent, if the parent/child relationship should be an overlay.

Add a bug subscription for this structure.

This method is used to create a new IStructuralSubscription for the target. This initially has a single filter which will allow all notifications will be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription.
Person to subscribe. If omitted, the requesting user will be subscribed.

Remove a subscription to bugs from this structure.

This will delete all associated filters.

subscriber:The IPerson who will be unsubscribed. If omitted, unsubscribed_by will be used.
unsubscribed_by:
 The IPerson removing the subscription.
Person to unsubscribe. If omitted, the requesting user will be unsubscribed.
Create a new milestone for this DistroSeries.

Date Targeted

Example: 2005-11-24

Name

Only letters, numbers, and simple punctuation are allowed.

Code name

An alternative name for the milestone.

Summary

A summary of the features and status of this milestone.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Active

Whether or not this series is stable and supported, or under current development. This excludes series which are experimental or obsolete.

The visible and active milestones associated with this object, ordered by date expected. All milestones associated with this object, ordered by date expected. All architectures in this series.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

E-mail changes to

The mailing list or other e-mail address that Launchpad should notify about new uploads.

The series component names The date this series was registered. Date released

Description

A detailed description of this series, with information on the architectures covered, the availability of security updates and any other relevant information.

Display name

The series displayname.

Distribution

The distribution for which this is a series.

Driver

The person or team responsible for decisions about features and bugs that will be targeted to this series of the distribution.

A list of the people or teams who are drivers for this series. This list is made up of any drivers or owners from this series and the parent drivers.

Series full name

The series full name, e.g. Ubuntu Warty

Include long descriptions in Packages rather than in Translation-en

If True, write long descriptions to the per-architecture Packages files; if False, write them to a Translation-en file common across architectures instead. Using a common file reduces the bandwidth footprint of enabling multiarch on clients, which requires downloading Packages files for multiple architectures.

Distribution Main Archive

Name

The name of this series.

Official Bug Tags

The list of bug tags defined as official.

Owning team of the derived series

This attribute mirrors the owner of the distribution.

Parent series

The series from which this one was branched.

Registrant Status The series pocket names

Summary

A single paragraph that explains the goals of of this series and the intended users. For example: "The 2.0 series of Apache represents the current stable series, and is recommended for all new deployments".

Supported

Whether or not this series is currently supported.

Title

The title of this series. It should be distinctive and designed to look good at the top of a page.

Version

The version string for this series.

Active

Whether or not this series is stable and supported, or under current development. This excludes series which are experimental or obsolete.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

E-mail changes to

The mailing list or other e-mail address that Launchpad should notify about new uploads.

The date this series was registered. Date released

Description

A detailed description of this series, with information on the architectures covered, the availability of security updates and any other relevant information.

Display name

The series displayname.

Distribution

The distribution for which this is a series.

Driver

The person or team responsible for decisions about features and bugs that will be targeted to this series of the distribution.

Series full name

The series full name, e.g. Ubuntu Warty

Include long descriptions in Packages rather than in Translation-en

If True, write long descriptions to the per-architecture Packages files; if False, write them to a Translation-en file common across architectures instead. Using a common file reduces the bandwidth footprint of enabling multiarch on clients, which requires downloading Packages files for multiple architectures.

Distribution Main Archive

Name

The name of this series.

Registrant Status

Summary

A single paragraph that explains the goals of of this series and the intended users. For example: "The 2.0 series of Apache represents the current stable series, and is recommended for all new deployments".

Supported

Whether or not this series is currently supported.

Title

The title of this series. It should be distinctive and designed to look good at the top of a page.

Version

The version string for this series.

The object that stores the IPerson's emails. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Email Address Person Person OpenPGP support The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. User Fingerprint OpenPGP key ID Hardware database application application root.

Return the known vendor IDs for the given bus.

param bus:A HWBus value.
return:A list of strings with vendor IDs fr this bus,
A Device Bus.

Return the submissions matiching the given parmeters.

param user:The IPerson running the query. Private submissions are returned only if the person running the query is the owner or an admin.
param device:Limit results to submissions containing this IHWDevice.
param driver:Limit results to submissions containing devices that use this IHWDriver.
param distribution:
 Limit results to submissions made for this IDistribution.
param distroseries:
 Limit results to submissions made for this IDistroSeries.
param architecture:
 Limit results to submissions made for a specific architecture.
param owner:Limit results to submissions from this person.
param created_before:
 Exclude results created after this date.
param created_after:
 Exclude results created before or on this date.
param submitted_before:
 Exclude results submitted after this date.
param submitted_after:
 Exclude results submitted before or on this date.

Only one of :distribution: or :distroseries: may be supplied.

Created After

If specified, Exclude results submitted before or on this date.

A Distribution Series

If specified, the result set is limited to submissions made for the given distribution series.

A Driver

If specified, the result set is limited to submissions containing devices that use this driver.

A Device

If specified, the result set is limited to submissions containing this device.

Created Before

If specified, exclude results submitted after this date.

A processor architecture

If specified, the result set is limited to sumbissions made for a specific architecture.

Created After

If specified, exclude results created before or on this date.

Person

If specified, the result set is limited to sumbissions from this person.

A Distribution

If specified, the result set is limited to submissions made for this distribution.

Created Before

If specified, exclude results created after this date.

Count the number of submissions mentioning a device or a driver.

Returns a dictionary {'submissions_with_device: n1, 'all_submissions': n2}, where submissions_with_device is the number of submissions having the given device or driver and matching the distro target criterion and where all_submissions is the number of submissions matching the distro target criterion.

param bus:The HWBus of the device (optional).
param vendor_id:
 The vendor ID of the device (optional).
param product_id:
 The product ID of the device (optional).
param driver_name:
 The name of the driver used for the device (optional).
param package_name:
 The name of the package the driver is a part of. (optional).
param distribution:
 Limit the count to submissions made for the given distribution, distroseries or distroarchseries. (optional).
param distroseries:
 Limit the count to submissions made for the given distroseries. (optional).
param distroarchseries:
 Limit the count to submissions made for the given distroarchseries. (optional).

You may specify at most one of the parameters distribution, distroseries or distroarchseries.

At least each of bus, vendor_id, product_id must not be None or driver_name must not be None.

The product ID

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

A package name

If specified, the count is limited to devices controlled by a driver from this package.

The device bus

A Distribution Series

If specified, the result set is limited to submissions made for the given distribution series.

The vendor ID

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

A driver name

If specified, the count is limited to devices controlled by this driver.

A Distribution

If specified, the result set is limited to submissions made for this distribution.

A Distribution Series

If specified, the result set is limited to submissions made for the given distroarchseries.

The number of people owning a device or using a driver.

Returns a dictionary {'owners': n1, 'all_submitters': n2} where owners is the number of people who made a HWDB submission containing the given device or driver, optionally limited to submissions made for the given distro target. all_submitters is the number of persons who made a HWDB submission, optionally limited to submission made on the given distro target installation.

param bus:The HWBus of the device (optional).
param vendor_id:
 The vendor ID of the device (optional).
param product_id:
 The product ID of the device (optional).
param driver_name:
 The name of the driver used for the device (optional).
param package_name:
 The name of the package the driver is a part of. (optional).
param distribution:
 Limit the count to submissions made for the given distribution, distroseries or distroarchseries. (optional).
param distroseries:
 Limit the count to submissions made for the given distroseries. (optional).
param distroarchseries:
 Limit the count to submissions made for the given distroarchseries. (optional).

You may specify at most one of the parameters distribution, distroseries or distroarchseries.

At least each of bus, vendor_id, product_id must not be None or driver_name must not be None.

The product ID

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

A package name

If specified, the count is limited to devices controlled by a driver from this package.

The device bus

A Distribution Series

If specified, the result set is limited to submissions made for the given distribution series.

The vendor ID

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

A driver name

If specified, the count is limited to devices controlled by this driver.

A Distribution

If specified, the result set is limited to submissions made for this distribution.

A Distribution Series

If specified, the result set is limited to submissions made for the given distroarchseries.

Return the set of drivers.

The name of the driver.

If name is omitted, all driver records are returned, optionally limited to those matching the parameter package_name.

The name of the package containing the driver.

If package_name is omitted, all driver records returned, optionally limited to those matching the parameter name. If package_name is (empty string), those records are returned where package_name is or None.

Return the set of devices. The device bus

The vendor ID

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

The product ID

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Count how often a device or a driver appears in HWDB submissions.

return:The number how often the given device appears in HWDB submissions.
param bus:The HWBus of the device (optional).
param vendor_id:
 The vendor ID of the device (optional).
param product_id:
 The product ID of the device (optional).
param driver_name:
 Limit the count to devices controlled by the given driver (optional).
param package_name:
 Limit the count to devices controlled by a driver from the given package (optional).
param distribution:
 Limit the count to submissions made for the given distribution, distroseries or distroarchseries. (optional).
param distroseries:
 Limit the count to submissions made for the given distroseries. (optional).
param distroarchseries:
 Limit the count to submissions made for the given distroarchseries. (optional).

You may specify at most one of the parameters distribution, distroseries or distroarchseries.

At least each of bus, vendor_id, product_id must not be None or driver_name must not be None.

The product ID

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

A package name

If specified, the count is limited to devices controlled by a driver from this package.

The device bus

A Distribution Series

If specified, the result set is limited to submissions made for the given distribution series.

The vendor ID

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

A driver name

If specified, the count is limited to devices controlled by this driver.

A Distribution

If specified, the result set is limited to submissions made for this distribution.

A Distribution Series

If specified, the result set is limited to submissions made for the given distroarchseries.

Return a list of owners and devices related to given bugs.

Actually returns a list of tuples where the tuple is of the form, (person name, bus name, vendor id, product id).`

param bug_ids:A sequence of bug IDs for which affected are looked up.
param bug_tags:A sequence of bug tags
param affected_by_bug:
 If True, those persons are looked up that have marked themselves as being affected by a one of the bugs matching the bug criteria.
param subscribed_to_bug:
 If True, those persons are looked up that are subscribed to a bug matching one of the bug criteria.
param user:The person making the query.

Search for users affected by a bug

If true, those device owners are looked up which are affected by one of the selected bugs.

A set of bug IDs

Search for devices and their owners related to bugs with these IDs.

A set of bug tags

Search for devices and their owners related to bugs having one of these tags.

Search for users who subscribed to a bug

If true, those device owners are looked up which to one of the selected bugs.

Return persons affected by given bugs and owning a given device.

param bus:The HWBus of the device.
param vendor_id:
 The vendor ID of the device.
param product_id:
 The product ID of the device.
param driver_name:
 Limit the search to devices controlled by the given driver.
param package_name:
 Limit the search to devices controlled by a driver from the given package.
param bug_ids:A sequence of bug IDs for which affected are looked up.
param bug_tags:A sequence of bug tags
param affected_by_bug:
 If True, those persons are looked up that have marked themselves as being affected by a one of the bugs matching the bug criteria.
param subscribed_to_bug:
 If True, those persons are looked up that are subscribed to a bug matching one of the bug criteria.
param user:The person making the query.

bug_ids must be a non-empty sequence of bug IDs, or bug_tags must be a non-empty sequence of bug tags.

The parameters bus, vendor_id, product_id must not be None, or driver_name must not be None.

By default, only those persons are returned which have reported a bug matching the given bug conditions.

Owners of private submissions are returned only if user is the owner of the private submission or if user is an admin.

The product ID

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

A package name

If specified, the search is limited to devices controlled by a driver from this package.

The device bus

The vendor ID

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for users who subscribed to a bug

If true, those device owners are looked up which to one of the selected bugs.

Search for users affected by a bug

If true, those device owners are looked up which are affected by one of the selected bugs.

A driver name

If specified, the search is limited to devices controlled by this driver.

A set of bug IDs

Search submitters, subscribers or affected users of bugs with these IDs.

A set of bug tags

Search submitters, subscribers or affected users of bugs having one of these tags.

The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Driver Names

All known distinct driver names appearing in HWDriver

Package Names

All known distinct package names appearing in HWDriver.

The capabilities of a device. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The main class of this device The sub class of this device Core information to identify a device.

List all submissions which mention this device.

param driver:Limit results to devices that use the given IHWDriver.
param distribution:
 Limit results to submissions for this IDistribution.
param distroseries:
 Limit results to submissions for this IDistroSeries.
param architecture:
 Limit results to submissions for this architecture.
param owner:Limit results to submissions from this person.

Only submissions matching all given criteria are returned. Only one of :distribution: or :distroseries: may be supplied.

The owner of this submission

A Distribution

If specified, the result set is limited to sumbissions made for the given distribution.

A driver used for this device in a submission

If specified, the result set is limited to sumbissions made for the given distribution, distroseries or distroarchseries.

A Distribution Series

If specified, the result set is limited to sumbissions made for the given distribution series.

A processor architecture

If specified, the result set is limited to submissions made for the given architecture.

Return an IHWDeviceClass record or create a new one.

param main_class:
 The main class to be added.
param sub_class:
 The sub-class to added (otpional).
return:An IHWDeviceClass record.

main_class and sub_class are integers specifying the class of the device, or, in the case of USB devices, the class of an interface.

IHWDeviceClass records must be unique; if this method is called to create a new record with data of an already existing record, the existing record is returned.

The main class of this device The sub class of this device

Add an IHWDeviceClass record.

param main_class:
 The main class to be added.
param sub_class:
 The sub-class to added.
The main class of this device The sub class of this device
The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The bus of the device.

The product identifier of the device

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

The device classes this device belongs to. The IHWDriver records related to this device. Device ID The human readable name of the device. A string that distiguishes different devices with identical vendor/product IDs

The vendor iD.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

The vendor name.

The product identifier of the device

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

The human readable name of the device. A string that distiguishes different devices with identical vendor/product IDs
Information about a device driver.

List all submissions which mention this driver.

param distribution:
 Limit results to submissions for this IDistribution.
param distroseries:
 Limit results to submissions for this IDistroSeries.
param architecture:
 Limit results to submissions for this architecture.
param owner:Limit results to submissions from this person.

Only submissions matching all given criteria are returned. Only one of :distribution: or :distroseries: may be supplied.

The owner of this submission

A Distribution

If specified, the result set is limited to sumbissions made for the given distribution.

A Distribution Series

If specified, the result set is limited to sumbissions made for the given distribution series.

A processor architecture

If specified, the result set is limited to sumbissions made for the given architecture.

The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Driver ID License of the Driver

Driver Name

The name of the driver written without spaces in lowercase letters and numbers.

Package Name

The name of the package written without spaces in lowercase letters and numbers.

License of the Driver

Driver Name

The name of the driver written without spaces in lowercase letters and numbers.

Package Name

The name of the package written without spaces in lowercase letters and numbers.

A driver name as appearing in IHWDriver. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Driver Name

The name of a driver as it appears in IHWDriver.

A driver name as appearing in IHWDriver. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Package Name

The name of a package as it appears in IHWDriver.

Link a submission to a IHWDeviceDriver row. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The device The driver used for this device in this submission The ID of the HAL node of this device in the submitted data HWSubmissionDevice ID The device The driver used for this device in this submission The ID of the HAL node of this device in the submitted data

Raw submission data for the hardware database.

See doc/hwdb.txt for details about the attributes.

The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Contactable Date Created Date Submitted The HWSubmissionDevice records for this submission. Format Version The owner of this submission Private Submission The raw submission data Submission Status Unique Submission ID Private Submission A list of vendor IDs for different busses associated with vendor names. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The bus that connects a device to a computer The Database ID Vendor ID The bus that connects a device to a computer Vendor ID An entity which has a collection of bug tasks.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. An interface for classes providing milestones. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The visible and active milestones associated with this object, ordered by date expected. All milestones associated with this object, ordered by date expected.

An entity that has a translation import queue.

Examples include ProductSeries, SourcePackage, DistroSeries, and Person.

Return entries in the translation import queue for this entity.

arg import_status:
 RosettaImportStatus DB Schema entry.
arg file_extension:
 String with the file type extension, usually 'po' or 'pot'.

If one of both of 'import_status' or 'file_extension' are given, the returned entries are filtered based on those values.

Filename extension

Show only entries with this filename suffix

Status

Show only entries with this status

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. A person's nickname on an IRC network. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. IRC network Nickname Owner IRC network Nickname Jabber specific user ID The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. New Jabber user ID Owner New Jabber user ID A Language. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The ISO 639 code The English name

Plural form expression

The expression that relates a number of items to the appropriate plural form.

Number of plural forms

The number of plural forms this language has.

Text direction

The direction of text in this language.

Total number of translators for this language.

Visible

Whether this language is visible by default.

The ISO 639 code The English name

Plural form expression

The expression that relates a number of items to the appropriate plural form.

Number of plural forms

The number of plural forms this language has.

Text direction

The direction of text in this language.

Visible

Whether this language is visible by default.

A message.

This is like an email (RFC822) message, though it could be created through the web as well.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. A list of BugAttachments connected to this message. All the text/plain chunks joined together as a unicode string. Date Created Person Parent Subject All the text/plain chunks joined together as a unicode string. A milestone, or a targeting point for bugs and other release-management items that need coordination.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Return all the subscriptions with the specified levels.

return:A sequence of IStructuralSubscription.
Is user subscribed, directly or via a team, to bug mail? Return the subscription for person, if it exists.

Add a bug subscription for this structure.

This method is used to create a new IStructuralSubscription for the target. This initially has a single filter which will allow all notifications will be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription.
Person to subscribe. If omitted, the requesting user will be subscribed.

Remove a subscription to bugs from this structure.

This will delete all associated filters.

subscriber:The IPerson who will be unsubscribed. If omitted, unsubscribed_by will be used.
unsubscribed_by:
 The IPerson removing the subscription.
Person to unsubscribe. If omitted, the requesting user will be unsubscribed.

Create a new ProductRelease.

param owner:IPerson object who manages the release.
param datereleased:
 Date of the product release.
param changelog:
 Detailed changes in each version.
param release_notes:
 Overview of changes in each version.
returns:IProductRelease object.

Date released

The date this release was published. Before release, this should have an estimated release date.

Release notes

A description of important new features (though the changelog below might repeat some of this information).

Changelog

A description of every change in the release.

Add a bug subscription filter for this structure.

This method is used to create a new IBugSubscriptionFilter for the target. It will initially allow all notifications to be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription filter.
Person to subscribe. If omitted, the requesting user will be subscribed.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Code name

An alternative name for the milestone.

Date Targeted

Example: 2005-11-24

Active

Whether or not this milestone should be shown in web forms for bug targeting.

Name

Only letters, numbers, and simple punctuation are allowed.

Official Bug Tags

The list of bug tags defined as official.

The release for this milestone. The productseries or distroseries of this milestone.

Summary

A summary of the features and status of this milestone.

The product or distribution of this milestone. A milestone context title for pages.

Code name

An alternative name for the milestone.

Date Targeted

Example: 2005-11-24

Active

Whether or not this milestone should be shown in web forms for bug targeting.

Name

Only letters, numbers, and simple punctuation are allowed.

The productseries or distroseries of this milestone.

Summary

A summary of the features and status of this milestone.

The product or distribution of this milestone.
A translation file. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The translation file id. A translation template. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Template is active

If unchecked, people can no longer change the template's translations.

Date for last update

Description

Please provide a brief description of the content of this translation template, for example, telling translators if this template contains strings for end-users or other developers.

Include translations for this template in language packs?

Check this box if this template is part of a language pack so its translations should be exported that way.

File format for the source file The translation template id. The number of languages for which we have translations. The number of translation messages for this template.

Template name

The name of this PO template, for example 'evolution-2.2'. Each translation template has a unique name in its package. It's important to get this correct, because Launchpad will recommend alternative translations based on the name.

Owner

The owner of the template in Launchpad can edit the template and change it's status, and can also upload new versions of the template when a new release is made or when the translation strings have been changed during development.

Path of the template in the source tree, including filename.

Priority

A number that describes how important this template is. Often there are multiple templates, and you can use this as a way of indicating which are more important and should be translated first. Pick any number - higher priority templates will generally be listed first.

Translation domain

The translation domain for a translation template. Used with PO file format when generating MO files for inclusion in language pack or MO tarball exports.

All translation files that exist for this template.

Template is active

If unchecked, people can no longer change the template's translations.

Date for last update

Description

Please provide a brief description of the content of this translation template, for example, telling translators if this template contains strings for end-users or other developers.

Include translations for this template in language packs?

Check this box if this template is part of a language pack so its translations should be exported that way.

File format for the source file

Template name

The name of this PO template, for example 'evolution-2.2'. Each translation template has a unique name in its package. It's important to get this correct, because Launchpad will recommend alternative translations based on the name.

Owner

The owner of the template in Launchpad can edit the template and change it's status, and can also upload new versions of the template when a new release is made or when the translation strings have been changed during development.

Path of the template in the source tree, including filename.

Priority

A number that describes how important this template is. Often there are multiple templates, and you can use this as a way of indicating which are more important and should be translated first. Pick any number - higher priority templates will generally be listed first.

Translation domain

The translation domain for a translation template. Used with PO file format when generating MO files for inclusion in language pack or MO tarball exports.

A Queue item for the archive uploader. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Archive

The archive for this upload.

Custom File URLs

Librarian URLs for all the custom files attached to this upload.

Date created

The date this package upload was done.

Architectures related to this item Generic displayname for a queue item This item's displayable source package version

Series

The distroseries targeted by this upload.

The pocket

The pocket targeted by this upload.

Queue status

The status of this upload.

Date created

The date this package upload was done.

Series

The distroseries targeted by this upload.

The pocket

The pocket targeted by this upload.

An interface for package sets.

Get all other package sets in this set's PackagesetGroup.

Returns all package sets that are related to this one, but not this one itself.

return:A (potentially empty) sequence of IPackageset instances.

Get all package sets that are included by this one.

Return all package sets that are directly or indirectly included by this one.

param direct_inclusion:
 if this flag is set to True only sets directly included by this one will be considered.
return:A (potentially empty) sequence of IPackageset instances.

Get source package names also included by another package set.

What source package names does this package set have in common with the other_package_set?

Please note: this method was mainly introduced in order to facilitate the listing of source package names via the LP web services API. It returns string names as opposed to ISourcePackageName instances.

param other_package_set:
 the other package set
param direct_inclusion:
 if this flag is set to True only directly included sources will be considered.
return:A (potentially empty) sequence of string source package names.
The package set we are comparing to.

Get all source names associated with this package set.

This method returns the source package names that are directly or indirectly associated with the package set at hand. Indirect associations may be defined through package set successors.

Please note: this method was mainly introduced in order to facilitate the listing of source package names via the LP web services API. It returns string names as opposed to ISourcePackageName instances.

param direct_inclusion:
 if this flag is set to True only sources directly included by this package set will be considered.
return:A (potentially empty) sequence of string source package names.

Get all package sets that include this one.

Return all package sets that directly or indirectly include this one.

param direct_inclusion:
 if this flag is set to True only sets directly including this one will be considered.
return:A (potentially empty) sequence of IPackageset instances.

Get source package names not included by another package set.

Which source package names included by this package are not included by the other_package_set?

Please note: this method was mainly introduced in order to facilitate the listing of source package names via the LP web services API. It returns string names as opposed to ISourcePackageName instances.

param other_package_set:
 the other package set
param direct_inclusion:
 if this flag is set to True only directly included sources will be considered.
return:A (potentially empty) sequence of string source package names.
The package set we are comparing to.

Remove the named package subsets from this package set.

Only package subsets directly included by this package set can be removed. Any others will be ignored.

This method facilitates the removal of package subsets via the LP web services API. It takes string names as opposed to IPackageset instances.

param names:an iterable with string package set names
A list of package set names.

Remove the named source packages from this package set.

Only source package names directly included by this package set can be removed. Any others will be ignored.

This method facilitates the removal of source package names from package sets via the LP web services API. It takes string names as opposed to ISourcePackageName instances.

param names:an iterable with string source package names
A list of source package names.

Add the named package sets as subsets to this package set.

Any passed source package names will become directly associated with the package set at hand.

This function is idempotent in the sense that package subsets that are already directly associated with a package set will be ignored.

This method facilitates the addition of package subsets via the LP web services API. It takes string names as opposed to IPackageset instances.

param names:an iterable with string package set names
A list of package set names.

Add the named source packages to this package set.

Any passed source package names will become directly associated with the package set at hand.

This function is idempotent in the sense that source package names that are already directly associated with a package set will be ignored.

This method facilitates the addition of source package names to package sets via the LP web services API. It takes string names as opposed to ISourcePackageName instances. Non-existing source package names will be ignored.

param names:an iterable with string source package names
A list of source package names.
The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Date Created

The creation date/time for the package set at hand.

Description

The description for the package set at hand.

Distribution series

The distroseries to which this package set is related.

ID Valid package set name

Person

The person who owns this package set.

Valid package set name A Person.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Returns all merge proposals of a given status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
returns:A list of IBranchMergeProposal.
A list of merge proposal statuses to filter by.

Returns all branches with the given lifecycle status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
param modified_since:
 If set, filters the branches being returned to those that have been modified since the specified date/time.
param eager_load:
 If True load related objects for the whole collection.
returns:A list of IBranch.
Limit the branches to those modified since this date. A list of branch lifecycle statuses to filter by.

Return entries in the translation import queue for this entity.

arg import_status:
 RosettaImportStatus DB Schema entry.
arg file_extension:
 String with the file type extension, usually 'po' or 'pot'.

If one of both of 'import_status' or 'file_extension' are given, the returned entries are filtered based on those values.

Filename extension

Show only entries with this filename suffix

Status

Show only entries with this status

Return a PPA with the given name if it exists.

param name:A string with the exact name of the ppa being looked up.
raises:NoSuchPPA if a suitable PPA could not be found.
return:a PPA IArchive record corresponding to the name.

Returns merge proposals where a person was asked to review.

This does not include merge proposals that were requested from teams that the person is part of. If status is not passed then it will return proposals that are in the "Needs Review" state.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
returns:A list of IBranchMergeProposal.
A list of merge proposal statuses to filter by.

Return the people whose membership on this team match :status:.

If no orderby is provided, Person.sortingColumns is used.

The state of this membership
Return the person's recipe with the given name.

Return private archive URLs that this person can see.

For each of the private archives (PPAs) that this person can see, return a URL that includes the HTTP basic auth data. The URL returned is suitable for including in a sources.list file.

Return the packages for which this person is a bug subscriber.

Returns a list of IDistributionSourcePackage's, ordered alphabetically (A to Z) by name.

Add the given person as a member of this team.

param person:If the given person is already a member of this team we'll simply change its membership status. Otherwise a new TeamMembership is created with the given status.
param reviewer:The user who made the given person a member of this team.
param comment:String that will be assigned to the proponent_comment, reviwer_comment, or acknowledger comment.
param status:TeamMembershipStatus value must be either Approved, Proposed or Admin. If the new member is a team, the status will be changed to Invited unless the user is also an admin of that team.
param force_team_add:
 If the person is actually a team and force_team_add is False, the team will actually be invited to join this one. Otherwise the team is added as if it were a person.
param may_subscribe_to_list:
 If the person is not a team, and may_subscribe_to_list is True, then the person may be subscribed to the team's mailing list, depending on the list status and the person's auto-subscribe settings.
return:A tuple containing a boolean indicating when the membership status changed and the current TeamMembershipStatus. This depends on the desired status passed as an argument, the subscription policy and the user's privileges.
The state of this membership Member

Join the given team if its subscriptionpolicy is not RESTRICTED.

Join the given team according to the policies and defaults of that team:

  • If the team subscriptionpolicy is OPEN, the user is added as an APPROVED member with a NULL TeamMembership.reviewer.
  • If the team subscriptionpolicy is MODERATED, the user is added as a PROPOSED member and one of the team's administrators have to approve the membership.

If may_subscribe_to_list is True, then also attempt to subscribe to the team's mailing list, depending on the list status and the person's auto-subscribe settings.

param requester:
 The person who requested the membership on behalf of a team or None when a person requests the membership for himself.
param may_subscribe_to_list:
 If True, also try subscribing to the team mailing list.
Team

Get a text line that is suitable to be used for a sources.list entry.

It will create a new IArchiveAuthToken if one doesn't already exist.

Create a PPA.

param name:A string with the name of the new PPA to create. If not specified, defaults to 'ppa'.
param displayname:
 The displayname for the new PPA.
param description:
 The description for the new PPA.
param private:Whether or not to create a private PPA. Defaults to False, which means the PPA will be public.
raises:PPACreationError if an error is encountered
return:a PPA IArchive record.

Leave the given team.

This is a convenience method for retractTeamMembership() that allows a user to leave the given team, or to cancel a PENDING membership request.

param team:The team to leave.
Team

Retract this team's membership in the given team.

If there's a membership entry for this team on the given team and its status is either APPROVED, ADMIN, PENDING, or INVITED, the status is changed and the relevant entries in TeamParticipation.

APPROVED and ADMIN status are changed to DEACTIVATED. PENDING status is changed to DECLINED. INVITED status is changes to INVITATION_DECLINED.

param team:The team to leave.
param user:The user making the retraction.
param comment:An optional explanation about why the change was made.
Team

Decline an invitation to become a member of the given team.

There must be a TeamMembership for this person and the given team with the INVITED status. The status of this TeamMembership will be changed to INVITATION_DECLINED.

Team

Accept an invitation to become a member of the given team.

There must be a TeamMembership for this person and the given team with the INVITED status. The status of this TeamMembership will be changed to APPROVED.

Team
Specify the location and time zone of a person. The latitude of this object. The time zone of this object. The longitude of this object. Specify the visibility of a person's location and time zone. Is this location record visible?

Create a SourcePackageRecipe owned by this person.

param name:the name to use for referring to the recipe.
param description:
 A description of the recipe.
param recipe_text:
 The text of the recipe.
param distroseries:
 The distroseries to use.
param registrant:
 The person who created this recipe.
param daily_build_archive:
 The archive to use for daily builds.
param build_daily:
 If True, build this recipe daily (if changed).
return:a SourcePackageRecipe.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. List of this team's admins.

Default PPA

The PPA named 'ppa' owned by this person.

Confirmed e-mails of this person.

Confirmed e-mails are the ones in the VALIDATED state

Date Created All members whose membership is in the DEACTIVATED state

Display Name

Your name as you would like it displayed throughout Launchpad. Most people use their full name here.

All members whose membership is in the EXPIRED state List of valid OpenPGP keys ordered by ID Hardware submissions Hide my email addresses from other Launchpad users

Homepage Content

The content of your profile page. Use plain text, paragraphs are preserved and URLs are linked in pages.

All members whose membership is in the INVITED state List of IRC nicknames of this Person. Is this person due to be merged with another? Is this a probationary user? Is this object a team? Signed Ubuntu Code of Conduct This is an active user or a team. List of Jabber IDs of this Person.

Karma

The cached total karma for this person.

List of languages known by this person The latitude of this object.

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to you. Traditionally this is a logo, a small picture or a personal mascot. It should be no bigger than 50kb in size.

The longitude of this object.

Mailing List Auto-subscription Policy

This attribute determines whether a person is automatically subscribed to a team's mailing list when the person joins said team.

List of direct members with ADMIN or APPROVED status

Active TeamMemberships for this object's members.

Active TeamMemberships are the ones with the ADMIN or APPROVED status. The results are ordered using Person.sortingColumns.

All TeamMemberships for Teams this Team or Person is an active member of.

Mugshot

A large image of exactly 192x192 pixels, that will be displayed on your home page in Launchpad. Traditionally this is a great big picture of your grinning face. Make the most of it! It should be no bigger than 100kb in size.

Name

A short unique name, beginning with a lower-case letter or number, and containing only letters, numbers, dots, hyphens, or plus signs.

Open membership invitations.

All TeamMemberships which represent an invitation (to join a team) sent to this person.

All participants of this team.

List of all direct and indirect people and teams who, one way or another, are a part of this team. If you want a method to check if a given person is a member of a team, you should probably look at IPerson.inTeam().

PPAs for this person.

PPAs owned by the context person ordered by name.

Preferred email address

The preferred email address for this person. The one we'll use to communicate with them.

This team is private

Private teams are visible only to their members.

All members whose membership is in the PROPOSED state All recipes associated with the object. List of SSH keys

All subteams of this team.

A subteam is any team that is a member (either directly or indirectly) of this team. As an example, let's say we have this hierarchy of teams:

Rosetta Translators
Rosetta pt Translators
Rosetta pt_BR Translators

In this case, both 'Rosetta pt Translators' and 'Rosetta pt_BR Translators' are subteams of the 'Rosetta Translators' team, and all members of both subteams are considered members of "Rosetta Translators".

All superteams of this team.

A superteam is any team that this team is a member of. For example, let's say we have this hierarchy of teams, and we are the "Rosetta pt_BR Translators":

Rosetta Translators
Rosetta pt Translators
Rosetta pt_BR Translators

In this case, we will return both 'Rosetta pt Translators' and 'Rosetta Translators', because we are member of both of them.

Team Owner The time zone of this object.

Visibility

Public visibility is standard. Private means the team is completely hidden.

All WikiNames of this Person, sorted alphabetically by URL.

Display Name

Your name as you would like it displayed throughout Launchpad. Most people use their full name here.

Hide my email addresses from other Launchpad users

Homepage Content

The content of your profile page. Use plain text, paragraphs are preserved and URLs are linked in pages.

Is this person due to be merged with another?

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to you. Traditionally this is a logo, a small picture or a personal mascot. It should be no bigger than 50kb in size.

Mailing List Auto-subscription Policy

This attribute determines whether a person is automatically subscribed to a team's mailing list when the person joins said team.

Mugshot

A large image of exactly 192x192 pixels, that will be displayed on your home page in Launchpad. Traditionally this is a great big picture of your grinning face. Make the most of it! It should be no bigger than 100kb in size.

Name

A short unique name, beginning with a lower-case letter or number, and containing only letters, numbers, dots, hyphens, or plus signs.

Team Owner

Visibility

Public visibility is standard. Private means the team is completely hidden.

An object that might be a project, a project group, or a distribution.

This is a polymorphic object served by the pillar set. Check the individual object to see what type it is.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Active

Whether or not this item is active.

Active

Whether or not this item is active.

An object for searching across projects, project groups, and distros.

Projects, project groups, and distributions are collectively known as "pillars". This object lets you do a combined search across all types of pillars. It also gives you access to pillars that have been flagged by administrators as "featured" pillars.

Return Projects/Project groups/Distros matching :text:.

If :limit: is None, the default batch size will be used.

The results are ordered descending by rank.

Search text Maximum number of items to return. This is a hard limit: any pagination you request will happen within this limit.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Projects, project groups, and distributions that are featured on the site.

A diff generated to show actual diff between two branches.

This diff will be used primarily for branch merge proposals where we are trying to determine the effective changes of landing the source branch on the target branch.

The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The number of lines added in this diff. The branch merge proposal that diff relates to. The conflicts text describing any path or text conflicts. The number of lines in this diff. Content of this diff Statistics about this diff The tip revision id of the prerequisite branch used to generate the diff. The number of lines removed in this diff. The tip revision id of the source branch used to generate the diff. If the preview diff is stale, it is out of date when compared to the tip revisions of the source, target, and possibly prerequisite branches. The tip revision id of the target branch used to generate the diff. The SQLObject Processor Interface The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The SQLObject ProcessorFamily Interface The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

A Product.

The Launchpad Registry describes the open source world as ProjectGroups and Products. Each ProjectGroup may be responsible for several Products. For example, the Mozilla Project has Firefox, Thunderbird and The Mozilla App Suite as Products, among others.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Return basic timeline data useful for creating a diagram.

The number of milestones returned per series is limited.

Include inactive

Returns all merge proposals of a given status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
returns:A list of IBranchMergeProposal.
A list of merge proposal statuses to filter by.

Return all the subscriptions with the specified levels.

return:A sequence of IStructuralSubscription.
Return the series for this product for the given name, or None. Name

Returns all branches with the given lifecycle status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
param modified_since:
 If set, filters the branches being returned to those that have been modified since the specified date/time.
param eager_load:
 If True load related objects for the whole collection.
returns:A list of IBranch.
Limit the branches to those modified since this date. A list of branch lifecycle statuses to filter by.
Is user subscribed, directly or via a team, to bug mail? Return the release for this product that has the version given. Version

Return entries in the translation import queue for this entity.

arg import_status:
 RosettaImportStatus DB Schema entry.
arg file_extension:
 String with the file type extension, usually 'po' or 'pot'.

If one of both of 'import_status' or 'file_extension' are given, the returned entries are filtered based on those values.

Filename extension

Show only entries with this filename suffix

Status

Show only entries with this status

Return the subscription for person, if it exists. Return a milestone with the given name for this object, or None. Name Remove tag from the official bug tags of this target. The official bug tag

Create a new code import.

param registrant:
 The IPerson to record as the registrant of the import
param branch_name:
 The name of the branch to create.
param rcs_type:The type of the foreign VCS.
param url:The URL to import from if the VCS type uses a single URL (i.e. isn't CVS).
param cvs_root:The CVSROOT for a CVS import.
param cvs_module:
 The module to import for a CVS import.
param owner:Who should own the created branch, or None for it to be the same as the registrant, or the caller over the API.
returns:An instance of ICodeImport.
CVS module to import Foreign VCS URL Name of branch to create Owner of the resulting branch CVS root URL

Creates a new IProductSeries for this IProduct.

param owner:The registrant of this series.
param name:The unique name of this series.
param summary:The summary of the purpose and focus of development of this series.
param branch:The bazaar branch that contains the code for this series.
param releasefileglob:
 The public URL pattern where release files can be automatically downloaded from and linked to this series.

Release URL pattern

A URL pattern that matches releases that are part of this series. Launchpad automatically scans this site to import new releases. Example: http://ftp.gnu.org/gnu/emacs/emacs-21.*.tar.gz

Name

The name of the series is a short, unique name that identifies it, being used in URLs. It must be all lowercase, with no special characters. For example, '2.0' or 'trunk'.

Branch

The Bazaar branch for this series. Leave blank if this series is not maintained in Bazaar.

Summary

A single paragraph that explains the goals of of this series and the intended users. For example: "The 2.0 series of Apache represents the current stable series, and is recommended for all new deployments".

Add a bug subscription filter for this structure.

This method is used to create a new IBugSubscriptionFilter for the target. It will initially allow all notifications to be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription filter.
Person to subscribe. If omitted, the requesting user will be subscribed.

Add a bug subscription for this structure.

This method is used to create a new IStructuralSubscription for the target. This initially has a single filter which will allow all notifications will be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription.
Person to subscribe. If omitted, the requesting user will be subscribed.

Remove a subscription to bugs from this structure.

This will delete all associated filters.

subscriber:The IPerson who will be unsubscribed. If omitted, unsubscribed_by will be used.
unsubscribed_by:
 The IPerson removing the subscription.
Person to unsubscribe. If omitted, the requesting user will be unsubscribed.
Add tag to the official bug tags of this target. The official bug tag
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Active

Whether or not this item is active.

The visible and active milestones associated with this object, ordered by date expected. All milestones associated with this object, ordered by date expected.

Brand

A large image of exactly 192x192 pixels, that will be displayed on this project's home page in Launchpad. It should be no bigger than 100kb in size.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

Bug Supervisor

The Launchpad id of the person or team (preferred) responsible for bug management. Mail about all bug activity will be sent to the supervisor by default. The bug supervisor can change the bug mail rules to limit the volume of email.

Bugs are tracked

Commercial subscriptions

An object which contains the timeframe and the voucher code of a subscription.

Commercial subscription is due

Whether the project's licensing requires a new commercial subscription to use launchpad.

Date Created

The date this project was created in Launchpad.

Next suggest packaging date

The date when Launchpad can resume suggesting Ubuntu packages that the project provides. The default value is one year after a user states the project is not packaged in Ubuntu.

Description

Details about the project's work, highlights, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages. Don't repeat the Summary.

Development focus

The series that represents the master or trunk branch. The Bazaar URL lp:<project> points to the development focus series branch.

Display Name

The name of the project as it would appear in a
paragraph.

Download URL

The full URL where downloads for this project
are located, if available. Please include the http://

Driver

This person or team will be able to set feature goals for and approve bug targeting or backporting for ANY major series in this project. You might want to leave this blank and just appoint a team for each specific series, rather than having one project team that does it all.

Freshmeat Project

The Freshmeat project name for
this project, if it is in freshmeat.

Homepage URL

The project home page. Please include
the http://

Icon

A small image of exactly 14x14 pixels and at most 5kb in size, that can be used to identify this project. The icon will be displayed next to the project name everywhere in Launchpad that we refer to the project and link to it.

Is Permitted

Whether the project's licensing qualifies for free hosting or the project has an up-to-date subscription.

License approved

The project is legitimate and its license appears valid. Not applicable to 'Other/Proprietary'.

Description of additional licenses

Description of licenses that do not appear in the list above.

Licenses

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to this project. It should be no bigger than 50kb in size.

Name

At least one lowercase letter or number, followed by letters, numbers, dots, hyphens or pluses. Keep this name short; it is used in URLs as shown above.

Official Bug Tags

The list of bug tags defined as official.

Maintainer

The person or team who maintains the project information in Launchpad.

Programming Languages

A comma delimited list of programming
languages used for this project.

Part of

Project group. This is an overarching initiative that includes several related projects. For example, the Mozilla Project produces Firefox, Thunderbird and Gecko. This information is used to group those projects in a coherent way. If you make this project part of a group, the group preferences and decisions around bug tracking, translation and security policy will apply to this project.

Project reviewed

Whether or not this project has been reviewed. If you looked at the project and how it uses Launchpad, you reviewed it.

Qualifies for free hosting

Whether the project's licensing qualifies it for free use of launchpad.

All recipes associated with the object.

Registrant

This person registered the project in Launchpad.

An iterator over the ProductReleases for this product.

Remote bug tracker project id

Some bug trackers host multiple projects at the same URL and require an identifier for the specific project.

Notes for the project reviewer

Notes on the project's license, editable only by reviewers (Admins and Commercial Admins).

Screenshots URL

The full URL for screenshots of this project,
if available. Please include the http://

Security Contact

The Launchpad id of the person or team (preferred) who handles security-related bug reports. The security contact will be subscribed to all bugs marked as a security vulnerability and will receive email about all activity on all security bugs.

Sourceforge Project

The SourceForge project name for
this project, if it is in sourceforge.

Summary

A short paragraph to introduce the project's work.

Title

The project title. Should be just a few words.

Translation focus

Project series that translators should focus on.

Wiki URL

The full URL of this project's wiki, if it has
one. Please include the http://

Active

Whether or not this item is active.

Brand

A large image of exactly 192x192 pixels, that will be displayed on this project's home page in Launchpad. It should be no bigger than 100kb in size.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

Bug Supervisor

The Launchpad id of the person or team (preferred) responsible for bug management. Mail about all bug activity will be sent to the supervisor by default. The bug supervisor can change the bug mail rules to limit the volume of email.

Bugs are tracked

Commercial subscriptions

An object which contains the timeframe and the voucher code of a subscription.

Next suggest packaging date

The date when Launchpad can resume suggesting Ubuntu packages that the project provides. The default value is one year after a user states the project is not packaged in Ubuntu.

Description

Details about the project's work, highlights, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages. Don't repeat the Summary.

Development focus

The series that represents the master or trunk branch. The Bazaar URL lp:<project> points to the development focus series branch.

Display Name

The name of the project as it would appear in a
paragraph.

Download URL

The full URL where downloads for this project
are located, if available. Please include the http://

Driver

This person or team will be able to set feature goals for and approve bug targeting or backporting for ANY major series in this project. You might want to leave this blank and just appoint a team for each specific series, rather than having one project team that does it all.

Freshmeat Project

The Freshmeat project name for
this project, if it is in freshmeat.

Homepage URL

The project home page. Please include
the http://

Icon

A small image of exactly 14x14 pixels and at most 5kb in size, that can be used to identify this project. The icon will be displayed next to the project name everywhere in Launchpad that we refer to the project and link to it.

License approved

The project is legitimate and its license appears valid. Not applicable to 'Other/Proprietary'.

Description of additional licenses

Description of licenses that do not appear in the list above.

Licenses

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to this project. It should be no bigger than 50kb in size.

Name

At least one lowercase letter or number, followed by letters, numbers, dots, hyphens or pluses. Keep this name short; it is used in URLs as shown above.

Official Bug Tags

The list of bug tags defined as official.

Maintainer

The person or team who maintains the project information in Launchpad.

Programming Languages

A comma delimited list of programming
languages used for this project.

Part of

Project group. This is an overarching initiative that includes several related projects. For example, the Mozilla Project produces Firefox, Thunderbird and Gecko. This information is used to group those projects in a coherent way. If you make this project part of a group, the group preferences and decisions around bug tracking, translation and security policy will apply to this project.

Project reviewed

Whether or not this project has been reviewed. If you looked at the project and how it uses Launchpad, you reviewed it.

Remote bug tracker project id

Some bug trackers host multiple projects at the same URL and require an identifier for the specific project.

Notes for the project reviewer

Notes on the project's license, editable only by reviewers (Admins and Commercial Admins).

Screenshots URL

The full URL for screenshots of this project,
if available. Please include the http://

Security Contact

The Launchpad id of the person or team (preferred) who handles security-related bug reports. The security contact will be subscribed to all bugs marked as a security vulnerability and will receive email about all activity on all security bugs.

Sourceforge Project

The SourceForge project name for
this project, if it is in sourceforge.

Summary

A short paragraph to introduce the project's work.

Title

The project title. Should be just a few words.

Translation focus

Project series that translators should focus on.

Wiki URL

The full URL of this project's wiki, if it has
one. Please include the http://

A specific release (i.e. version) of a product.

For example: Mozilla 1.7.2 or Apache 2.0.48.

Add file to the library and link to this IProductRelease.

The signature file will also be added if available.

param filename:Name of the file being uploaded.
param file_content:
 StringIO or file object.
param content_type:
 A MIME content type string.
param uploader:The person who uploaded the file.
param signature_filename:
 Name of the uploaded gpg signature file.
param signature_content:
 StringIO or file object.
param file_type:
 An UpstreamFileType enum value.
param description:
 Info about the file.
returns:IProductReleaseFile object.

Description

A detailed description of the file contents

Upstream file type

Delete this product release.

This method must not be used if this product release has any release files associated with it.

The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Changelog

A description of every change in the release.

Date Created

The date this project release was created in Launchpad.

Date released

The date this release was published. Before release, this should have an estimated release date.

Constructed display name for a project release.

Project release files

A list of files for this release.

Milestone for this release

A release requires a corresponding milestone that is not attached to another release.

The owner of this release.

The person or team who owns his product release.

The upstream project of this release.

Release notes

A description of important new features (though the changelog below might repeat some of this information).

Constructed title for a project release.

Version

The specific version number assigned to this release. Letters and numbers are acceptable, for releases like "1.2rc3".

Changelog

A description of every change in the release.

Date released

The date this release was published. Before release, this should have an estimated release date.

Milestone for this release

A release requires a corresponding milestone that is not attached to another release.

The owner of this release.

The person or team who owns his product release.

Release notes

A description of important new features (though the changelog below might repeat some of this information).

Version

The specific version number assigned to this release. Letters and numbers are acceptable, for releases like "1.2rc3".

A file associated with a ProductRelease. Delete the product release file. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Upload date

The date this file was uploaded

Description

A detailed description of the file contents

File

The file contents.

Upstream file type

Project release

The parent product release.

File signature

The file signature.

Description

A detailed description of the file contents

Upstream file type

Project release

The parent product release.

A series of releases. For example '2.0' or '1.3' or 'dev'.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Return basic timeline data useful for creating a diagram.

The number of milestones returned is limited.

Include inactive

Return all the subscriptions with the specified levels.

return:A sequence of IStructuralSubscription.

Return an iterator over all its translation templates.

The returned templates are either obsolete or current.

return:A sequence of IPOTemplate.

Return entries in the translation import queue for this entity.

arg import_status:
 RosettaImportStatus DB Schema entry.
arg file_extension:
 String with the file type extension, usually 'po' or 'pot'.

If one of both of 'import_status' or 'file_extension' are given, the returned entries are filtered based on those values.

Filename extension

Show only entries with this filename suffix

Status

Show only entries with this status

Is user subscribed, directly or via a team, to bug mail? Return the subscription for person, if it exists.

Add a bug subscription for this structure.

This method is used to create a new IStructuralSubscription for the target. This initially has a single filter which will allow all notifications will be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription.
Person to subscribe. If omitted, the requesting user will be subscribed.

Remove a subscription to bugs from this structure.

This will delete all associated filters.

subscriber:The IPerson who will be unsubscribed. If omitted, unsubscribed_by will be used.
unsubscribed_by:
 The IPerson removing the subscription.
Person to unsubscribe. If omitted, the requesting user will be unsubscribed.
Create a new milestone for this ProjectSeries.

Date Targeted

Example: 2005-11-24

Name

Only letters, numbers, and simple punctuation are allowed.

Code name

An alternative name for the milestone.

Summary

A summary of the features and status of this milestone.

Add a bug subscription filter for this structure.

This method is used to create a new IBugSubscriptionFilter for the target. It will initially allow all notifications to be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription filter.
Person to subscribe. If omitted, the requesting user will be subscribed.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Active

Whether or not this series is stable and supported, or under current development. This excludes series which are experimental or obsolete.

The visible milestones associated with this project series, ordered by date expected. All milestones associated with this project series, ordered by date expected.

Branch

The Bazaar branch for this series. Leave blank if this series is not maintained in Bazaar.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

Date Registered

Display Name

Display name, in this case we have removed the underlying database field, and this attribute just returns the name.

Release manager

The person or team responsible for decisions about features and bugs that will be targeted to this series. If you don't nominate someone here, then the owner of this series will automatically have those permissions, as will the project and project group drivers.

A list of the people or teams who are drivers for this series. This list is made up of any drivers or owners from this series and the parent drivers.

Name

The name of the series is a short, unique name that identifies it, being used in URLs. It must be all lowercase, with no special characters. For example, '2.0' or 'trunk'.

Official Bug Tags

The list of bug tags defined as official.

Owner

Project owner, either a valid Person or Team

Project

Release URL pattern

A URL pattern that matches releases that are part of this series. Launchpad automatically scans this site to import new releases. Example: http://ftp.gnu.org/gnu/emacs/emacs-21.*.tar.gz

An iterator over the releases in this Series, sorted with latest release first. Status

Summary

A single paragraph that explains the goals of of this series and the intended users. For example: "The 2.0 series of Apache represents the current stable series, and is recommended for all new deployments".

Title

The product series title. Should be just a few words.

Active

Whether or not this series is stable and supported, or under current development. This excludes series which are experimental or obsolete.

Branch

The Bazaar branch for this series. Leave blank if this series is not maintained in Bazaar.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

Display Name

Display name, in this case we have removed the underlying database field, and this attribute just returns the name.

Release manager

The person or team responsible for decisions about features and bugs that will be targeted to this series. If you don't nominate someone here, then the owner of this series will automatically have those permissions, as will the project and project group drivers.

Name

The name of the series is a short, unique name that identifies it, being used in URLs. It must be all lowercase, with no special characters. For example, '2.0' or 'trunk'.

Owner

Project owner, either a valid Person or Team

Project

Release URL pattern

A URL pattern that matches releases that are part of this series. Launchpad automatically scans this site to import new releases. Example: http://ftp.gnu.org/gnu/emacs/emacs-21.*.tar.gz

Status

Summary

A single paragraph that explains the goals of of this series and the intended users. For example: "The 2.0 series of Apache represents the current stable series, and is recommended for all new deployments".

Title

The product series title. Should be just a few words.

A ProjectGroup.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Returns all merge proposals of a given status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
returns:A list of IBranchMergeProposal.
A list of merge proposal statuses to filter by.

Return all the subscriptions with the specified levels.

return:A sequence of IStructuralSubscription.

Returns all branches with the given lifecycle status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
param modified_since:
 If set, filters the branches being returned to those that have been modified since the specified date/time.
param eager_load:
 If True load related objects for the whole collection.
returns:A list of IBranch.
Limit the branches to those modified since this date. A list of branch lifecycle statuses to filter by.
Is user subscribed, directly or via a team, to bug mail? Return the subscription for person, if it exists. Return a milestone with the given name for this object, or None. Name

Add a bug subscription for this structure.

This method is used to create a new IStructuralSubscription for the target. This initially has a single filter which will allow all notifications will be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription.
Person to subscribe. If omitted, the requesting user will be subscribed.

Remove a subscription to bugs from this structure.

This will delete all associated filters.

subscriber:The IPerson who will be unsubscribed. If omitted, unsubscribed_by will be used.
unsubscribed_by:
 The IPerson removing the subscription.
Person to unsubscribe. If omitted, the requesting user will be unsubscribed.

Add a bug subscription filter for this structure.

This method is used to create a new IBugSubscriptionFilter for the target. It will initially allow all notifications to be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription filter.
Person to subscribe. If omitted, the requesting user will be subscribed.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Active

Whether or not this item is active.

The visible and active milestones associated with this object, ordered by date expected. All milestones associated with this object, ordered by date expected.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

If I’m reporting a bug, I should include, if possible

These guidelines will be shown to anyone reporting a bug.

Bug Tracker

The bug tracker the projects in this project group use.

Date Created

The date this project group was created in Launchpad.

Description

Details about the project group's work, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages. Don't repeat the Summary.

Display Name

Appropriately capitalised, and typically ending in "Project". Examples: the Apache Project, the Mozilla Project, the Gimp Project.

Driver

This is a project group-wide appointment. Think carefully here! This person or team will be able to set feature goals and approve bug targeting and backporting for ANY series in ANY project in this group. You can also appoint drivers at the level of a specific project or series. So you may just want to leave this space blank, and instead let the individual projects and series have drivers.

Freshmeat Project Name

The Freshmeat project name for this project group, if it is in Freshmeat.

Homepage Content

The content of this project group's home page. Edit this and it will be displayed for all the world to see. It is NOT a wiki so you cannot undo changes.

Homepage URL

The project group home page. Please include the http://

Icon

A small image of exactly 14x14 pixels and at most 5kb in size, that can be used to identify this project group. The icon will be displayed in Launchpad everywhere that we link to this project group. For example in listings or tables of active project groups.

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to this project group. It should be no bigger than 50kb in size.

Brand

A large image of exactly 192x192 pixels, that will be displayed on this project group's home page in Launchpad. It should be no bigger than 100kb in size.

Name

A unique name, used in URLs, identifying the project group. All lowercase, no special characters. Examples: apache, mozilla, gimp.

Official Bug Tags

The list of bug tags defined as official.

Maintainer

Project group owner. Must be either a Launchpad Person or Team.

List of active projects for this project group.

Registrant

Project group registrant. Must be a valid Launchpad Person.

Reviewed

Whether or not this project group has been reviewed.

SourceForge Project Name

The SourceForge project name for this project group, if it is in SourceForge.

Project Group Summary

A short paragraph to introduce the project group's work.

Title

The full name of the project group, which can contain spaces, special characters, etc.

Wiki URL

The URL of this project group's wiki, if it has one. Please include the http://

Active

Whether or not this item is active.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

If I’m reporting a bug, I should include, if possible

These guidelines will be shown to anyone reporting a bug.

Bug Tracker

The bug tracker the projects in this project group use.

Description

Details about the project group's work, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages. Don't repeat the Summary.

Display Name

Appropriately capitalised, and typically ending in "Project". Examples: the Apache Project, the Mozilla Project, the Gimp Project.

Driver

This is a project group-wide appointment. Think carefully here! This person or team will be able to set feature goals and approve bug targeting and backporting for ANY series in ANY project in this group. You can also appoint drivers at the level of a specific project or series. So you may just want to leave this space blank, and instead let the individual projects and series have drivers.

Freshmeat Project Name

The Freshmeat project name for this project group, if it is in Freshmeat.

Homepage Content

The content of this project group's home page. Edit this and it will be displayed for all the world to see. It is NOT a wiki so you cannot undo changes.

Homepage URL

The project group home page. Please include the http://

Icon

A small image of exactly 14x14 pixels and at most 5kb in size, that can be used to identify this project group. The icon will be displayed in Launchpad everywhere that we link to this project group. For example in listings or tables of active project groups.

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to this project group. It should be no bigger than 50kb in size.

Brand

A large image of exactly 192x192 pixels, that will be displayed on this project group's home page in Launchpad. It should be no bigger than 100kb in size.

Name

A unique name, used in URLs, identifying the project group. All lowercase, no special characters. Examples: apache, mozilla, gimp.

Maintainer

Project group owner. Must be either a Launchpad Person or Team.

Reviewed

Whether or not this project group has been reviewed.

SourceForge Project Name

The SourceForge project name for this project group, if it is in SourceForge.

Project Group Summary

A short paragraph to introduce the project group's work.

Title

The full name of the project group, which can contain spaces, special characters, etc.

Wiki URL

The URL of this project group's wiki, if it has one. Please include the http://

A single question, often a support request. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. SSH public key The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Comment describing this key Key text Key type A source package associated to a particular distribution series.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Returns all merge proposals of a given status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
returns:A list of IBranchMergeProposal.
A list of merge proposal statuses to filter by.

Return an iterator over all its translation templates.

The returned templates are either obsolete or current.

return:A sequence of IPOTemplate.

Get the official branches for this package.

This operation returns a {Pocket-name : IBranch} dict.

return:A {Pocket-name : IBranch} dict.

Returns all branches with the given lifecycle status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
param modified_since:
 If set, filters the branches being returned to those that have been modified since the specified date/time.
param eager_load:
 If True load related objects for the whole collection.
returns:A list of IBranch.
Limit the branches to those modified since this date. A list of branch lifecycle statuses to filter by.

Return entries in the translation import queue for this entity.

arg import_status:
 RosettaImportStatus DB Schema entry.
arg file_extension:
 String with the file type extension, usually 'po' or 'pot'.

If one of both of 'import_status' or 'file_extension' are given, the returned entries are filtered based on those values.

Filename extension

Show only entries with this filename suffix

Status

Show only entries with this status

Get the official branch for this package in the given pocket.

param pocket:A PackagePublishingPocket.
return:An IBranch.
Pocket

Set the official branch for the given pocket of this package.

param pocket:A PackagePublishingPocket.
param branch:The branch to set as the official branch.
param registrant:
 The individual who created this link.
return:None
Pocket Branch

Create a new code import.

param registrant:
 The IPerson to record as the registrant of the import
param branch_name:
 The name of the branch to create.
param rcs_type:The type of the foreign VCS.
param url:The URL to import from if the VCS type uses a single URL (i.e. isn't CVS).
param cvs_root:The CVSROOT for a CVS import.
param cvs_module:
 The module to import for a CVS import.
param owner:Who should own the created branch, or None for it to be the same as the registrant, or the caller over the API.
returns:An instance of ICodeImport.
CVS module to import Foreign VCS URL Name of branch to create Owner of the resulting branch CVS root URL
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

Display name

A displayname, constructed, for this package

Distribution

The distribution for this source package.

Distribution Series

The DistroSeries for this SourcePackage

The name of the component in which the package was last published.

Name

The text name of this source package.

Official Bug Tags

The list of bug tags defined as official.

Project series

The registered project series that this source package is based on. This series may be the same as the one that earlier versions of this source packages were based on.

After reporting a bug, I can expect the following.

This message of acknowledgement will be displayed to anyone after reporting a bug.

Helpful guidelines for reporting a bug

These guidelines will be shown to everyone reporting a bug and should be text or a bulleted list with your particular requirements, if any.

A source package publishing history record.

Return all resulted IBinaryPackagePublishingHistory.

Follow the build record and return every PUBLISHED or PENDING binary publishing record for any DistroArchSeries in this DistroSeries and in the same IArchive and Pocket, ordered by architecture tag.

return:a list with all corresponding publishing records.

URL of the debdiff file between this and the supplied version.

param to_version:
 The version of the source package for which you want to get the diff to.
return:A URL to the librarian file containing the diff.
To Version

Return a list of IBuild objects in this publishing context.

The builds are ordered by DistroArchSeries.architecturetag.

return:a list of IBuilds.

URLs for this source publication's binary files.

return:A collection of URLs for this source.

URLs for this source publication's uploaded source files.

return:A collection of URLs for this source.

The .changes file URL for this source publication.

return:the .changes file URL for this source (a string).

Delete this source and its binaries.

param removed_by:
 IPerson responsible for the removal.
param removal_comment:
 optional text describing the removal reason.
Removal comment
The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Archive ID Component Name The date on which this record was created The date on which this record was set as pending removal The date on which this record was published The date on which this record was removed from the published set The date on which this record was marked superseded

Display Name

Text representation of the current record.

The distro series being published into

Package Creator

The IPerson who created the source package.

Package Maintainer

The IPerson who maintains the source package.

Package Signer

The IPerson who signed the source package.

Pocket

The pocket into which this entry is published

Reason why this publication is going to be removed. The IPerson responsible for the removal The date on which this record is scheduled for deletion Section Name Source Package Name Source Package Version

Package Publishing Status

The status of this publishing record

The date on which this record was created The date on which this record was set as pending removal The date on which this record was published The date on which this record was removed from the published set The date on which this record was marked superseded

Display Name

Text representation of the current record.

The distro series being published into Reason why this publication is going to be removed. The IPerson responsible for the removal The date on which this record is scheduled for deletion

Package Publishing Status

The status of this publishing record

A build of a source package. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

Archive

The Archive context for this build.

Build Log URL

A URL for the build log. None if there is no log available.

Status

The current status of the job.

Date finished

The actual build start time. Set when the build is dispatched the first time and not changed in subsequent build attempts.

Date finished

The timestamp when the build farm job was finished.

Date created

The timestamp when the build farm job was created.

Dependencies

Debian-like dependency line that must be satisfied before attempting to build this request.

Distribution

Shortcut for its distribution.

Distribution series

Shortcut for its distribution series.

Pocket

The build targeted pocket.

Title

Upload Log URL

A URL for failed upload logs.Will be None if there was no failure.

Build Log URL

A URL for the build log. None if there is no log available.

Status

The current status of the job.

Dependencies

Debian-like dependency line that must be satisfied before attempting to build this request.

Distribution

Shortcut for its distribution.

Distribution series

Shortcut for its distribution series.

Pocket

The build targeted pocket.

Title

Upload Log URL

A URL for failed upload logs.Will be None if there was no failure.

An ISourcePackageRecipe describes how to build a source package.

More precisely, it describes how to combine a number of branches into a debianized source tree.

Request that the recipe be built in to the specified archive.

param archive:The IArchive which you want the build to end up in.
param requester:
 the person requesting the build.
param pocket:the pocket that should be targeted.
raises:various specific upload errors if the requestor is not able to upload to the archive.
Set the text of the recipe. Perform a build into the daily build archive.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The base branch used by this recipe.

Built daily

Automatically build each day, if the source has changed.

All builds of this recipe.

All builds of this recipe, sorted in descending order of finishing (or starting if notcompleted successfully).

The completed builds of this recipe.

Completed builds of this recipe, sorted in descending order of finishing (or starting if notcompleted successfully).

The archive to use for daily builds.

deb-version template

The template that will be used to generate a deb version.

Description

A short description of the recipe.

Default distribution series

If built daily, these are the distribution versions that the recipe will be built for.

The the most recent build of this recipe.

Name

The name of the recipe is part of the URL and needs to be unique for the given owner.

Owner

The person or team who can edit this recipe.

The pending builds of this recipe.

Pending builds of this recipe, sorted in descending order of creation.

The person who created this recipe.

Built daily

Automatically build each day, if the source has changed.

The archive to use for daily builds.

Description

A short description of the recipe.

Name

The name of the recipe is part of the URL and needs to be unique for the given owner.

Owner

The person or team who can edit this recipe.

A branch linked to a specification. Destroy this specification branch link The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Branch The person who linked the bug to the branch Blueprint Branch A Specification.

Unlink a branch from this bug.

param branch:The branch being unlinked from.
param user:The user unlinking the branch.

Associate a branch with this bug.

param branch:The branch being linked to.
param registrant:
 The user linking the branch.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. A subscription to a Launchpad structure. Returns a new BugSubscriptionFilter for this subscription. The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. List of bug filters that narrow this subscription. The date on which this subscription was created. The date on which this subscription was last updated.

Subscribed by

The person creating the subscription.

Subscriber

The person subscribed.

The structure to which this subscription belongs.
A Launchpad Structure allowing users to subscribe to it. Return the subscription for person, if it exists. Is user subscribed, directly or via a team, to bug mail?

Return all the subscriptions with the specified levels.

return:A sequence of IStructuralSubscription.

Remove a subscription to bugs from this structure.

This will delete all associated filters.

subscriber:The IPerson who will be unsubscribed. If omitted, unsubscribed_by will be used.
unsubscribed_by:
 The IPerson removing the subscription.
Person to unsubscribe. If omitted, the requesting user will be unsubscribed.

Add a bug subscription filter for this structure.

This method is used to create a new IBugSubscriptionFilter for the target. It will initially allow all notifications to be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription filter.
Person to subscribe. If omitted, the requesting user will be subscribed.

Add a bug subscription for this structure.

This method is used to create a new IStructuralSubscription for the target. This initially has a single filter which will allow all notifications will be sent.

subscriber:The IPerson who will be subscribed. If omitted, subscribed_by will be used.
subscribed_by:The IPerson creating the subscription.
return:The new bug subscription.
Person to subscribe. If omitted, the requesting user will be subscribed.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource.

A group of people and other teams.

Launchpadlib example of getting the date a user joined a team:

def get_join_date(team, user):
    team = launchpad.people[team]
    members = team.members_details
    for member in members:
        if member.member.name == user:
            return member.date_joined
    return None

Implementation notes:

  • ITeam extends IPerson.
  • The teamowner should never be None.

Search the IBugTasks reported on this entity.

search_params:a BugTaskSearchParams object

Return an iterable of matching results.

Note: milestone is currently ignored for all IBugTargets except IProduct.

In order to search bugs that are related to a given hardware device, you must specify the bus, the vendor ID, the product ID of the device and set at least one of hardware_owner_is_bug_reporter, hardware_owner_is_affected_by_bug, hardware_owner_is_subscribed_to_bug, hardware_is_linked_to_bug to True.

Status upstream

Indicates the status of any remote watches associated with the bug. Possible values include: pending_bugwatch, hide_upstream, resolved_upstream, and open_upstream.

The vendor ID of a hardware device related to a bug.

Allowed values of the vendor ID depend on the bus of the device.

Vendor IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI vendor IDs are strings with exactly 8 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Tags combination

Search for any or all of the tags specified.

Show only bugs associated with a CVE

The product ID of a hardware device related to a bug.

Allowed values of the product ID depend on the bus of the device.

Product IDs of PCI, PCCard and USB devices are hexadecimal string representations of 16 bit integers in the format '0x01ab': The prefix '0x', followed by exactly 4 digits; where a digit is one of the characters 0..9, a..f. The characters A..F are not allowed.

SCSI product IDs are strings with exactly 16 characters. Shorter names are right-padded with space (0x20) characters.

IDs for other buses may be arbitrary strings.

Search for bugs that are linked to branches or for bugs that are not linked to branches. List of fields by which the results are ordered. Exclude bugs with packages specified The package of the driver which controls a hardware device related to a bug.

Status

Show only bugs with the given status value or list of values.

Target

Tags

String or list of strings for tags to search. To exclude, prepend a '-', e.g. '-unwantedtag'

Importance

Show only bugs with the given importance or list of importances.

Component

Distribution package archive grouping. E.g. main, universe, multiverse

Search for bugs where a bug subscriber owns the given device or uses the given hardware driver. Omit bugs targeted to a series Search for bugs that have been modified since the given date. The driver controlling a hardware device related to a bug.

Milestone

Show only bug tasks targeted to this milestone.

Search for bugs which are linked to hardware reports which contain the given device or whcih contain a devicecontrolled by the given driver. Show only bugs with patches available. Bug ID or search text. Search for bugs where people affected by a bug own the given device or use the given hardware driver. Search for bugs that have been created since the given date. Omit bugs marked as duplicate, Search for bugs reported by people who own the given device or who use the given hardware driver. The bus of a hardware device related to a bug

Returns all merge proposals of a given status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
returns:A list of IBranchMergeProposal.
A list of merge proposal statuses to filter by.

Returns all branches with the given lifecycle status.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
param modified_since:
 If set, filters the branches being returned to those that have been modified since the specified date/time.
param eager_load:
 If True load related objects for the whole collection.
returns:A list of IBranch.
Limit the branches to those modified since this date. A list of branch lifecycle statuses to filter by.

Return entries in the translation import queue for this entity.

arg import_status:
 RosettaImportStatus DB Schema entry.
arg file_extension:
 String with the file type extension, usually 'po' or 'pot'.

If one of both of 'import_status' or 'file_extension' are given, the returned entries are filtered based on those values.

Filename extension

Show only entries with this filename suffix

Status

Show only entries with this status

Return a PPA with the given name if it exists.

param name:A string with the exact name of the ppa being looked up.
raises:NoSuchPPA if a suitable PPA could not be found.
return:a PPA IArchive record corresponding to the name.

Returns merge proposals where a person was asked to review.

This does not include merge proposals that were requested from teams that the person is part of. If status is not passed then it will return proposals that are in the "Needs Review" state.

param status:A list of statuses to filter with.
param visible_by_user:
 Normally the user who is asking.
returns:A list of IBranchMergeProposal.
A list of merge proposal statuses to filter by.

Return the people whose membership on this team match :status:.

If no orderby is provided, Person.sortingColumns is used.

The state of this membership
Return the person's recipe with the given name.

Return private archive URLs that this person can see.

For each of the private archives (PPAs) that this person can see, return a URL that includes the HTTP basic auth data. The URL returned is suitable for including in a sources.list file.

Return the packages for which this person is a bug subscriber.

Returns a list of IDistributionSourcePackage's, ordered alphabetically (A to Z) by name.

Add the given person as a member of this team.

param person:If the given person is already a member of this team we'll simply change its membership status. Otherwise a new TeamMembership is created with the given status.
param reviewer:The user who made the given person a member of this team.
param comment:String that will be assigned to the proponent_comment, reviwer_comment, or acknowledger comment.
param status:TeamMembershipStatus value must be either Approved, Proposed or Admin. If the new member is a team, the status will be changed to Invited unless the user is also an admin of that team.
param force_team_add:
 If the person is actually a team and force_team_add is False, the team will actually be invited to join this one. Otherwise the team is added as if it were a person.
param may_subscribe_to_list:
 If the person is not a team, and may_subscribe_to_list is True, then the person may be subscribed to the team's mailing list, depending on the list status and the person's auto-subscribe settings.
return:A tuple containing a boolean indicating when the membership status changed and the current TeamMembershipStatus. This depends on the desired status passed as an argument, the subscription policy and the user's privileges.
The state of this membership Member

Get a text line that is suitable to be used for a sources.list entry.

It will create a new IArchiveAuthToken if one doesn't already exist.

Create a PPA.

param name:A string with the name of the new PPA to create. If not specified, defaults to 'ppa'.
param displayname:
 The displayname for the new PPA.
param description:
 The description for the new PPA.
param private:Whether or not to create a private PPA. Defaults to False, which means the PPA will be public.
raises:PPACreationError if an error is encountered
return:a PPA IArchive record.

Decline an invitation to become a member of the given team.

There must be a TeamMembership for this person and the given team with the INVITED status. The status of this TeamMembership will be changed to INVITATION_DECLINED.

Team

Accept an invitation to become a member of the given team.

There must be a TeamMembership for this person and the given team with the INVITED status. The status of this TeamMembership will be changed to APPROVED.

Team
Specify the location and time zone of a person. The latitude of this object. The time zone of this object. The longitude of this object.

Join the given team if its subscriptionpolicy is not RESTRICTED.

Join the given team according to the policies and defaults of that team:

  • If the team subscriptionpolicy is OPEN, the user is added as an APPROVED member with a NULL TeamMembership.reviewer.
  • If the team subscriptionpolicy is MODERATED, the user is added as a PROPOSED member and one of the team's administrators have to approve the membership.

If may_subscribe_to_list is True, then also attempt to subscribe to the team's mailing list, depending on the list status and the person's auto-subscribe settings.

param requester:
 The person who requested the membership on behalf of a team or None when a person requests the membership for himself.
param may_subscribe_to_list:
 If True, also try subscribing to the team mailing list.
Team

Leave the given team.

This is a convenience method for retractTeamMembership() that allows a user to leave the given team, or to cancel a PENDING membership request.

param team:The team to leave.
Team

Retract this team's membership in the given team.

If there's a membership entry for this team on the given team and its status is either APPROVED, ADMIN, PENDING, or INVITED, the status is changed and the relevant entries in TeamParticipation.

APPROVED and ADMIN status are changed to DEACTIVATED. PENDING status is changed to DECLINED. INVITED status is changes to INVITATION_DECLINED.

param team:The team to leave.
param user:The user making the retraction.
param comment:An optional explanation about why the change was made.
Team
Specify the visibility of a person's location and time zone. Is this location record visible?

Create a SourcePackageRecipe owned by this person.

param name:the name to use for referring to the recipe.
param description:
 A description of the recipe.
param recipe_text:
 The text of the recipe.
param distroseries:
 The distroseries to use.
param registrant:
 The person who created this recipe.
param daily_build_archive:
 The archive to use for daily builds.
param build_daily:
 If True, build this recipe daily (if changed).
return:a SourcePackageRecipe.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. List of this team's admins.

Default PPA

The PPA named 'ppa' owned by this person.

Confirmed e-mails of this person.

Confirmed e-mails are the ones in the VALIDATED state

Date Created All members whose membership is in the DEACTIVATED state

Subscription period

Number of days a new subscription lasts before expiring. You can customize the length of an individual subscription when approving it. Leave this empty or set to 0 for subscriptions to never expire.

Renewal period

Number of days a subscription lasts after being renewed. The number can be from 1 to 3650 (10 years). You can customize the lengths of individual renewals, but this is what's used for auto-renewed and user-renewed memberships.

Display Name

Your name as you would like it displayed throughout Launchpad. Most people use their full name here.

All members whose membership is in the EXPIRED state List of valid OpenPGP keys ordered by ID Hardware submissions Hide my email addresses from other Launchpad users

Homepage Content

The content of your profile page. Use plain text, paragraphs are preserved and URLs are linked in pages.

All members whose membership is in the INVITED state List of IRC nicknames of this Person. Is this person due to be merged with another? Is this a probationary user? Is this object a team? Signed Ubuntu Code of Conduct This is an active user or a team. List of Jabber IDs of this Person.

Karma

The cached total karma for this person.

List of languages known by this person The latitude of this object.

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to you. Traditionally this is a logo, a small picture or a personal mascot. It should be no bigger than 50kb in size.

The longitude of this object.

Mailing List Auto-subscription Policy

This attribute determines whether a person is automatically subscribed to a team's mailing list when the person joins said team.

List of direct members with ADMIN or APPROVED status

Active TeamMemberships for this object's members.

Active TeamMemberships are the ones with the ADMIN or APPROVED status. The results are ordered using Person.sortingColumns.

All TeamMemberships for Teams this Team or Person is an active member of.

Mugshot

A large image of exactly 192x192 pixels, that will be displayed on your home page in Launchpad. Traditionally this is a great big picture of your grinning face. Make the most of it! It should be no bigger than 100kb in size.

Name

A short unique name, beginning with a lower-case letter or number, and containing only letters, numbers, dots, hyphens, or plus signs.

Open membership invitations.

All TeamMemberships which represent an invitation (to join a team) sent to this person.

All participants of this team.

List of all direct and indirect people and teams who, one way or another, are a part of this team. If you want a method to check if a given person is a member of a team, you should probably look at IPerson.inTeam().

PPAs for this person.

PPAs owned by the context person ordered by name.

Preferred email address

The preferred email address for this person. The one we'll use to communicate with them.

This team is private

Private teams are visible only to their members.

All members whose membership is in the PROPOSED state All recipes associated with the object. When someone's membership is about to expire, notify them and List of SSH keys

All subteams of this team.

A subteam is any team that is a member (either directly or indirectly) of this team. As an example, let's say we have this hierarchy of teams:

Rosetta Translators
Rosetta pt Translators
Rosetta pt_BR Translators

In this case, both 'Rosetta pt Translators' and 'Rosetta pt_BR Translators' are subteams of the 'Rosetta Translators' team, and all members of both subteams are considered members of "Rosetta Translators".

Subscription policy

The policies that describe who can be a member and how new memberships are handled. The choice of policy reflects the need to build a community versus the need to control Launchpad assets.

All superteams of this team.

A superteam is any team that this team is a member of. For example, let's say we have this hierarchy of teams, and we are the "Rosetta pt_BR Translators":

Rosetta Translators
Rosetta pt Translators
Rosetta pt_BR Translators

In this case, we will return both 'Rosetta pt Translators' and 'Rosetta Translators', because we are member of both of them.

Team Description

Details about the team's work, highlights, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages.

Team Owner The time zone of this object.

Visibility

Public visibility is standard. Private means the team is completely hidden.

All WikiNames of this Person, sorted alphabetically by URL.

Subscription period

Number of days a new subscription lasts before expiring. You can customize the length of an individual subscription when approving it. Leave this empty or set to 0 for subscriptions to never expire.

Renewal period

Number of days a subscription lasts after being renewed. The number can be from 1 to 3650 (10 years). You can customize the lengths of individual renewals, but this is what's used for auto-renewed and user-renewed memberships.

Display Name

Your name as you would like it displayed throughout Launchpad. Most people use their full name here.

Hide my email addresses from other Launchpad users

Homepage Content

The content of your profile page. Use plain text, paragraphs are preserved and URLs are linked in pages.

Is this person due to be merged with another?

Logo

An image of exactly 64x64 pixels that will be displayed in the heading of all pages related to you. Traditionally this is a logo, a small picture or a personal mascot. It should be no bigger than 50kb in size.

Mailing List Auto-subscription Policy

This attribute determines whether a person is automatically subscribed to a team's mailing list when the person joins said team.

Mugshot

A large image of exactly 192x192 pixels, that will be displayed on your home page in Launchpad. Traditionally this is a great big picture of your grinning face. Make the most of it! It should be no bigger than 100kb in size.

Name

A short unique name, beginning with a lower-case letter or number, and containing only letters, numbers, dots, hyphens, or plus signs.

When someone's membership is about to expire, notify them and

Subscription policy

The policies that describe who can be a member and how new memberships are handled. The choice of policy reflects the need to build a community versus the need to control Launchpad assets.

Team Description

Details about the team's work, highlights, goals, and how to contribute. Use plain text, paragraphs are preserved and URLs are linked in pages.

Team Owner

Visibility

Public visibility is standard. Private means the team is completely hidden.

TeamMembership for Users.

This table includes direct team members only. Indirect memberships are handled by the TeamParticipation table.

Set this membership's expiration date.

The given date must be None or in the future and the given user must be allowed to change this membership's expiration date as per the rules defined in canChangeExpirationDate().

Date expires

Set the status of this membership.

The user and comment are stored in last_changed_by and last_change_comment and may also be stored in proposed_by (and proponent_comment), reviewed_by (and reviewer_comment) or acknowledged_by (and acknowledger_comment), depending on the state transition.

The given status must be different than the current status.

Return True if the status got changed, otherwise False.

Reviewer comment The state of this membership Do not send notifications of status change. For use by Launchpad administrators only.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Date expires

Date joined

The date in which this membership was made active for the first time.

Comment on the last change Last person who change this Member The state of this membership Team
A blob which we will store in the database temporarily. Returns a dict containing the processed blob data. Return True if this blob has been processed. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. UUID Minimal product series info for the timeline. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Is series the development focus of the project List of milestones and releases

Name

The name of the series is a short, unique name that identifies it, being used in URLs. It must be all lowercase, with no special characters. For example, '2.0' or 'trunk'.

Project Status

Series URI

foo

Is series the development focus of the project List of milestones and releases

Name

The name of the series is a short, unique name that identifies it, being used in URLs. It must be all lowercase, with no special characters. For example, '2.0' or 'trunk'.

Project Status

Series URI

foo

A TranslationGroup. The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. An entry of the Translation Import Queue.

Transition to a new status if possible.

param new_status:
 Status to transition to.
param user:The user that is doing the transition.
The status of the import.
The canonical link to this resource. The canonical human-addressable web link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. The timestamp when this queue entry was created. The timestamp when the status was changed. Series

Error output

Output from most recent import attempt.

The file format of the import. The entry ID

Path

The path to this file inside the source tree. Includes the filename.

Series The sourcepackage associated with this entry. The status of the import.

Uploader

The person that uploaded this file to Launchpad.

The timestamp when the status was changed.

Path

The path to this file inside the source tree. Includes the filename.

Wiki for Users The canonical link to this resource. The link to the WADL description of this resource. The value of the HTTP ETag for this resource. Owner The URL for this wiki home page. Wiki host Wikiname Wiki host Wikiname
././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1574442809.0 launchpadlib-1.10.13/src/launchpadlib/testing/launchpad.py0000644000175000017500000005315600000000000025223 0ustar00cjwatsoncjwatson00000000000000# Copyright 2008 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # launchpadlib is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with launchpadlib. If not, see # . """Testing API allows fake data to be used in unit tests. Testing launchpadlib code is tricky, because it depends so heavily on a remote, unique webservice: Launchpad. This module helps you write tests for your launchpadlib application that can be run locally and quickly. Say you were writing some code that needed to call out to Launchpad and get the branches owned by the logged-in person, and then do something to them. For example, something like this:: def collect_unique_names(lp): names = [] for branch in lp.me.getBranches(): names.append(branch.unique_name) return names To test it, you would first prepare a L{FakeLaunchpad} object, and give it some sample data of your own devising:: lp = FakeLaunchpad() my_branches = [dict(unique_name='~foo/bar/baz')] lp.me = dict(getBranches: lambda status: my_branches) Then, in the test, call your own code and assert that it behaves correctly given the data. names = collect_unique_names(lp) self.assertEqual(['~foo/bar/baz'], names) And that's it. The L{FakeLaunchpad} code uses a WADL file to type-check any objects created or returned. This means you can be sure that you won't accidentally store sample data with misspelled attribute names. The WADL file that we use by default is for version 1.0 of the Launchpad API. If you want to work against a more recent version of the API, download the WADL yourself (see ) and construct your C{FakeLaunchpad} like this:: from wadllib.application import Application lp = FakeLaunchpad( Application('https://api.launchpad.net/devel/', '/path/to/wadl.xml')) Where 'https://api.launchpad.net/devel/' is the URL for the WADL file, found also in the WADL file itelf. """ from datetime import datetime try: from collections.abc import Callable except ImportError: from collections import Callable import sys if sys.version_info[0] >= 3: basestring = str JSON_MEDIA_TYPE = "application/json" class IntegrityError(Exception): """Raised when bad sample data is used with a L{FakeLaunchpad} instance.""" class FakeLaunchpad(object): """A fake Launchpad API class for unit tests that depend on L{Launchpad}. @param application: A C{wadllib.application.Application} instance for a Launchpad WADL definition file. """ def __init__(self, credentials=None, service_root=None, cache=None, timeout=None, proxy_info=None, application=None): if application is None: from launchpadlib.testing.resources import get_application application = get_application() root_resource = FakeRoot(application) self.__dict__.update({"credentials": credentials, "_application": application, "_service_root": root_resource}) def __setattr__(self, name, values): """Set sample data. @param name: The name of the attribute. @param values: A dict representing an object matching a resource defined in Launchpad's WADL definition. """ service_root = self._service_root setattr(service_root, name, values) def __getattr__(self, name): """Get sample data. @param name: The name of the attribute. """ return getattr(self._service_root, name) @classmethod def login(cls, consumer_name, token_string, access_secret, service_root=None, cache=None, timeout=None, proxy_info=None): """Convenience for setting up access credentials.""" from launchpadlib.testing.resources import get_application return cls(object(), application=get_application()) @classmethod def get_token_and_login(cls, consumer_name, service_root=None, cache=None, timeout=None, proxy_info=None): """Get credentials from Launchpad and log into the service root.""" from launchpadlib.testing.resources import get_application return cls(object(), application=get_application()) @classmethod def login_with(cls, consumer_name, service_root=None, launchpadlib_dir=None, timeout=None, proxy_info=None): """Log in to Launchpad with possibly cached credentials.""" from launchpadlib.testing.resources import get_application return cls(object(), application=get_application()) def find_by_attribute(element, name, value): """Find children of 'element' where attribute 'name' is equal to 'value'. """ return [child for child in element if child.get(name) == value] def strip_suffix(string, suffix): if string.endswith(suffix): return string[:-len(suffix)] return string class FakeResource(object): """ Represents valid sample data on L{FakeLaunchpad} instances. @ivar _children: A dictionary of child resources, each of type C{FakeResource}. @ivar _values: A dictionary of values associated with this resource. e.g. "display_name" or "date_created". The values of this dictionary will never be C{FakeResource}s. Note that if C{_children} has a key, then C{_values} will not, and vice versa. That is, they are distinct dicts. """ special_methods = ["lp_save"] def __init__(self, application, resource_type, values=None): """Construct a FakeResource. @param application: A C{waddlib.application.Application} instance. @param resource_type: A C{wadllib.application.ResourceType} instance for this resource. @param values: Optionally, a dict representing attribute key/value pairs for this resource. """ if values is None: values = {} self.__dict__.update({"_application": application, "_resource_type": resource_type, "_children": {}, "_values": values}) def __setattr__(self, name, value): """Set sample data. C{value} can be a dict representing an object matching a resource defined in the WADL definition. Alternatively, C{value} could be a resource itself. Either way, it is checked for type correctness against the WADL definition. """ if isinstance(value, dict): self._children[name] = self._create_child_resource(name, value) else: values = {} values.update(self._values) values[name] = value # Confirm that the new 'values' dict is a partial type match for # this resource. self._check_resource_type(self._resource_type, values) self.__dict__["_values"] = values def __getattr__(self, name, _marker=object()): """Get sample data. @param name: The name of the attribute. """ result = self._children.get(name, _marker) if result is _marker: result = self._values.get(name, _marker) if isinstance(result, Callable): return self._wrap_method(name, result) if name in self.special_methods: return lambda: True if result is _marker: raise AttributeError("%r has no attribute '%s'" % (self, name)) return result def _wrap_method(self, name, method): """Wrapper around methods validates results when it's run. @param name: The name of the method. @param method: The callable to run when the method is called. """ def wrapper(*args, **kwargs): return self._run_method(name, method, *args, **kwargs) return wrapper def _create_child_resource(self, name, values): """ Ensure that C{values} is a valid object for the C{name} attribute and return a resource object to represent it as API data. @param name: The name of the attribute to check the C{values} object against. @param values: A dict with key/value pairs representing attributes and methods of an object matching the C{name} resource's definition. @return: A L{FakeEntry} for an ordinary resource or a L{FakeCollection} for a resource that represents a collection. @raises IntegrityError: Raised if C{name} isn't a valid attribute for this resource or if C{values} isn't a valid object for the C{name} attribute. """ root_resource = self._application.get_resource_by_path("") is_link = False param = root_resource.get_parameter(name + "_collection_link", JSON_MEDIA_TYPE) if param is None: is_link = True param = root_resource.get_parameter(name + "_link", JSON_MEDIA_TYPE) if param is None: raise IntegrityError("%s isn't a valid property." % (name,)) resource_type = self._get_resource_type(param) if is_link: self._check_resource_type(resource_type, values) return FakeEntry(self._application, resource_type, values) else: name, child_resource_type = ( self._check_collection_type(resource_type, values)) return FakeCollection(self._application, resource_type, values, name, child_resource_type) def _get_resource_type(self, param): """Get the resource type for C{param}. @param param: An object representing a C{_link} or C{_collection_link} parameter. @return: The resource type for the parameter, or None if one isn't available. """ [link] = list(param.tag) name = link.get("resource_type") return self._application.get_resource_type(name) def _check_resource_type(self, resource_type, partial_object): """ Ensure that attributes and methods defined for C{partial_object} match attributes and methods defined for C{resource_type}. @param resource_type: The resource type to check the attributes and methods against. @param partial_object: A dict with key/value pairs representing attributes and methods. """ for name, value in partial_object.items(): if isinstance(value, Callable): # Performs an integrity check. self._get_method(resource_type, name) else: self._check_attribute(resource_type, name, value) def _check_collection_type(self, resource_type, partial_object): """ Ensure that attributes and methods defined for C{partial_object} match attributes and methods defined for C{resource_type}. Collection entries are treated specially. @param resource_type: The resource type to check the attributes and methods against. @param partial_object: A dict with key/value pairs representing attributes and methods. @return: (name, resource_type), where 'name' is the name of the child resource type and 'resource_type' is the corresponding resource type. """ name = None child_resource_type = None for name, value in partial_object.items(): if name == "entries": name, child_resource_type = ( self._check_entries(resource_type, value)) elif isinstance(value, Callable): # Performs an integrity check. self._get_method(resource_type, name) else: self._check_attribute(resource_type, name, value) return name, child_resource_type def _find_representation_id(self, resource_type, name): """Find the WADL XML id for the representation of C{resource_type}. Looks in the WADL for the first representiation associated with the method for a resource type. :return: An XML id (a string). """ get_method = self._get_method(resource_type, name) for response in get_method: for representation in response: representation_url = representation.get("href") if representation_url is not None: return self._application.lookup_xml_id(representation_url) def _check_attribute(self, resource_type, name, value): """ Ensure that C{value} is a valid C{name} attribute on C{resource_type}. Does this by finding the representation for the default, canonical GET method (as opposed to the many "named" GET methods that exist.) @param resource_type: The resource type to check the attribute against. @param name: The name of the attribute. @param value: The value to check. """ xml_id = self._find_representation_id(resource_type, 'get') self._check_attribute_representation(xml_id, name, value) def _check_attribute_representation(self, xml_id, name, value): """ Ensure that C{value} is a valid value for C{name} with the representation definition matching C{xml_id}. @param xml_id: The XML ID for the representation to check the attribute against. @param name: The name of the attribute. @param value: The value to check. @raises IntegrityError: Raised if C{name} is not a valid attribute name or if C{value}'s type is not valid for the attribute. """ representation = self._application.representation_definitions[xml_id] parameters = dict((child.get("name"), child) for child in representation.tag) if name not in parameters: raise IntegrityError("%s not found" % name) parameter = parameters[name] data_type = parameter.get("type") if data_type is None: if not isinstance(value, basestring): raise IntegrityError( "%s is not a str or unicode for %s" % (value, name)) elif data_type == "xsd:dateTime": if not isinstance(value, datetime): raise IntegrityError( "%s is not a datetime for %s" % (value, name)) def _get_method(self, resource_type, name): """Get the C{name} method on C{resource_type}. @param resource_type: The method's resource type. @param name: The name of the method. @raises IntegrityError: Raised if a method called C{name} is not available on C{resource_type}. @return: The XML element for the method from the WADL. """ if name in self.special_methods: return resource_name = resource_type.tag.get("id") xml_id = "%s-%s" % (resource_name, name) try: [get_method] = find_by_attribute(resource_type.tag, 'id', xml_id) except ValueError: raise IntegrityError( "%s is not a method of %s" % (name, resource_name)) return get_method def _run_method(self, name, method, *args, **kwargs): """Run a method and convert its result into a L{FakeResource}. If the result represents an object it is validated against the WADL definition before being returned. @param name: The name of the method. @param method: A callable. @param args: Arguments to pass to the callable. @param kwargs: Keyword arguments to pass to the callable. @return: A L{FakeResource} representing the result if it's an object. @raises IntegrityError: Raised if the return value from the method isn't valid. """ result = method(*args, **kwargs) if name in self.special_methods: return result else: return self._create_resource(self._resource_type, name, result) def _create_resource(self, resource_type, name, result): """Create a new L{FakeResource} for C{resource_type} method call result. @param resource_type: The resource type of the method. @param name: The name of the method on C{resource_type}. @param result: The result of calling the method. @raises IntegrityError: Raised if C{result} is an invalid return value for the method. @return: A L{FakeResource} for C{result}. """ resource_name = resource_type.tag.get("id") if resource_name == name: name = "get" xml_id = self._find_representation_id(resource_type, name) xml_id = strip_suffix(xml_id, '-full') if xml_id not in self._application.resource_types: xml_id += '-resource' result_resource_type = self._application.resource_types[xml_id] self._check_resource_type(result_resource_type, result) # XXX: Should this wrap in collection? return FakeResource(self._application, result_resource_type, result) def _get_child_resource_type(self, resource_type): """Get the name and resource type for the entries in a collection. @param resource_type: The resource type for a collection. @return: (name, resource_type), where 'name' is the name of the child resource type and 'resource_type' is the corresponding resource type. """ xml_id = self._find_representation_id(resource_type, 'get') representation_definition = ( self._application.representation_definitions[xml_id]) [entry_links] = find_by_attribute( representation_definition.tag, 'name', 'entry_links') [resource_type] = list(entry_links) resource_type_url = resource_type.get("resource_type") resource_type_name = resource_type_url.split("#")[1] return ( resource_type_name, self._application.get_resource_type(resource_type_url)) def _check_entries(self, resource_type, entries): """Ensure that C{entries} are valid for a C{resource_type} collection. @param resource_type: The resource type of the collection the entries are in. @param entries: A list of dicts representing objects in the collection. @return: (name, resource_type), where 'name' is the name of the child resource type and 'resource_type' is the corresponding resource type. """ name, child_resource_type = self._get_child_resource_type(resource_type) for entry in entries: self._check_resource_type(child_resource_type, entry) return name, child_resource_type def __repr__(self): """ The resource type, identifier if available, and memory address are used to generate a representation of this fake resource. """ name = self._resource_type.tag.get("id") key = "object" key = self._values.get("id", key) key = self._values.get("name", key) return "<%s %s %s at %s>" % ( self.__class__.__name__, name, key, hex(id(self))) class FakeRoot(FakeResource): """Fake root object for an application.""" def __init__(self, application): """Create a L{FakeResource} for the service root of C{application}. @param application: A C{wadllib.application.Application} instance. """ resource_type = application.get_resource_type( application.markup_url + "#service-root") super(FakeRoot, self).__init__(application, resource_type) class FakeEntry(FakeResource): """A fake resource for an entry.""" class FakeCollection(FakeResource): """A fake resource for a collection.""" def __init__(self, application, resource_type, values=None, name=None, child_resource_type=None): super(FakeCollection, self).__init__(application, resource_type, values) self.__dict__.update({"_name": name, "_child_resource_type": child_resource_type}) def __iter__(self): """Iterate items if this resource has an C{entries} attribute.""" entries = self._values.get("entries", ()) for entry in entries: yield self._create_resource(self._child_resource_type, self._name, entry) def __getitem__(self, key): """Look up a slice, or a subordinate resource by index. @param key: An individual object key or a C{slice}. @raises IndexError: Raised if an invalid key is provided. @return: A L{FakeResource} instance for the entry matching C{key}. """ entries = list(self) if isinstance(key, slice): start = key.start or 0 stop = key.stop if start < 0: raise ValueError("Collection slices must have a nonnegative " "start point.") if stop < 0: raise ValueError("Collection slices must have a definite, " "nonnegative end point.") return entries.__getitem__(key) elif isinstance(key, int): return entries.__getitem__(key) else: raise IndexError("Do not support index lookups yet.") ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/src/launchpadlib/testing/resources.py0000644000175000017500000000372000000000000025266 0ustar00cjwatsoncjwatson00000000000000# Copyright 2008, 2011 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # launchpadlib is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with launchpadlib. If not, see # . """Resources for use in unit tests with the C{testresources} module.""" from pkg_resources import resource_string from testresources import TestResource from wadllib.application import Application from launchpadlib.testing.launchpad import FakeLaunchpad launchpad_testing_application = None def get_application(): """Get or create a WADL application for testing Launchpad. Note that this uses the Launchpad v1.0 WADL bundled with launchpadlib for testing purposes. For your own application, you might want to construct an L{Application} object directly, giving it your own WADL. """ global launchpad_testing_application if launchpad_testing_application is None: markup_url = "https://api.launchpad.net/1.0/" markup = resource_string("launchpadlib.testing", "launchpad-wadl.xml") launchpad_testing_application = Application(markup_url, markup) return launchpad_testing_application class FakeLaunchpadResource(TestResource): def make(self, dependency_resources): return FakeLaunchpad( application=Application( "https://api.example.com/testing/", resource_string("launchpadlib.testing", "testing-wadl.xml"))) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/src/launchpadlib/testing/testing-wadl.xml0000644000175000017500000003023300000000000026025 0ustar00cjwatsoncjwatson00000000000000 ]> A Bazaar branch. Interface representing the set of branches. Application root for malone. The core bug entry. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5192525 launchpadlib-1.10.13/src/launchpadlib/testing/tests/0000755000175000017500000000000000000000000024042 5ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/src/launchpadlib/testing/tests/__init__.py0000644000175000017500000000000000000000000026141 0ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1436278060.0 launchpadlib-1.10.13/src/launchpadlib/testing/tests/test_launchpad.py0000644000175000017500000003710400000000000027417 0ustar00cjwatsoncjwatson00000000000000# Copyright 2008 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # launchpadlib is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with launchpadlib. If not, see # . from datetime import datetime from testresources import ResourcedTestCase from launchpadlib.testing.launchpad import ( FakeLaunchpad, FakeResource, FakeRoot, IntegrityError, ) from launchpadlib.testing.resources import ( FakeLaunchpadResource, get_application) class FakeRootTest(ResourcedTestCase): def test_create_root_resource(self): root_resource = FakeRoot(get_application()) self.assertTrue(isinstance(root_resource, FakeResource)) class FakeResourceTest(ResourcedTestCase): resources = [("launchpad", FakeLaunchpadResource())] def test_repr(self): """A custom C{__repr__} is provided for L{FakeResource}s.""" branches = dict(total_size="test-branch") self.launchpad.me = dict(getBranches=lambda statuses: branches) branches = self.launchpad.me.getBranches([]) obj_id = hex(id(branches)) self.assertEqual( "" % obj_id, repr(branches)) def test_repr_with_name(self): """ If the fake has a C{name} property it's included in the repr string to make it easier to figure out what it is. """ self.launchpad.me = dict(name="foo") person = self.launchpad.me self.assertEqual("" % hex(id(person)), repr(person)) def test_repr_with_id(self): """ If the fake has an C{id} property it's included in the repr string to make it easier to figure out what it is. """ bug = dict(id="1", title="Bug #1") self.launchpad.bugs = dict(entries=[bug]) [bug] = list(self.launchpad.bugs) self.assertEqual("" % hex(id(bug)), repr(bug)) class FakeLaunchpadTest(ResourcedTestCase): resources = [("launchpad", FakeLaunchpadResource())] def test_wb_instantiate_without_application(self): """ The builtin WADL definition is used if the C{application} is not provided during instantiation. """ credentials = object() launchpad = FakeLaunchpad(credentials) self.assertEqual(credentials, launchpad.credentials) self.assertEqual(get_application(), launchpad._application) def test_instantiate_with_everything(self): """ L{FakeLaunchpad} takes the same parameters as L{Launchpad} during instantiation, with the addition of an C{application} parameter. The optional parameters are discarded when the object is instantiated. """ credentials = object() launchpad = FakeLaunchpad(credentials, service_root=None, cache=None, timeout=None, proxy_info=None, application=get_application()) self.assertEqual(credentials, launchpad.credentials) def test_instantiate_with_credentials(self): """A L{FakeLaunchpad} can be instantiated with credentials.""" credentials = object() launchpad = FakeLaunchpad(credentials, application=get_application()) self.assertEqual(credentials, launchpad.credentials) def test_instantiate_without_credentials(self): """ A L{FakeLaunchpad} instantiated without credentials has its C{credentials} attribute set to C{None}. """ self.assertIsNone(self.launchpad.credentials) def test_set_undefined_property(self): """ An L{IntegrityError} is raised if an attribute is set on a L{FakeLaunchpad} instance that isn't present in the WADL definition. """ self.assertRaises(IntegrityError, setattr, self.launchpad, "foo", "bar") def test_get_undefined_resource(self): """ An L{AttributeError} is raised if an attribute is accessed on a L{FakeLaunchpad} instance that doesn't exist. """ self.launchpad.me = dict(display_name="Foo") self.assertRaises(AttributeError, getattr, self.launchpad.me, "name") def test_string_property(self): """ Sample data can be created by setting L{FakeLaunchpad} attributes with dicts that represent objects. Plain string values can be represented as C{str} values. """ self.launchpad.me = dict(name="foo") self.assertEqual("foo", self.launchpad.me.name) def test_unicode_property(self): """ Sample data can be created by setting L{FakeLaunchpad} attributes with dicts that represent objects. Plain string values can be represented as C{unicode} strings. """ self.launchpad.me = dict(name=u"foo") self.assertEqual(u"foo", self.launchpad.me.name) def test_datetime_property(self): """ Attributes that represent dates are set with C{datetime} instances. """ now = datetime.utcnow() self.launchpad.me = dict(date_created=now) self.assertEqual(now, self.launchpad.me.date_created) def test_invalid_datetime_property(self): """ Only C{datetime} values can be set on L{FakeLaunchpad} instances for attributes that represent dates. """ self.assertRaises(IntegrityError, setattr, self.launchpad, "me", dict(date_created="now")) def test_multiple_string_properties(self): """ Sample data can be created by setting L{FakeLaunchpad} attributes with dicts that represent objects. """ self.launchpad.me = dict(name="foo", display_name="Foo") self.assertEqual("foo", self.launchpad.me.name) self.assertEqual("Foo", self.launchpad.me.display_name) def test_invalid_property_name(self): """ Sample data set on a L{FakeLaunchpad} instance is validated against the WADL definition. If a key is defined on a resource that doesn't match a related parameter, an L{IntegrityError} is raised. """ self.assertRaises(IntegrityError, setattr, self.launchpad, "me", dict(foo="bar")) def test_invalid_property_value(self): """ The types of sample data values set on L{FakeLaunchpad} instances are validated against types defined in the WADL definition. """ self.assertRaises(IntegrityError, setattr, self.launchpad, "me", dict(name=102)) def test_callable(self): """ A callable set on a L{FakeLaunchpad} instance is validated against the WADL definition, to make sure a matching method exists. """ branches = dict(total_size="test-branch") self.launchpad.me = dict(getBranches=lambda statuses: branches) self.assertNotEqual(None, self.launchpad.me.getBranches([])) def test_invalid_callable_name(self): """ An L{IntegrityError} is raised if a method is defined on a resource that doesn't match a method defined in the WADL definition. """ self.assertRaises(IntegrityError, setattr, self.launchpad, "me", dict(foo=lambda: None)) def test_callable_object_return_type(self): """ The result of a fake method is a L{FakeResource}, automatically created from the object used to define the return object. """ branches = dict(total_size="8") self.launchpad.me = dict(getBranches=lambda statuses: branches) branches = self.launchpad.me.getBranches([]) self.assertTrue(isinstance(branches, FakeResource)) self.assertEqual("8", branches.total_size) def test_invalid_callable_object_return_type(self): """ An L{IntegrityError} is raised if a method returns an invalid result. """ branches = dict(total_size=8) self.launchpad.me = dict(getBranches=lambda statuses: branches) self.assertRaises(IntegrityError, self.launchpad.me.getBranches, []) def test_collection_property(self): """ Sample collections can be set on L{FakeLaunchpad} instances. They are validated the same way other sample data is validated. """ branch = dict(name="foo") self.launchpad.branches = dict(getByUniqueName=lambda name: branch) branch = self.launchpad.branches.getByUniqueName("foo") self.assertEqual("foo", branch.name) def test_iterate_collection(self): """ Data for a sample collection set on a L{FakeLaunchpad} instance can be iterated over if an C{entries} key is defined. """ bug = dict(id="1", title="Bug #1") self.launchpad.bugs = dict(entries=[bug]) bugs = list(self.launchpad.bugs) self.assertEqual(1, len(bugs)) bug = bugs[0] self.assertEqual("1", bug.id) self.assertEqual("Bug #1", bug.title) def test_collection_with_invalid_entries(self): """ Sample data for each entry in a collection is validated when it's set on a L{FakeLaunchpad} instance. """ bug = dict(foo="bar") self.assertRaises(IntegrityError, setattr, self.launchpad, "bugs", dict(entries=[bug])) def test_slice_collection(self): """ Data for a sample collection set on a L{FakeLaunchpad} instance can be sliced if an C{entries} key is defined. """ bug1 = dict(id="1", title="Bug #1") bug2 = dict(id="2", title="Bug #2") bug3 = dict(id="3", title="Bug #3") self.launchpad.bugs = dict(entries=[bug1, bug2, bug3]) bugs = self.launchpad.bugs[1:3] self.assertEqual(2, len(bugs)) self.assertEqual("2", bugs[0].id) self.assertEqual("3", bugs[1].id) def test_slice_collection_with_negative_start(self): """ A C{ValueError} is raised if a negative start value is used when slicing a sample collection set on a L{FakeLaunchpad} instance. """ bug1 = dict(id="1", title="Bug #1") bug2 = dict(id="2", title="Bug #2") self.launchpad.bugs = dict(entries=[bug1, bug2]) self.assertRaises(ValueError, lambda: self.launchpad.bugs[-1:]) self.assertRaises(ValueError, lambda: self.launchpad.bugs[-1:2]) def test_slice_collection_with_negative_stop(self): """ A C{ValueError} is raised if a negative stop value is used when slicing a sample collection set on a L{FakeLaunchpad} instance. """ bug1 = dict(id="1", title="Bug #1") bug2 = dict(id="2", title="Bug #2") self.launchpad.bugs = dict(entries=[bug1, bug2]) self.assertRaises(ValueError, lambda: self.launchpad.bugs[:-1]) self.assertRaises(ValueError, lambda: self.launchpad.bugs[0:-1]) def test_subscript_operator_out_of_range(self): """ An C{IndexError} is raised if an invalid index is used when retrieving data from a sample collection. """ bug1 = dict(id="1", title="Bug #1") self.launchpad.bugs = dict(entries=[bug1]) self.assertRaises(IndexError, lambda: self.launchpad.bugs[2]) def test_replace_property(self): """Values already set on fake resource objects can be replaced.""" self.launchpad.me = dict(name="foo") person = self.launchpad.me self.assertEqual("foo", person.name) person.name = "bar" self.assertEqual("bar", person.name) self.assertEqual("bar", self.launchpad.me.name) def test_replace_method(self): """Methods already set on fake resource objects can be replaced.""" branch1 = dict(name="foo", bzr_identity="lp:~user/project/branch1") branch2 = dict(name="foo", bzr_identity="lp:~user/project/branch2") self.launchpad.branches = dict(getByUniqueName=lambda name: branch1) self.launchpad.branches.getByUniqueName = lambda name: branch2 branch = self.launchpad.branches.getByUniqueName("foo") self.assertEqual("lp:~user/project/branch2", branch.bzr_identity) def test_replace_property_with_invalid_value(self): """Values set on fake resource objects are validated.""" self.launchpad.me = dict(name="foo") person = self.launchpad.me self.assertRaises(IntegrityError, setattr, person, "name", 1) def test_replace_resource(self): """Resources already set on L{FakeLaunchpad} can be replaced.""" self.launchpad.me = dict(name="foo") self.assertEqual("foo", self.launchpad.me.name) self.launchpad.me = dict(name="bar") self.assertEqual("bar", self.launchpad.me.name) def test_add_property(self): """Sample data set on a L{FakeLaunchpad} instance can be added to.""" self.launchpad.me = dict(name="foo") person = self.launchpad.me person.display_name = "Foo" self.assertEqual("foo", person.name) self.assertEqual("Foo", person.display_name) self.assertEqual("foo", self.launchpad.me.name) self.assertEqual("Foo", self.launchpad.me.display_name) def test_add_property_to_empty_object(self): """An empty object can be used when creating sample data.""" self.launchpad.me = dict() self.assertRaises(AttributeError, getattr, self.launchpad.me, "name") self.launchpad.me.name = "foo" self.assertEqual("foo", self.launchpad.me.name) def test_login(self): """ L{FakeLaunchpad.login} ignores all parameters and returns a new instance using the builtin WADL definition. """ launchpad = FakeLaunchpad.login("name", "token", "secret") self.assertTrue(isinstance(launchpad, FakeLaunchpad)) def test_get_token_and_login(self): """ L{FakeLaunchpad.get_token_and_login} ignores all parameters and returns a new instance using the builtin WADL definition. """ launchpad = FakeLaunchpad.get_token_and_login("name") self.assertTrue(isinstance(launchpad, FakeLaunchpad)) def test_login_with(self): """ L{FakeLaunchpad.login_with} ignores all parameters and returns a new instance using the builtin WADL definition. """ launchpad = FakeLaunchpad.login_with("name") self.assertTrue(isinstance(launchpad, FakeLaunchpad)) def test_lp_save(self): """ Sample object have an C{lp_save} method that is a no-op by default. """ self.launchpad.me = dict(name="foo") self.assertTrue(self.launchpad.me.lp_save()) def test_custom_lp_save(self): """A custom C{lp_save} method can be set on a L{FakeResource}.""" self.launchpad.me = dict(name="foo", lp_save=lambda: "custom") self.assertEqual("custom", self.launchpad.me.lp_save()) def test_set_custom_lp_save(self): """ A custom C{lp_save} method can be set on a L{FakeResource} after its been created. """ self.launchpad.me = dict(name="foo") self.launchpad.me.lp_save = lambda: "custom" self.assertEqual("custom", self.launchpad.me.lp_save()) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5232527 launchpadlib-1.10.13/src/launchpadlib/tests/0000755000175000017500000000000000000000000022365 5ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1340708447.0 launchpadlib-1.10.13/src/launchpadlib/tests/__init__.py0000644000175000017500000000130200000000000024472 0ustar00cjwatsoncjwatson00000000000000# Copyright 2008 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . """Tests for launchpadlib""" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1580826952.0 launchpadlib-1.10.13/src/launchpadlib/tests/test_credential_store.py0000644000175000017500000002122100000000000027322 0ustar00cjwatsoncjwatson00000000000000# Copyright 2010-2011 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . """Tests for the credential store classes.""" import os import tempfile import unittest from base64 import b64decode if bytes is str: # Python 2 unicode_type = unicode else: unicode_type = str from launchpadlib.testing.helpers import ( fake_keyring, InMemoryKeyring, ) from launchpadlib.credentials import ( AccessToken, Credentials, KeyringCredentialStore, UnencryptedFileCredentialStore, ) class TestAccessToken(unittest.TestCase): """Tests for the AccessToken class.""" def test_from_string(self): access_token = AccessToken.from_string( "oauth_token_secret=secret%3Dpassword&oauth_token=lock%26key") self.assertEqual("lock&key", access_token.key) self.assertEqual("secret=password", access_token.secret) self.assertIsNone(access_token.context) def test_from_string_with_context(self): access_token = AccessToken.from_string( "oauth_token_secret=secret%3Dpassword&oauth_token=lock%26key&" "lp.context=firefox") self.assertEqual("lock&key", access_token.key) self.assertEqual("secret=password", access_token.secret) self.assertEqual("firefox", access_token.context) class CredentialStoreTestCase(unittest.TestCase): def make_credential(self, consumer_key): """Helper method to make a fake credential.""" return Credentials( "app name", consumer_secret='consumer_secret:42', access_token=AccessToken(consumer_key, 'access_secret:168')) class TestUnencryptedFileCredentialStore(CredentialStoreTestCase): """Tests for the UnencryptedFileCredentialStore class.""" def setUp(self): ignore, self.filename = tempfile.mkstemp() self.store = UnencryptedFileCredentialStore(self.filename) def tearDown(self): if os.path.exists(self.filename): os.remove(self.filename) def test_save_and_load(self): # Make sure you can save and load credentials to a file. credential = self.make_credential("consumer key") self.store.save(credential, "unique key") credential2 = self.store.load("unique key") self.assertEqual(credential.consumer.key, credential2.consumer.key) def test_unique_id_doesnt_matter(self): # If a file contains a credential, that credential will be # accessed no matter what unique ID you specify. credential = self.make_credential("consumer key") self.store.save(credential, "some key") credential2 = self.store.load("some other key") self.assertEqual(credential.consumer.key, credential2.consumer.key) def test_file_only_contains_one_credential(self): # A credential file may contain only one credential. If you # write two credentials with different unique IDs to the same # file, the first credential will be overwritten with the # second. credential1 = self.make_credential("consumer key") credential2 = self.make_credential("consumer key2") self.store.save(credential1, "unique key 1") self.store.save(credential1, "unique key 2") loaded = self.store.load("unique key 1") self.assertEqual(loaded.consumer.key, credential2.consumer.key) class TestKeyringCredentialStore(CredentialStoreTestCase): """Tests for the KeyringCredentialStore class.""" def setUp(self): self.keyring = InMemoryKeyring() self.store = KeyringCredentialStore() def test_save_and_load(self): # Make sure you can save and load credentials to a keyring. with fake_keyring(self.keyring): credential = self.make_credential("consumer key") self.store.save(credential, "unique key") credential2 = self.store.load("unique key") self.assertEqual( credential.consumer.key, credential2.consumer.key) def test_lookup_by_unique_key(self): # Credentials in the keyring are looked up by the unique ID # under which they were stored. with fake_keyring(self.keyring): credential1 = self.make_credential("consumer key1") self.store.save(credential1, "key 1") credential2 = self.make_credential("consumer key2") self.store.save(credential2, "key 2") loaded1 = self.store.load("key 1") self.assertTrue(loaded1) self.assertEqual( credential1.consumer.key, loaded1.consumer.key) loaded2 = self.store.load("key 2") self.assertEqual( credential2.consumer.key, loaded2.consumer.key) def test_reused_unique_id_overwrites_old_credential(self): # Writing a credential to the keyring with a given unique ID # will overwrite any credential stored under that ID. with fake_keyring(self.keyring): credential1 = self.make_credential("consumer key1") self.store.save(credential1, "the only key") credential2 = self.make_credential("consumer key2") self.store.save(credential2, "the only key") loaded = self.store.load("the only key") self.assertEqual( credential2.consumer.key, loaded.consumer.key) def test_bad_unique_id_returns_none(self): # Trying to load a credential without providing a good unique # ID will get you None. with fake_keyring(self.keyring): self.assertIsNone(self.store.load("no such key")) def test_keyring_returns_unicode(self): # Kwallet is reported to sometimes return Unicode, which broke the # credentials parsing. This test ensures a Unicode password is # handled correctly. (See bug lp:877374) class UnicodeInMemoryKeyring(InMemoryKeyring): def get_password(self, service, username): password = super(UnicodeInMemoryKeyring, self).get_password( service, username) if isinstance(password, unicode_type): password = password.encode('utf-8') return password self.keyring = UnicodeInMemoryKeyring() with fake_keyring(self.keyring): credential = self.make_credential("consumer key") self.assertTrue(credential) # Shouldn't this test actually use a unicodish key?! self.store.save(credential, "unique key") credential2 = self.store.load("unique key") self.assertTrue(credential2) self.assertEqual( credential.consumer.key, credential2.consumer.key) self.assertEqual( credential.consumer.secret, credential2.consumer.secret) def test_nonencoded_key_handled(self): # For backwards compatibility with keys that are not base 64 encoded. class UnencodedInMemoryKeyring(InMemoryKeyring): def get_password(self, service, username): pw = super(UnencodedInMemoryKeyring, self).get_password( service, username) return b64decode(pw[5:]) self.keyring = UnencodedInMemoryKeyring() with fake_keyring(self.keyring): credential = self.make_credential("consumer key") self.store.save(credential, "unique key") credential2 = self.store.load("unique key") self.assertEqual( credential.consumer.key, credential2.consumer.key) self.assertEqual( credential.consumer.secret, credential2.consumer.secret) def test_corrupted_key_handled(self): # A corrupted password results in None being returned. class CorruptedInMemoryKeyring(InMemoryKeyring): def get_password(self, service, username): return "bad" self.keyring = CorruptedInMemoryKeyring() with fake_keyring(self.keyring): credential = self.make_credential("consumer key") self.store.save(credential, "unique key") credential2 = self.store.load("unique key") self.assertIsNone(credential2) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1436277990.0 launchpadlib-1.10.13/src/launchpadlib/tests/test_http.py0000644000175000017500000002204600000000000024761 0ustar00cjwatsoncjwatson00000000000000# Copyright 2010 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . """Tests for the LaunchpadOAuthAwareHTTP class.""" from collections import deque import tempfile import unittest try: from json import dumps JSONDecodeError = ValueError except ImportError: from simplejson import dumps, JSONDecodeError from launchpadlib.errors import Unauthorized from launchpadlib.credentials import UnencryptedFileCredentialStore from launchpadlib.launchpad import ( Launchpad, LaunchpadOAuthAwareHttp, ) from launchpadlib.testing.helpers import NoNetworkAuthorizationEngine # The simplest WADL that looks like a representation of the service root. SIMPLE_WADL = b''' ''' # The simplest JSON that looks like a representation of the service root. SIMPLE_JSON = dumps({}).encode('utf-8') class Response: """A fake HTTP response object.""" def __init__(self, status, content): self.status = status self.content = content class SimulatedResponsesHttp(LaunchpadOAuthAwareHttp): """Responds to HTTP requests by shifting responses off a stack.""" def __init__(self, responses, *args): """Constructor. :param responses: A list of HttpResponse objects to use in response to requests. """ super(SimulatedResponsesHttp, self).__init__(*args) self.sent_responses = [] self.unsent_responses = responses self.cache = None def _request(self, *args): response = self.unsent_responses.popleft() self.sent_responses.append(response) return self.retry_on_bad_token(response, response.content, *args) class SimulatedResponsesLaunchpad(Launchpad): # Every Http object generated by this class will return these # responses, in order. responses = [] def httpFactory(self, *args): return SimulatedResponsesHttp( deque(self.responses), self, self.authorization_engine, *args) @classmethod def credential_store_factory(cls, credential_save_failed): return UnencryptedFileCredentialStore( tempfile.mkstemp()[1], credential_save_failed) class SimulatedResponsesTestCase(unittest.TestCase): """Test cases that give fake responses to launchpad's HTTP requests.""" def setUp(self): """Clear out the list of simulated responses.""" SimulatedResponsesLaunchpad.responses = [] self.engine = NoNetworkAuthorizationEngine( 'http://api.example.com/', 'application name') def launchpad_with_responses(self, *responses): """Use simulated HTTP responses to get a Launchpad object. The given Response objects will be sent, in order, in response to launchpadlib's requests. :param responses: Some number of Response objects. :return: The Launchpad object, assuming that errors in the simulated requests didn't prevent one from being created. """ SimulatedResponsesLaunchpad.responses = responses return SimulatedResponsesLaunchpad.login_with( 'application name', authorization_engine=self.engine) class TestAbilityToParseData(SimulatedResponsesTestCase): """Test launchpadlib's ability to handle the sample data. To create a Launchpad object, two HTTP requests must succeed and return usable data: the requests for the WADL and JSON representations of the service root. This test shows that the minimal data in SIMPLE_WADL and SIMPLE_JSON is good enough to create a Launchpad object. """ def test_minimal_data(self): """Make sure that launchpadlib can use the minimal data.""" self.launchpad_with_responses( Response(200, SIMPLE_WADL), Response(200, SIMPLE_JSON)) def test_bad_wadl(self): """Show that bad WADL causes an exception.""" self.assertRaises( SyntaxError, self.launchpad_with_responses, Response(200, b"This is not WADL."), Response(200, SIMPLE_JSON)) def test_bad_json(self): """Show that bad JSON causes an exception.""" self.assertRaises( JSONDecodeError, self.launchpad_with_responses, Response(200, SIMPLE_WADL), Response(200, b"This is not JSON.")) class TestTokenFailureDuringRequest(SimulatedResponsesTestCase): """Test access token failures during a request. launchpadlib makes two HTTP requests on startup, to get the WADL and JSON representations of the service root. If Launchpad receives a 401 error during this process, it will acquire a fresh access token and try again. """ def test_good_token(self): """If our token is good, we never get another one.""" SimulatedResponsesLaunchpad.responses = [ Response(200, SIMPLE_WADL), Response(200, SIMPLE_JSON)] self.assertEqual(self.engine.access_tokens_obtained, 0) SimulatedResponsesLaunchpad.login_with( 'application name', authorization_engine=self.engine) self.assertEqual(self.engine.access_tokens_obtained, 1) def test_bad_token(self): """If our token is bad, we get another one.""" SimulatedResponsesLaunchpad.responses = [ Response(401, b"Invalid token."), Response(200, SIMPLE_WADL), Response(200, SIMPLE_JSON)] self.assertEqual(self.engine.access_tokens_obtained, 0) SimulatedResponsesLaunchpad.login_with( 'application name', authorization_engine=self.engine) self.assertEqual(self.engine.access_tokens_obtained, 2) def test_expired_token(self): """If our token is expired, we get another one.""" SimulatedResponsesLaunchpad.responses = [ Response(401, b"Expired token."), Response(200, SIMPLE_WADL), Response(200, SIMPLE_JSON)] self.assertEqual(self.engine.access_tokens_obtained, 0) SimulatedResponsesLaunchpad.login_with( 'application name', authorization_engine=self.engine) self.assertEqual(self.engine.access_tokens_obtained, 2) def test_unknown_token(self): """If our token is unknown, we get another one.""" SimulatedResponsesLaunchpad.responses = [ Response(401, b"Unknown access token."), Response(200, SIMPLE_WADL), Response(200, SIMPLE_JSON)] self.assertEqual(self.engine.access_tokens_obtained, 0) SimulatedResponsesLaunchpad.login_with( 'application name', authorization_engine=self.engine) self.assertEqual(self.engine.access_tokens_obtained, 2) def test_delayed_error(self): """We get another token no matter when the error happens.""" SimulatedResponsesLaunchpad.responses = [ Response(200, SIMPLE_WADL), Response(401, b"Expired token."), Response(200, SIMPLE_JSON)] self.assertEqual(self.engine.access_tokens_obtained, 0) SimulatedResponsesLaunchpad.login_with( 'application name', authorization_engine=self.engine) self.assertEqual(self.engine.access_tokens_obtained, 2) def test_many_errors(self): """We'll keep getting new tokens as long as tokens are the problem.""" SimulatedResponsesLaunchpad.responses = [ Response(401, b"Invalid token."), Response(200, SIMPLE_WADL), Response(401, b"Expired token."), Response(401, b"Invalid token."), Response(200, SIMPLE_JSON)] self.assertEqual(self.engine.access_tokens_obtained, 0) SimulatedResponsesLaunchpad.login_with( 'application name', authorization_engine=self.engine) self.assertEqual(self.engine.access_tokens_obtained, 4) def test_other_unauthorized(self): """If the token is not at fault, a 401 error raises an exception.""" SimulatedResponsesLaunchpad.responses = [ Response(401, b"Some other error.")] self.assertRaises( Unauthorized, SimulatedResponsesLaunchpad.login_with, 'application name', authorization_engine=self.engine) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288570.0 launchpadlib-1.10.13/src/launchpadlib/tests/test_launchpad.py0000644000175000017500000007635300000000000025753 0ustar00cjwatsoncjwatson00000000000000# Copyright 2009, 2011 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . """Tests for the Launchpad class.""" __metaclass__ = type from contextlib import contextmanager import os import shutil import socket import stat import tempfile import unittest try: from unittest.mock import patch except ImportError: from mock import patch import warnings from lazr.restfulclient.resource import ServiceRoot from launchpadlib.credentials import ( AccessToken, Credentials, ) from launchpadlib import uris import launchpadlib.launchpad from launchpadlib.launchpad import Launchpad from launchpadlib.testing.helpers import ( assert_keyring_not_imported, BadSaveKeyring, fake_keyring, FauxSocketModule, InMemoryKeyring, NoNetworkAuthorizationEngine, NoNetworkLaunchpad, ) from launchpadlib.credentials import ( KeyringCredentialStore, ) # A dummy service root for use in tests SERVICE_ROOT = "http://api.example.com/" class TestResourceTypeClasses(unittest.TestCase): """launchpadlib must know about restfulclient's resource types.""" def test_resource_types(self): # Make sure that Launchpad knows about every special resource # class defined by lazr.restfulclient. for name, cls in ServiceRoot.RESOURCE_TYPE_CLASSES.items(): self.assertEqual(Launchpad.RESOURCE_TYPE_CLASSES[name], cls) class TestNameLookups(unittest.TestCase): """Test the utility functions in the 'uris' module.""" def setUp(self): self.aliases = sorted( ['production', 'qastaging', 'staging', 'dogfood', 'dev', 'test_dev', 'edge']) @contextmanager def edge_deprecation_error(self): # Run some code and assert that a deprecation error was issued # due to attempted access to the edge server. with warnings.catch_warnings(record=True) as caught: warnings.simplefilter("always") yield self.assertEqual(len(caught), 1) warning, = caught self.assertTrue(issubclass(warning.category, DeprecationWarning)) self.assertIn("no longer exists", str(warning)) def test_short_names(self): # Ensure the short service names are all supported. self.assertEqual(sorted(uris.service_roots.keys()), self.aliases) self.assertEqual(sorted(uris.web_roots.keys()), self.aliases) def test_edge_service_root_is_production(self): # The edge server no longer exists, so if the client wants # edge we give them production. with self.edge_deprecation_error(): self.assertEqual(uris.lookup_service_root('edge'), uris.lookup_service_root('production')) def test_edge_web_root_is_production(self): # The edge server no longer exists, so if the client wants # edge we give them production. with self.edge_deprecation_error(): self.assertEqual(uris.lookup_web_root('edge'), uris.lookup_web_root('production')) def test_edge_service_root_url_becomes_production(self): with self.edge_deprecation_error(): self.assertEqual(uris.lookup_service_root(uris.EDGE_SERVICE_ROOT), uris.lookup_service_root('production')) def test_edge_web_root_url_becomes_production(self): with self.edge_deprecation_error(): self.assertEqual(uris.lookup_web_root(uris.EDGE_WEB_ROOT), uris.lookup_web_root('production')) def test_top_level_edge_constant_becomes_production(self): with self.edge_deprecation_error(): self.assertEqual(uris.lookup_service_root(uris.EDGE_SERVICE_ROOT), uris.lookup_service_root('production')) def test_edge_server_equivalent_string_becomes_production(self): with self.edge_deprecation_error(): self.assertEqual( uris.lookup_service_root('https://api.edge.launchpad.net/'), uris.lookup_service_root('production')) def test_edge_web_server_equivalent_string_becomes_production(self): with self.edge_deprecation_error(): self.assertEqual( uris.lookup_web_root('https://edge.launchpad.net/'), uris.lookup_web_root('production')) def test_lookups(self): """Ensure that short service names turn into long service names.""" # If the service name is a known alias, lookup methods convert # it to a URL. with self.edge_deprecation_error(): for alias in self.aliases: self.assertEqual( uris.lookup_service_root(alias), uris.service_roots[alias]) with self.edge_deprecation_error(): for alias in self.aliases: self.assertEqual( uris.lookup_web_root(alias), uris.web_roots[alias]) # If the service name is a valid URL, lookup methods let it # through. other_root = "http://some-other-server.com" self.assertEqual(uris.lookup_service_root(other_root), other_root) self.assertEqual(uris.lookup_web_root(other_root), other_root) # Otherwise, lookup methods raise an exception. not_a_url = "not-a-url" self.assertRaises(ValueError, uris.lookup_service_root, not_a_url) self.assertRaises(ValueError, uris.lookup_web_root, not_a_url) class TestServiceNameWithEmbeddedVersion(unittest.TestCase): """Reject service roots that include the version at the end of the URL. If the service root is "http://api.launchpad.net/beta/" and the version is "beta", the launchpadlib constructor will raise an exception. This happens with scripts that were written against old versions of launchpadlib. The alternative is to try to silently fix it (the fix will eventually break as new versions of the web service are released) or to go ahead and make a request to http://api.launchpad.net/beta/beta/, and cause an unhelpful 404 error. """ def test_service_name_with_embedded_version(self): # Basic test. If there were no exception raised here, # launchpadlib would make a request to # /version-foo/version-foo. version = "version-foo" root = uris.service_roots['staging'] + version try: Launchpad(None, None, None, service_root=root, version=version) except ValueError as e: self.assertTrue(str(e).startswith( "It looks like you're using a service root that incorporates " 'the name of the web service version ("version-foo")')) else: raise AssertionError( "Expected a ValueError that was not thrown!") # Make sure the problematic URL is caught even if it has a # slash on the end. root += '/' self.assertRaises(ValueError, Launchpad, None, None, None, service_root=root, version=version) # Test that the default version has the same problem # when no explicit version is specified default_version = NoNetworkLaunchpad.DEFAULT_VERSION root = uris.service_roots['staging'] + default_version + '/' self.assertRaises(ValueError, Launchpad, None, None, None, service_root=root) class TestRequestTokenAuthorizationEngine(unittest.TestCase): """Tests for the RequestTokenAuthorizationEngine class.""" def test_app_must_be_identified(self): self.assertRaises( ValueError, NoNetworkAuthorizationEngine, SERVICE_ROOT) def test_application_name_identifies_app(self): NoNetworkAuthorizationEngine(SERVICE_ROOT, application_name='name') def test_consumer_name_identifies_app(self): NoNetworkAuthorizationEngine(SERVICE_ROOT, consumer_name='name') def test_conflicting_app_identification(self): # You can't specify both application_name and consumer_name. self.assertRaises( ValueError, NoNetworkAuthorizationEngine, SERVICE_ROOT, application_name='name1', consumer_name='name2') # This holds true even if you specify the same value for # both. They're not the same thing. self.assertRaises( ValueError, NoNetworkAuthorizationEngine, SERVICE_ROOT, application_name='name', consumer_name='name') class TestLaunchpadLoginWithCredentialsFile(unittest.TestCase): """Tests for Launchpad.login_with() with a credentials file.""" def test_filename(self): ignore, filename = tempfile.mkstemp() launchpad = NoNetworkLaunchpad.login_with( application_name='not important', credentials_file=filename) # The credentials are stored unencrypted in the file you # specify. credentials = Credentials.load_from_path(filename) self.assertEqual(credentials.consumer.key, launchpad.credentials.consumer.key) os.remove(filename) def test_cannot_specify_both_filename_and_store(self): ignore, filename = tempfile.mkstemp() store = KeyringCredentialStore() self.assertRaises( ValueError, NoNetworkLaunchpad.login_with, application_name='not important', credentials_file=filename, credential_store=store) os.remove(filename) class KeyringTest(unittest.TestCase): """Base class for tests that use the keyring.""" def setUp(self): # The real keyring package should never be imported during tests. assert_keyring_not_imported() # For these tests we want to use a dummy keyring implementation # that only stores data in memory. launchpadlib.credentials.keyring = InMemoryKeyring() def tearDown(self): # Remove the fake keyring module we injected during setUp. del launchpadlib.credentials.keyring class TestLaunchpadLoginWith(KeyringTest): """Tests for Launchpad.login_with().""" def setUp(self): super(TestLaunchpadLoginWith, self).setUp() self.temp_dir = tempfile.mkdtemp() def tearDown(self): super(TestLaunchpadLoginWith, self).tearDown() shutil.rmtree(self.temp_dir) def test_dirs_created(self): # The path we pass into login_with() is the directory where # cache for all service roots are stored. launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') NoNetworkLaunchpad.login_with( 'not important', service_root=SERVICE_ROOT, launchpadlib_dir=launchpadlib_dir) # The 'launchpadlib' dir got created. self.assertTrue(os.path.isdir(launchpadlib_dir)) # A directory for the passed in service root was created. service_path = os.path.join(launchpadlib_dir, 'api.example.com') self.assertTrue(os.path.isdir(service_path)) # Inside the service root directory, there is a 'cache' # directory. self.assertTrue( os.path.isdir(os.path.join(service_path, 'cache'))) # In older versions there was also a 'credentials' directory, # but no longer. credentials_path = os.path.join(service_path, 'credentials') self.assertFalse(os.path.isdir(credentials_path)) def test_dirs_created_are_changed_to_secure(self): launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') # Verify a newly created-by-hand directory is insecure os.mkdir(launchpadlib_dir) os.chmod(launchpadlib_dir, 0o755) self.assertTrue(os.path.isdir(launchpadlib_dir)) statinfo = os.stat(launchpadlib_dir) mode = stat.S_IMODE(statinfo.st_mode) self.assertNotEqual(mode, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC) NoNetworkLaunchpad.login_with( 'not important', service_root=SERVICE_ROOT, launchpadlib_dir=launchpadlib_dir) # Verify the mode has been changed to 0700 statinfo = os.stat(launchpadlib_dir) mode = stat.S_IMODE(statinfo.st_mode) self.assertEqual(mode, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC) def test_dirs_created_are_secure(self): launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') NoNetworkLaunchpad.login_with( 'not important', service_root=SERVICE_ROOT, launchpadlib_dir=launchpadlib_dir) self.assertTrue(os.path.isdir(launchpadlib_dir)) # Verify the mode is safe statinfo = os.stat(launchpadlib_dir) mode = stat.S_IMODE(statinfo.st_mode) self.assertEqual(mode, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC) def test_version_is_propagated(self): # Make sure the login_with() method conveys the 'version' # argument all the way to the Launchpad object. The # credentials will be cached to disk. launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') launchpad = NoNetworkLaunchpad.login_with( 'not important', service_root=SERVICE_ROOT, launchpadlib_dir=launchpadlib_dir, version="foo") self.assertEqual(launchpad.passed_in_args['version'], 'foo') # Now execute the same test a second time. This time, the # credentials are loaded from disk and a different code path # is executed. We want to make sure this code path propagates # the 'version' argument. launchpad = NoNetworkLaunchpad.login_with( 'not important', service_root=SERVICE_ROOT, launchpadlib_dir=launchpadlib_dir, version="bar") self.assertEqual(launchpad.passed_in_args['version'], 'bar') def test_application_name_is_propagated(self): # Create a Launchpad instance for a given application name. # Credentials are stored, but they don't include the # application name, since multiple applications may share a # single system-wide credential. launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') launchpad = NoNetworkLaunchpad.login_with( 'very important', service_root=SERVICE_ROOT, launchpadlib_dir=launchpadlib_dir) self.assertEqual( launchpad.credentials.consumer.application_name, 'very important') # Now execute the same test a second time. This time, the # credentials are loaded from disk and a different code path # is executed. We want to make sure this code path propagates # the application name, instead of picking an empty one from # disk. launchpad = NoNetworkLaunchpad.login_with( 'very important', service_root=SERVICE_ROOT, launchpadlib_dir=launchpadlib_dir) self.assertEqual( launchpad.credentials.consumer.application_name, 'very important') def test_authorization_engine_is_propagated(self): # You can pass in a custom authorization engine, which will be # used to get a request token and exchange it for an access # token. engine = NoNetworkAuthorizationEngine( SERVICE_ROOT, 'application name') NoNetworkLaunchpad.login_with(authorization_engine=engine) self.assertEqual(engine.request_tokens_obtained, 1) self.assertEqual(engine.access_tokens_obtained, 1) def test_login_with_must_identify_application(self): # If you call login_with without identifying your application # you'll get an error. self.assertRaises(ValueError, NoNetworkLaunchpad.login_with) def test_application_name_identifies_app(self): # If you pass in application_name, that's good enough to identify # your application. NoNetworkLaunchpad.login_with(application_name="name") def test_consumer_name_identifies_app(self): # If you pass in consumer_name, that's good enough to identify # your application. NoNetworkLaunchpad.login_with(consumer_name="name") def test_inconsistent_application_name_rejected(self): """Catch an attempt to specify inconsistent application_names.""" engine = NoNetworkAuthorizationEngine( SERVICE_ROOT, 'application name1') self.assertRaises(ValueError, NoNetworkLaunchpad.login_with, "application name2", authorization_engine=engine) def test_inconsistent_consumer_name_rejected(self): """Catch an attempt to specify inconsistent application_names.""" engine = NoNetworkAuthorizationEngine( SERVICE_ROOT, None, consumer_name="consumer_name1") self.assertRaises(ValueError, NoNetworkLaunchpad.login_with, "consumer_name2", authorization_engine=engine) def test_inconsistent_allow_access_levels_rejected(self): """Catch an attempt to specify inconsistent allow_access_levels.""" engine = NoNetworkAuthorizationEngine( SERVICE_ROOT, consumer_name="consumer", allow_access_levels=['FOO']) self.assertRaises(ValueError, NoNetworkLaunchpad.login_with, None, consumer_name="consumer", allow_access_levels=['BAR'], authorization_engine=engine) def test_inconsistent_credential_save_failed(self): # Catch an attempt to specify inconsistent callbacks for # credential save failure. def callback1(): pass store = KeyringCredentialStore(credential_save_failed=callback1) def callback2(): pass self.assertRaises(ValueError, NoNetworkLaunchpad.login_with, "app name", credential_store=store, credential_save_failed=callback2) def test_non_desktop_integration(self): # When doing a non-desktop integration, you must specify a # consumer_name. You can pass a list of allowable access # levels into login_with(). launchpad = NoNetworkLaunchpad.login_with( consumer_name="consumer", allow_access_levels=['FOO']) self.assertEqual(launchpad.credentials.consumer.key, "consumer") self.assertEqual(launchpad.credentials.consumer.application_name, None) self.assertEqual(launchpad.authorization_engine.allow_access_levels, ['FOO']) def test_desktop_integration_doesnt_happen_without_consumer_name(self): # The only way to do a non-desktop integration is to specify a # consumer_name. If you specify application_name instead, your # value for allow_access_levels is ignored, and a desktop # integration is performed. launchpad = NoNetworkLaunchpad.login_with( 'application name', allow_access_levels=['FOO']) self.assertEqual(launchpad.authorization_engine.allow_access_levels, ['DESKTOP_INTEGRATION']) def test_no_credentials_creates_new_credential(self): # If no credentials are found, a desktop-wide credential is created. timeout = object() proxy_info = object() launchpad = NoNetworkLaunchpad.login_with( 'app name', launchpadlib_dir=self.temp_dir, service_root=SERVICE_ROOT, timeout=timeout, proxy_info=proxy_info) # Here's the new credential. self.assertEqual(launchpad.credentials.access_token.key, NoNetworkAuthorizationEngine.ACCESS_TOKEN_KEY) self.assertEqual(launchpad.credentials.consumer.application_name, 'app name') self.assertEqual(launchpad.authorization_engine.allow_access_levels, ['DESKTOP_INTEGRATION']) # The expected arguments were passed in to the Launchpad # constructor. expected_arguments = dict( service_root=SERVICE_ROOT, cache=os.path.join(self.temp_dir, 'api.example.com', 'cache'), timeout=timeout, proxy_info=proxy_info, version=NoNetworkLaunchpad.DEFAULT_VERSION) self.assertEqual(launchpad.passed_in_args, expected_arguments) def test_anonymous_login(self): """Test the anonymous login helper function.""" launchpad = NoNetworkLaunchpad.login_anonymously( 'anonymous access', launchpadlib_dir=self.temp_dir, service_root=SERVICE_ROOT) self.assertEqual(launchpad.credentials.access_token.key, '') self.assertEqual(launchpad.credentials.access_token.secret, '') # Test that anonymous credentials are not saved. credentials_path = os.path.join( self.temp_dir, 'api.example.com', 'credentials', 'anonymous access') self.assertFalse(os.path.exists(credentials_path)) def test_existing_credentials_arguments_passed_on(self): # When re-using existing credentials, the arguments login_with # is called with are passed on the the __init__() method. os.makedirs( os.path.join(self.temp_dir, 'api.example.com', 'credentials')) credentials_file_path = os.path.join( self.temp_dir, 'api.example.com', 'credentials', 'app name') credentials = Credentials( 'app name', consumer_secret='consumer_secret:42', access_token=AccessToken('access_key:84', 'access_secret:168')) credentials.save_to_path(credentials_file_path) timeout = object() proxy_info = object() version = "foo" launchpad = NoNetworkLaunchpad.login_with( 'app name', launchpadlib_dir=self.temp_dir, service_root=SERVICE_ROOT, timeout=timeout, proxy_info=proxy_info, version=version) expected_arguments = dict( service_root=SERVICE_ROOT, timeout=timeout, proxy_info=proxy_info, version=version, cache=os.path.join(self.temp_dir, 'api.example.com', 'cache')) for key, expected in expected_arguments.items(): actual = launchpad.passed_in_args[key] self.assertEqual(actual, expected) def test_None_launchpadlib_dir(self): # If no launchpadlib_dir is passed in to login_with, # $HOME/.launchpadlib is used. old_home = os.environ.get('HOME') os.environ['HOME'] = self.temp_dir launchpad = NoNetworkLaunchpad.login_with( 'app name', service_root=SERVICE_ROOT) # Reset the environment to the old value. if old_home is not None: os.environ['HOME'] = old_home else: del os.environ['HOME'] cache_dir = launchpad.passed_in_args['cache'] launchpadlib_dir = os.path.abspath( os.path.join(cache_dir, '..', '..')) self.assertEqual( launchpadlib_dir, os.path.join(self.temp_dir, '.launchpadlib')) self.assertTrue(os.path.exists( os.path.join(launchpadlib_dir, 'api.example.com', 'cache'))) def test_short_service_name(self): # A short service name is converted to the full service root URL. launchpad = NoNetworkLaunchpad.login_with('app name', 'staging') self.assertEqual( launchpad.passed_in_args['service_root'], 'https://api.staging.launchpad.net/') # A full URL as the service name is left alone. launchpad = NoNetworkLaunchpad.login_with( 'app name', uris.service_roots['staging']) self.assertEqual( launchpad.passed_in_args['service_root'], uris.service_roots['staging']) # A short service name that does not match one of the # pre-defined service root names, and is not a valid URL, # raises an exception. launchpad = ('app name', 'https://') self.assertRaises( ValueError, NoNetworkLaunchpad.login_with, 'app name', 'foo') def test_max_failed_attempts_accepted(self): # You can pass in a value for the 'max_failed_attempts' # argument, even though that argument doesn't do anything. NoNetworkLaunchpad.login_with( 'not important', max_failed_attempts=5) class TestDeprecatedLoginMethods(KeyringTest): """Make sure the deprecated login methods still work.""" def test_login_is_deprecated(self): # login() works but triggers a deprecation warning. with warnings.catch_warnings(record=True) as caught: warnings.simplefilter("always") warnings.simplefilter("ignore", PendingDeprecationWarning) NoNetworkLaunchpad.login('consumer', 'token', 'secret') self.assertEqual(len(caught), 1) self.assertEqual(caught[0].category, DeprecationWarning) def test_get_token_and_login_is_deprecated(self): # get_token_and_login() works but triggers a deprecation warning. with warnings.catch_warnings(record=True) as caught: warnings.simplefilter("always") warnings.simplefilter("ignore", PendingDeprecationWarning) NoNetworkLaunchpad.get_token_and_login('consumer') self.assertEqual(len(caught), 1) self.assertEqual(caught[0].category, DeprecationWarning) class TestCredenitialSaveFailedCallback(unittest.TestCase): # There is a callback which will be called if saving the credentials # fails. def setUp(self): # launchpadlib.launchpad uses the socket module to look up the # hostname, obviously that can vary so we replace the socket module # with a fake that returns a fake hostname. launchpadlib.launchpad.socket = FauxSocketModule() self.temp_dir = tempfile.mkdtemp() def tearDown(self): launchpadlib.launchpad.socket = socket shutil.rmtree(self.temp_dir) @patch.object(NoNetworkLaunchpad, '_is_sudo', staticmethod(lambda: False)) def test_credentials_save_failed(self): # If saving the credentials did not succeed and a callback was # provided, it is called. callback_called = [] def callback(): # Since we can't rebind "callback_called" here, we'll have to # settle for mutating it to signal success. callback_called.append(None) launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') service_root = "http://api.example.com/" with fake_keyring(BadSaveKeyring()): NoNetworkLaunchpad.login_with( 'not important', service_root=service_root, launchpadlib_dir=launchpadlib_dir, credential_save_failed=callback) self.assertEqual(len(callback_called), 1) @patch.object(NoNetworkLaunchpad, '_is_sudo', staticmethod(lambda: False)) def test_default_credentials_save_failed_is_to_raise_exception(self): # If saving the credentials did not succeed and no callback was # provided, the underlying exception is raised. launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') service_root = "http://api.example.com/" with fake_keyring(BadSaveKeyring()): self.assertRaises( RuntimeError, NoNetworkLaunchpad.login_with, 'not important', service_root=service_root, launchpadlib_dir=launchpadlib_dir) @patch.object(NoNetworkLaunchpad, '_is_sudo', staticmethod(lambda: True)) def test_credentials_save_fail_under_sudo_does_not_raise_exception(self): # When running under sudo, Launchpad will not attempt to use # the keyring, so credential save failure will never happen launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') service_root = "http://api.example.com/" with fake_keyring(BadSaveKeyring()): NoNetworkLaunchpad.login_with( 'not important', service_root=service_root, launchpadlib_dir=launchpadlib_dir) class TestMultipleSites(unittest.TestCase): # If the same application name (consumer name) is used to access more than # one site, the credentials need to be stored seperately. Therefore, the # "username" passed ot the keyring includes the service root. def setUp(self): # launchpadlib.launchpad uses the socket module to look up the # hostname, obviously that can vary so we replace the socket module # with a fake that returns a fake hostname. launchpadlib.launchpad.socket = FauxSocketModule() self.temp_dir = tempfile.mkdtemp() def tearDown(self): launchpadlib.launchpad.socket = socket shutil.rmtree(self.temp_dir) @patch.object(NoNetworkLaunchpad, '_is_sudo', staticmethod(lambda: False)) def test_components_of_application_key(self): launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') keyring = InMemoryKeyring() service_root = 'http://api.example.com/' application_name = 'Super App 3000' with fake_keyring(keyring): launchpad = NoNetworkLaunchpad.login_with( application_name, service_root=service_root, launchpadlib_dir=launchpadlib_dir) consumer_name = launchpad.credentials.consumer.key application_key = list(keyring.data.keys())[0][1] # Both the consumer name (normally the name of the application) and # the service root (the URL of the service being accessed) are # included in the key when storing credentials. self.assertIn(service_root, application_key) self.assertIn(consumer_name, application_key) # The key used to store the credentials is of this structure (and # shouldn't change between releases or stored credentials will be # "forgotten"). self.assertEqual(application_key, consumer_name + '@' + service_root) @patch.object(NoNetworkLaunchpad, '_is_sudo', staticmethod(lambda: False)) def test_same_app_different_servers(self): launchpadlib_dir = os.path.join(self.temp_dir, 'launchpadlib') keyring = InMemoryKeyring() # Be paranoid about the keyring starting out empty. assert not keyring.data, 'oops, a fresh keyring has data in it' with fake_keyring(keyring): # Create stored credentials for the same application but against # two different sites (service roots). NoNetworkLaunchpad.login_with( 'application name', service_root='http://alpha.example.com/', launchpadlib_dir=launchpadlib_dir) NoNetworkLaunchpad.login_with( 'application name', service_root='http://beta.example.com/', launchpadlib_dir=launchpadlib_dir) # There should only be two sets of stored credentials (this assertion # is of the test mechanism, not a test assertion). assert len(keyring.data.keys()) == 2 application_key_1 = list(keyring.data.keys())[0][1] application_key_2 = list(keyring.data.keys())[1][1] self.assertNotEqual(application_key_1, application_key_2) def test_suite(): return unittest.TestLoader().loadTestsFromName(__name__) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1558535650.0 launchpadlib-1.10.13/src/launchpadlib/uris.py0000644000175000017500000001060700000000000022563 0ustar00cjwatsoncjwatson00000000000000# Copyright 2009 Canonical Ltd. # This file is part of launchpadlib. # # launchpadlib is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation, version 3 of the License. # # launchpadlib is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with launchpadlib. If not, see . """Launchpad-specific URIs and convenience lookup functions. The code in this module lets users say "staging" when they mean "https://api.staging.launchpad.net/". """ __metaclass__ = type __all__ = [ 'lookup_service_root', 'lookup_web_root', 'web_root_for_service_root', ] try: from urllib.parse import urlparse except ImportError: from urlparse import urlparse import warnings from lazr.uri import URI LPNET_SERVICE_ROOT = 'https://api.launchpad.net/' QASTAGING_SERVICE_ROOT = 'https://api.qastaging.launchpad.net/' STAGING_SERVICE_ROOT = 'https://api.staging.launchpad.net/' DEV_SERVICE_ROOT = 'https://api.launchpad.test/' DOGFOOD_SERVICE_ROOT = 'https://api.dogfood.paddev.net/' TEST_DEV_SERVICE_ROOT = 'http://api.launchpad.test:8085/' LPNET_WEB_ROOT = 'https://launchpad.net/' QASTAGING_WEB_ROOT = 'https://qastaging.launchpad.net/' STAGING_WEB_ROOT = 'https://staging.launchpad.net/' DEV_WEB_ROOT = 'https://launchpad.test/' DOGFOOD_WEB_ROOT = 'https://dogfood.paddev.net/' TEST_DEV_WEB_ROOT = 'http://launchpad.test:8085/' # If you use EDGE_SERVICE_ROOT, or its alias, or the equivalent # string, launchpadlib will issue a deprecation warning and use # PRODUCTION_SERVICE_ROOT instead. Similarly for EDGE_WEB_ROOT. EDGE_SERVICE_ROOT = 'https://api.edge.launchpad.net/' EDGE_WEB_ROOT = 'https://edge.launchpad.net/' service_roots = dict( production=LPNET_SERVICE_ROOT, edge=LPNET_SERVICE_ROOT, qastaging=QASTAGING_SERVICE_ROOT, staging=STAGING_SERVICE_ROOT, dogfood=DOGFOOD_SERVICE_ROOT, dev=DEV_SERVICE_ROOT, test_dev=TEST_DEV_SERVICE_ROOT ) web_roots = dict( production=LPNET_WEB_ROOT, edge = LPNET_WEB_ROOT, qastaging=QASTAGING_WEB_ROOT, staging=STAGING_WEB_ROOT, dogfood=DOGFOOD_WEB_ROOT, dev=DEV_WEB_ROOT, test_dev=TEST_DEV_WEB_ROOT ) def _dereference_alias(root, aliases): """Dereference what might a URL or an alias for a URL.""" if root == 'edge': warnings.warn(("Launchpad edge server no longer exists. " "Using 'production' instead."), DeprecationWarning) if root in aliases: return aliases[root] # It's not an alias. Is it a valid URL? (scheme, netloc, path, parameters, query, fragment) = urlparse(root) if scheme != "" and netloc != "": return root # It's not an alias or a valid URL. raise ValueError("%s is not a valid URL or an alias for any Launchpad " "server" % root) def lookup_service_root(service_root): """Dereference an alias to a service root. A recognized server alias such as "staging" gets turned into the appropriate URI. A URI gets returned as is. Any other string raises a ValueError. """ if service_root == EDGE_SERVICE_ROOT: # This will trigger a deprecation warning and use production instead. service_root = 'edge' return _dereference_alias(service_root, service_roots) def lookup_web_root(web_root): """Dereference an alias to a website root. A recognized server alias such as "staging" gets turned into the appropriate URI. A URI gets returned as is. Any other string raises a ValueError. """ if web_root == EDGE_WEB_ROOT: # This will trigger a deprecation warning and use production instead. web_root = 'edge' return _dereference_alias(web_root, web_roots) def web_root_for_service_root(service_root): """Turn a service root URL into a web root URL. This is done heuristically, not with a lookup. """ service_root = lookup_service_root(service_root) web_root_uri = URI(service_root) web_root_uri.path = "" web_root_uri.host = web_root_uri.host.replace("api.", "", 1) web_root = str(web_root_uri.ensureSlash()) return web_root ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288694.0 launchpadlib-1.10.13/src/launchpadlib/version.txt0000644000175000017500000000001000000000000023440 0ustar00cjwatsoncjwatson000000000000001.10.13 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1587288714.5192525 launchpadlib-1.10.13/src/launchpadlib.egg-info/0000755000175000017500000000000000000000000022715 5ustar00cjwatsoncjwatson00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288712.0 launchpadlib-1.10.13/src/launchpadlib.egg-info/PKG-INFO0000644000175000017500000003431000000000000024013 0ustar00cjwatsoncjwatson00000000000000Metadata-Version: 2.1 Name: launchpadlib Version: 1.10.13 Summary: Script Launchpad through its web services interfaces. Officially supported. Home-page: https://help.launchpad.net/API/launchpadlib Author: The Launchpad developers Author-email: launchpadlib@lists.launchpad.net Maintainer: LAZR Developers Maintainer-email: lazr-developers@lists.launchpad.net License: LGPL v3 Download-URL: https://launchpad.net/launchpadlib/+download Description: .. This file is part of launchpadlib. launchpadlib is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. launchpadlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with launchpadlib. If not, see . launchpadlib ************ See https://help.launchpad.net/API/launchpadlib . ===================== NEWS for launchpadlib ===================== 1.10.13 (2020-04-19) ==================== - Fix test runs under sudo. 1.10.12 (2020-04-17) ==================== - Postpone keyring.errors import in the same way that we postpone importing keyring itself. 1.10.11 (2020-04-14) ==================== - Don't store credentials or open a browser window when running under sudo. [bug=1825014,1862948] - Fall back to in-memory credentials store if no keyring backend is available. [bug=1864204] 1.10.10 (2020-02-04) ==================== - Fix AccessToken.from_string crash on Python 3.8. [bug=1861873] 1.10.9 (2019-11-28) =================== - Explicitly install version.txt; launchpadlib requires it. 1.10.8 (2019-11-26) =================== - Squash a deprecation warning on Python >= 3.7 in launchpadlib.testing.launchpad. - Switch from buildout to tox. - Weaken hosted-files test slightly to avoid problems with zope.publisher >= 4.2.2. 1.10.7 (2019-05-22) =================== - Change 'dev' URLs from launchpad.dev to launchpad.test. 1.10.6 (2018-03-08) =================== - Fix saving of credentials in python3 with gnome-keyring. [bug=1685962] 1.10.5 (2017-02-02) =================== - Fix AccessToken.from_string crash on Python 3. [bug=1471927] - Fix fallback if authorizing a token with a browser raises webbrowser.Error. - Stop introduction.txt doctest from writing to $HOME. 1.10.4 (2016-07-12) =================== - Fix _bad_oauth_token crash on Python 3. [bug=1471894] - Time out make_end_user_authorize_token after 15 minutes. - Ignore PendingDeprecationWarning from lazr.restfulclient. [bug=1473577] - Ask forgiveness rather than permission when creating cache directories. - Fix browser token authorization on OS X. [bug=1516080] 1.10.3 (2014-12-05) =================== - Port to Python3. - Detect proxies from the environment by default. 1.10.2 (2012-07-05) =================== - Typo in the doctest fix, discovered when trying to integrate with launchpad itself. [bug=1020667] 1.10.1 (2012-07-04) =================== - Fix a doctest in introduction.txt so that the test suite runs with python-2.7 (note the doctests only run when running integrated with launchpad's test suite itself). [bug=1020667] 1.10.0 (2012-06-19) =================== - Add environment variable, LP_DISABLE_SSL_CERTIFICATE_VALIDATION, to disable SSL certificate checks. Most useful when testing against development servers. 1.9.12 (2011-12-05) =================== - Move keyring base64 encoding to KeyringCredential and be more defensive about decoding. [bug=900307] 1.9.11 (2011-11-21) =================== - 1.9.10 was a bad release due to incomplete NEWS entries. - Add fake Launchpad web service for unit test. - Improve HACKING documentation. - Improve launchpadlib directory discovery on Windows. - Added script to delete spurious bugtasks or split a bugtask from a bug. - Properly handle Unicode passwords if returned by the keyring. - Base 64 encode serialized credentials before putting in keyring/wallet. 1.9.10 (2011-11-21) =================== - Base 64 encode serialized credentials before putting in keyring/wallet. 1.9.9 (2011-07-27) ================== - Fix a failing test for lazr.restfulclient 0.12.0. 1.9.8 (2011-02-28) ================== - Detect the error Launchpad sends when it doesn't recognize an access token, and get a new token. 1.9.7 (2011-02-15) ================== - Slightly tweaked the behavior of EDGE_SERVICE_ROOT, and improved tests. 1.9.6 (2011-02-14) ================== - Added EDGE_SERVICE_ROOT and the 'edge' alias back, though they both operate on production behind the scenes. Using the 'edge' alias will cause a deprecation warning. 1.9.5 (2011-02-08) ================== - Fixed a bug that prevented the deprecated get_token_and_login code from working, and that required that users of get_token_and_login get a new token on every usage. 1.9.4 (2011-01-18) ================== - Removed references to the 'edge' service root, which is being phased out. - Fixed a minor bug in the upload_release_tarball contrib script which was causing tarballs to be uploaded with the wrong media type. - The XSLT stylesheet for converting the Launchpad WADL into HTML documentation has been moved back into Launchpad. 1.9.3 (2011-01-10) ================== - The keyring package import is now delayed until the keyring needs to be accessed. This reduces launchapdlib users' exposure to unintended side effects of importing keyring (KWallet authorization dialogs and the registration of a SIGCHLD handler). 1.9.2 (2011-01-07) ================== - Added a missing import. 1.9.1 (2011-01-06) ================== - Corrected a test failure. 1.9.0 (2011-01-05) ================== - When an authorization token expires or becomes invalid, attempt to acquire a new one, even in the middle of a session, rather than crashing. - The HTML generated by wadl-to-refhtml.xsl now validates. - Most of the helper login methods have been deprecated. There are now only two helper methods: * Launchpad.login_anonymously, for anonymous credential-free access. * Launchpad.login_with, for programs that need a credential. 1.8.0 (2010-11-15) ================== - Store authorization tokens in the Gnome keyring or KDE wallet, when available. The credentials_file parameter of Launchpad.login_with() is now ignored. - By default, Launchpad.login_with() now asks Launchpad for desktop-wide integration. This removes the need for each individual application to get its own OAuth token. 1.7.0 (2010-09-23) ================== - Removed "fake Launchpad browser" code that didn't work and was misleading developers. - Added support for http://qastaging.launchpad.net by adding astaging to the uris. 1.6.5 (2010-08-23) ================== - Make launchpadlib compatible with the latest lazr.restfulclient. 1.6.4 (2010-08-18) ================== - Test fixes. 1.6.3 (2010-08-12) ================== - Instead of making the end-user hit Enter after authorizing an application to access their Launchpad account, launchpadlib will automatically poll Launchpad until the user makes a decision. - launchpadlib now raises a more helpful exception when the end-user explicitly denies access to a launchpadlib application. - Improved the XSLT stylesheet to reflect Launchpad's more complex top-level structure. [bug=286941] - Test fixes. [bug=488448,616055] 1.6.2 (2010-06-21) ================== - Extended the optimization from version 1.6.1 to apply to Launchpad's top-level collection of people. 1.6.1 (2010-06-16) ================== - Added an optimization that lets launchpadlib avoid making an HTTP request in some situations. 1.6.0 (2010-04-07) ================== - Fixed a test to work against the latest version of Launchpad. 1.5.8 (2010-03-25) ================== - Use version 1.0 of the Launchpad web service by default. 1.5.7 (2010-03-16) ================== - Send a Referer header whenever making requests to the Launchpad website (as opposed to the web service) to avoid falling afoul of new cross-site-request-forgery countermeasures. 1.5.6 (2010-03-04) ================== - Fixed a minor bug when using login_with() to access a version of the Launchpad web service other than the default. - Added a check to catch old client code that would cause newer versions of launchpadlib to make nonsensical requests to https://api.launchpad.dev/beta/beta/, and raise a helpful exception telling the developer how to fix it. 1.5.5 ===== - Added the ability to access different versions of the Launchpad web service. 1.5.4 (2009-12-17) ================== - Made it easy to get anonymous access to a Launchpad instance. - Made it easy to plug in different clients that take the user's Launchpad login and password for purposes of authorizing a request token. The most secure technique is still the default: to open the user's web browser to the appropriate Launchpad page. - Introduced a command-line script bin/launchpad-credentials-console, which takes the user's Launchpad login and password, and authorizes a request token on their behalf. - Introduced a command-line script bin/launchpad-request-token, which creates a request token on any Launchpad installation and dumps the JSON description of that token to standard output. - Shorthand service names like 'edge' should now be respected everywhere in launchpadlib. 1.5.3 (2009-10-22) ================== - Moved some more code from launchpadlib into the more generic lazr.restfulclient. 1.5.2 (2009-10-01) ================== - Added a number of new sample scripts from elsewhere. - Added a reference to the production Launchpad instance. - Made it easier to specify a Launchpad instance to run against. 1.5.1 (2009-07-16) ================== - Added a sample script for uploading a release tarball to Launchpad. 1.5.0 (2009-07-09) ================== - Most of launchpadlib's code has been moved to the generic lazr.restfulclient library. launchpadlib now contains only code specific to Launchpad. There should be no changes in functionality. - Moved bootstrap.py into the top-level directory. Having it in a subdirectory with a top-level symlink was breaking installation on Windows. - The notice to the end-user (that we're opening their web browser) is now better formatted. 1.0.1 (2009-05-30) ================== - Correct tests for new launchpad cache behavior in librarian - Remove build dependency on setuptools_bzr because it was causing bzr to be downloaded during installation of the package, which was unnecessary and annoying. 1.0 (2009-03-24) ================ - Initial release on PyPI Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Provides-Extra: docs Provides-Extra: test ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288714.0 launchpadlib-1.10.13/src/launchpadlib.egg-info/SOURCES.txt0000644000175000017500000000252000000000000024600 0ustar00cjwatsoncjwatson00000000000000COPYING.txt HACKING.rst NEWS.rst README.rst setup.py src/launchpadlib/__init__.py src/launchpadlib/apps.py src/launchpadlib/credentials.py src/launchpadlib/errors.py src/launchpadlib/launchpad.py src/launchpadlib/uris.py src/launchpadlib/version.txt src/launchpadlib.egg-info/PKG-INFO src/launchpadlib.egg-info/SOURCES.txt src/launchpadlib.egg-info/dependency_links.txt src/launchpadlib.egg-info/not-zip-safe src/launchpadlib.egg-info/requires.txt src/launchpadlib.egg-info/top_level.txt src/launchpadlib/docs/Makefile src/launchpadlib/docs/NEWS.rst src/launchpadlib/docs/command-line.rst src/launchpadlib/docs/conf.py src/launchpadlib/docs/hosted-files.rst src/launchpadlib/docs/index.rst src/launchpadlib/docs/introduction.rst src/launchpadlib/docs/operations.rst src/launchpadlib/docs/people.rst src/launchpadlib/docs/toplevel.rst src/launchpadlib/docs/files/mugshot.png src/launchpadlib/testing/__init__.py src/launchpadlib/testing/helpers.py src/launchpadlib/testing/launchpad-wadl.xml src/launchpadlib/testing/launchpad.py src/launchpadlib/testing/resources.py src/launchpadlib/testing/testing-wadl.xml src/launchpadlib/testing/tests/__init__.py src/launchpadlib/testing/tests/test_launchpad.py src/launchpadlib/tests/__init__.py src/launchpadlib/tests/test_credential_store.py src/launchpadlib/tests/test_http.py src/launchpadlib/tests/test_launchpad.py././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288712.0 launchpadlib-1.10.13/src/launchpadlib.egg-info/dependency_links.txt0000644000175000017500000000000100000000000026763 0ustar00cjwatsoncjwatson00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1399901006.0 launchpadlib-1.10.13/src/launchpadlib.egg-info/not-zip-safe0000644000175000017500000000000100000000000025143 0ustar00cjwatsoncjwatson00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288712.0 launchpadlib-1.10.13/src/launchpadlib.egg-info/requires.txt0000644000175000017500000000022300000000000025312 0ustar00cjwatsoncjwatson00000000000000httplib2 keyring lazr.restfulclient>=0.9.19 lazr.uri setuptools six testresources wadllib [docs] Sphinx [test] [test:python_version < "3"] mock ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1587288712.0 launchpadlib-1.10.13/src/launchpadlib.egg-info/top_level.txt0000644000175000017500000000001500000000000025443 0ustar00cjwatsoncjwatson00000000000000launchpadlib