defer-1.0.6/0000755000175000017500000000000011752516011013360 5ustar renaterenate00000000000000defer-1.0.6/COPYRIGHT0000644000175000017500000004310311435206377014665 0ustar renaterenate00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. defer-1.0.6/README0000644000175000017500000000055211435214465014250 0ustar renaterenate00000000000000The defer module provides an easy way to write asynchrouns Python programms. It is greatly inspired by Twisted's defer, but comes without a lot of the dependencies. At first defer was part of aptdaemon and moved to a separate project in August of 2010. The project homepage is at https://launchpad.net/python-defer You can report errors and suggestion there. defer-1.0.6/NEWS0000644000175000017500000000137711752470756014106 0ustar renaterenate00000000000000CHANGES FOR 1.0.5: * Fix some Python3 issues CHANGES FOR 1.0.4: * Remove obsoleted porting by 2to3 during installation * Compare Python version by sys.version_info instead of sys.version CHANGES FOR 1.0.3: * Add support for Python3. We now require at least Python 2.6 CHANGES FOR 1.0.2: * Fix a missing import of the DeferredException CHANGES FOR 1.0.1: * The utils.deferable decorator detects if the decorated function was called from an inline_callbacks decorated function. In this case a Deferred will be return automatically. There isn't any need to specify the defer argument anymore. * Fixes: - Detection of call of return_value outside of inline_callbacks CHANGES FOR 1.0: - Initial release as a separate package defer-1.0.6/PKG-INFO0000644000175000017500000000172411752516011014461 0ustar renaterenate00000000000000Metadata-Version: 1.1 Name: defer Version: 1.0.6 Summary: Simple framework for asynchronous programming Home-page: http://launchpad.net/python-defer Author: Sebastian Heinlein Author-email: devel@glatzor.de License: GNU GPL Description: The defer module provides an easy way to write asynchrouns Python programms. It is greatly inspired by Twisted's defer, but comes without a lot of the dependencies. At first defer was part of aptdaemon and moved to a separate project in August of 2010. The project homepage is at https://launchpad.net/python-defer You can report errors and suggestion there. Keywords: async defer dbus asynchronous Platform: posix Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: Programming Language :: Python Classifier: Topic :: Software Development :: Libraries :: Python Modules defer-1.0.6/MANIFEST.in0000644000175000017500000000015411435221213015111 0ustar renaterenate00000000000000include AUTHORS include COPYRIGHT include NEWS include NEWS.aptdaemon include pylintrc include README.tests defer-1.0.6/NEWS.aptdaemon0000644000175000017500000002613011435206377016041 0ustar renaterenate00000000000000API CHANGES 0.4X: * org.debian.aptdaemon D-Bus interface: - Allow to specify the to be installed/removed version of package. The package name and version are separated by "=", e.g. "xterm=258-1". - BREAK: The CommitPackage method has got a new argument to downgrade packages. You have to specify the version of the to be downgraded packages. * console client: - Add a --details option to show the version number of to be changed packages API CHANGES 0.3X * policykit1 Python module - Raise an AuthorizationFailed exception in a non-interactive check if the user could obtain the privilege in interactive-mode (is_challenged) * errors Python module - Make the AuthorizationFailed error an inheritance of NotAuthorizedError * PolicyKit1: - Allow every active user to update the cache - Merge install-packages, remove-packages and fix privilege into a new install-or-remove-packages one - Merge add- and remove-vendor-key privileges into change-repository one - Remove upgrade-system in favour of upgrade-packages - Allow set-proxy and cancel-foreign only by auth_admin API CHANGES 0.32 * PolicyKit1: - Add a new privilege org.debian.apt.set-proxy which allows to set an http proxy server for a transaction. Currently every active user is allowed to set a proxy for his or her transactions. * entry points: - Add modify_cache_before and modify_cache_after entry point which make it possible for plugins to modify the to be installed or removed packages of a transaction. See README.Plugins for further details. * client Python module: - Allow to convert all methods into Deferreds by using the deferable_function decorator, see below for more details. - Add a downloads attribute to AptTransaction. It contains a dictionary of all processed downloads. The key is the uri of the download. The value is a tuple of status enum, short description, full size, downloaded size and a status/error message - Add a progress-download-changed signal to AptTransaction which is emitted when a download progress information changed, see above. - Implement the wait arguement in the AptClient methods which are transaction based. If True the transaction will be started immediately and the method call will return when the transaction is finished. - Add add_vendor_key_from_keyserver method, see AddVendorKeyFromKeyserver * enums Python module: - Add a set of DOWNLOAD_* status enumerations. - Fix value of STATUS_DOWNLOADING: from status-downloadgin to status-downloading * defer Python module: - Add inline_callbacks and return_value functions which allow to write async code in a sync way. Works like the inlineCallbacks decorator from the Twisted framework. - Add deferable decorator which adds a defer attribute to the decorated function and returns a Deferred instance. The callback of the Deferred will be passed as reply_handler argument and the errback as the error_handler argument to the decorated function. * gtkwidgets Python module: - Add to the AptConfirmDialog two methods which allow to override the rendered objects and icons: map_package and render_package_icon - Add AptDownloadsView class, which allows to show the sub progress of each download - Rename AptTerminalExpander to AptDetailsExpander and add a terminal attribute to the __init__ call, since the expander now also shows the download sub-progresses. - AptProgressWindow now sets the proxy and debconf frontend during the run call instead of during the set_transaction call. * org.debian.aptdaemon.transaction D-Bus interface: - Add a ProgressDownload property. It contains the last download progress information that was recieved from APT. It is an array of uri, status enum, short description, full size, downloaded size and an error/status message. - Add AddVendorKeyFromKeyserver method to download and use a GnuPG which is used for authenticating packages. API CHANGES 0.31 * client Python module: - Add AptClient.enable_distro_component method, see EnableDistroComponent * org.debian.aptdaemon D-Bus interface: - Add EnableDistroComponent method which enables a component for all distro repositories, e.g. main or universe API CHANGES 0.30 * client Python module: - Change order of error_handler and reply_handler in the AptTransaction.run method to be in sync with the other methods - Add the dependencies, download and space attribute and the corresponding *-changed signal to AptTransaction, see interface changes below - Add a new AptTransaction.simulate() method, see interface changes below - The AptDaemonError stored in client.AptTransaction.error was replaced by a errors.TransactionFailed error. The APtDaemonError has been removed from the client module. - The DBus exception will be converted to native ones which are shared with the daemon. E.g. The DBusException with the error name "org.debian.apt.TransactionRoleAlreadySet" will be a TransactionRoleAlreadySet instance instead. This makes error handling easier since you can use try/except without having to compare the _dbus_error_name attributes. * errors Python modules: - Rename APTDError to AptDaemonError because of readabilty - Add convert_dbus_exception decorator which converts DBus exception raised in a function to native ones. Also takes asynchrous calls into account. - Move NotAuthorizedError from policykit1 to the errors module * enums Python module: - Use strings instead of integers for STATUS_*, EXIT_*, ROLE_* and ERROR_* enum. See interface changes for additional information - Add new enum EXIT_UNFINISHED * org.debian.aptdaemon.transaction D-Bus interface: - The Exit, Status, Role and Error property and the Finished signal now use strings for the enums. This helps to make debugging a lot easier. - Add Simulate method which calculates the dependencies, the download size and the to be used disk space of the transaction. Furthermore it raises a "org.debian.aptdaemon.errors.TransactionFailed" if the transaction could not be performed. The Simulate call also takes all previously queued or currently running transactions into account. So you can simulate the removal a package if the installation of it is still in the queue. - Add new properties Dependencies, Download and Space, see above. API CHANGES 0.20 You don't have to request a transaction, set it up and call the whished action on it aynmore. Instead you call the action, e.g. UpdateCache, on the daemon interface which will return the id of a newly created transaction. After settingit up you have to call its Run method. * org.debian.aptdaemon D-Bus interface: - Add InstallPackages, InstallFile, RemovePackages, CommitPackages, UpgradePackages, UpgradeSystem, AddVendorKey, RemoveVendorKey, UpdateCache method. Each method creates a new transaction and returns its tid. - Remove RequestTransaction method - Add new FixIncompleteInstall method which basically runs dpkg --configure -a - Add a new FixBrokenDepends method wich tries to correct dependencies * org.debian.aptdaemon.transaction D-Bus interface: - Remove InstallPackages, InstallFile, RemovePackages, CommitPackages, UpgradePackages, UpgradeSystem, AddVendorKey, RemoveVendorKey, UpdateCache method. They are now part of the org.debian.aptdaemon interface. - Add a Run method which queues the transaction. - Add PropertyChanged signal - should be used instead of the deprecated signals. Signal matchers are quite limited on the system bus by default. - Add ProgressDetails, RequiredMedium, ConfigFilePrompt, ExitState, Error, Locale, AllowUnauthenticated, Terminal, DebconfSocket, Packages, MetaData and RemoveObsoletedDepends properties. The Packages property keeps a lists of packages which should be installed, reinstalled, removed, purged or upgraded. Currently this doesn't work for UpgradeSystem. The MetaData property allows clients to store additional meta data in the transaction. See man page org.debian.apt.transaction(7) for the format. - Rename the AllowCancel property to Cancellable and the AllowTerminal one to TerminalAttached - helps to make a difference between allowing from the client and daemon side e.g. AllowUnauthenticated. - Remove Message signal and the concept of having non-critical fail states on the daemon side. The decision is up to the client e.g. if a system could not be fully updated. - Remove the Role, Status, AllowCancel, AllowTerminal, StatusDetails, Progress, ProgressDetails signal - PropertyChanged signal should be used instead. - Remove the Attach method - GetAll on the properties interface should be used instead. - Rename property ConfigFilePrompt to ConfigFileConflict and the method AnswerConfigFilePrompt to ResolveConfigFileConflict * client Python module: - The exit_handler was removed from the AptDaemonClient methods, instead it now supports (reply|error)_handlers to call the method asynchronously and furthermore a wait statement to return after the method is complete. - Add public attributes to the Transaction class and remove get_* helpers: role, error (stores an AptDaemonError instance), error_code, error_message, exit_state, cancellable, term_attached, required_medium, config_file_prompt, status, status_details, progress, progress_details, paused, remove_obsoleted_depends The properties are automatically updated by the PropertyChanged signal matcher. - Rename GObject signals of the Transaction class: - role -> role-changed - status -> status-changed - allow-cancel -> cancellable-changed - allow-terminal -> terminal-attached-changed - status -> status-changed - status-details -> status-details-changed - progress -> progress-changed - progress-details -> progress-details-changed - config-file-prompt -> config-file-conflict - Rename method config_file_prompt_answer to resolve_config_file_conflict - Add GObject signals to the Transaction class: - meta-data-changed - paused - resumed - locale-changed - allow-unauthenticated-changed - remove-obsoleted-depends-changed - debconf-socket-changed - The methods Transaction.set_(locale|allow_unauthenticated|data| debconf_socket|remove_obsoleted_depends) reply with the transaction instance if called async. This makes queing much easier. - Remove messages attribute from the Transaction class, see above - Remove Transaction.attach method in favour of a new sync method which uses the GetAll method on the D-Bus properties interface. - Add set_meta_data method which accepts pairs of key=value * PyGTK widgtes: - On the one hand the run method of AptProgressDialog doesn't provide a way to wait until the transaction is done anymore (by iterating on pending gtk events), but on the other hand it now allows to show an error dialog if required (show_error argument) or to close the progress window automatically when the transaction is finished (close_on_finished arguement). - Rename AptConfigFilePromptDialog to AptConfigFileConflictDialog defer-1.0.6/pylintrc0000644000175000017500000000023611435206377015161 0ustar renaterenate00000000000000[BASIC] # Allow CamelCase method names (DBus convention) method-rgx=[a-zA-Z_][a-zA-Z0-9_]{2,30}$ [DESIGN] max-args=10 max-attributes=20 min-public-methods=0 defer-1.0.6/setup.py0000755000175000017500000000224611752514725015113 0ustar renaterenate00000000000000#!/usr/bin/env python import os import re from setuptools import setup import sys def read_version(): f= os.path.join(os.path.dirname(__file__), "defer", "version.py") s=open(f).read() ver = re.match("VERSION=\"(.*)\"", s).group(1) return ver version = read_version() readme = open(os.path.join(os.path.dirname(__file__), "README")).read() setup(name="defer", version=version, description="Simple framework for asynchronous programming", long_description=readme, author="Sebastian Heinlein", author_email="devel@glatzor.de", license = "GNU GPL", url="http://launchpad.net/python-defer", keywords="async defer dbus asynchronous", classifiers=["Development Status :: 5 - Production/Stable", "License :: OSI Approved :: " \ "GNU General Public License (GPL)", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: " \ "Python Modules"], packages=["defer"], test_suite="nose.collector", test_requires=["Nose"], platforms="posix", use_2to3=True, ) defer-1.0.6/AUTHORS0000644000175000017500000000014111435206726014433 0ustar renaterenate00000000000000Maintainer: Sebastian Heinlein Developers: Michael Vogt defer-1.0.6/README.tests0000644000175000017500000000013111435206377015405 0ustar renaterenate00000000000000Tests are supported via nosetests from the python-nose package. Run them via nosetests. defer-1.0.6/setup.cfg0000644000175000017500000000035211752516011015201 0ustar renaterenate00000000000000[nosetests] verbose = 1 detailed-errors = 1 pdb = 1 pdb-failures = 1 with-coverage = 1 cover-package = defer with-doctest = 1 [upload_sphinx] upload-dir = build/sphinx/html [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 defer-1.0.6/defer.egg-info/0000755000175000017500000000000011752516011016137 5ustar renaterenate00000000000000defer-1.0.6/defer.egg-info/PKG-INFO0000644000175000017500000000172411752516011017240 0ustar renaterenate00000000000000Metadata-Version: 1.1 Name: defer Version: 1.0.6 Summary: Simple framework for asynchronous programming Home-page: http://launchpad.net/python-defer Author: Sebastian Heinlein Author-email: devel@glatzor.de License: GNU GPL Description: The defer module provides an easy way to write asynchrouns Python programms. It is greatly inspired by Twisted's defer, but comes without a lot of the dependencies. At first defer was part of aptdaemon and moved to a separate project in August of 2010. The project homepage is at https://launchpad.net/python-defer You can report errors and suggestion there. Keywords: async defer dbus asynchronous Platform: posix Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: Programming Language :: Python Classifier: Topic :: Software Development :: Libraries :: Python Modules defer-1.0.6/defer.egg-info/SOURCES.txt0000644000175000017500000000040711752516011020024 0ustar renaterenate00000000000000AUTHORS COPYRIGHT MANIFEST.in NEWS NEWS.aptdaemon README README.tests pylintrc setup.cfg setup.py defer/__init__.py defer/utils.py defer/version.py defer.egg-info/PKG-INFO defer.egg-info/SOURCES.txt defer.egg-info/dependency_links.txt defer.egg-info/top_level.txtdefer-1.0.6/defer.egg-info/top_level.txt0000644000175000017500000000000611752516011020665 0ustar renaterenate00000000000000defer defer-1.0.6/defer.egg-info/dependency_links.txt0000644000175000017500000000000111752516011022205 0ustar renaterenate00000000000000 defer-1.0.6/defer/0000755000175000017500000000000011752516011014445 5ustar renaterenate00000000000000defer-1.0.6/defer/__init__.py0000644000175000017500000005372111752515664016603 0ustar renaterenate00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """Small framework for asynchronous programming.""" # Copyright (C) 2008-2010 Sebastian Heinlein # Copyright (c) 2001-2010 # Allen Short # Andy Gayton # Andrew Bennetts # Antoine Pitrou # Apple Computer, Inc. # Benjamin Bruheim # Bob Ippolito # Canonical Limited # Christopher Armstrong # David Reid # Donovan Preston # Eric Mangold # Eyal Lotem # Itamar Shtull-Trauring # James Knight # Jason A. Mobarak # Jean-Paul Calderone # Jessica McKellar # Jonathan Jacobs # Jonathan Lange # Jonathan D. Simms # Jürgen Hermann # Kevin Horn # Kevin Turner # Mary Gardiner # Matthew Lefkowitz # Massachusetts Institute of Technology # Moshe Zadka # Paul Swartz # Pavel Pergamenshchik # Ralph Meijer # Sean Riley # Software Freedom Conservancy # Travis B. Hartwell # Thijs Triemstra # Thomas Herve # Timothy Allen # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. __author__ = "Sebastian Heinlein " __all__ = ("Deferred", "AlreadyCalledDeferred", "DeferredException", "defer", "inline_callbacks", "return_value") import collections from functools import wraps import sys import warnings from . import version __version__ = version.VERSION PY3K = sys.version_info.major > 2 class _DefGen_Return(BaseException): """Exception to return a result from an inline callback.""" def __init__(self, value): self.value = value class AlreadyCalledDeferred(Exception): """The Deferred is already running a callback.""" class DeferredException(object): """Allows to defer exceptions.""" def __init__(self, type=None, value=None, traceback=None): """Return a new DeferredException instance. If type, value and traceback are not specified the infotmation will be retreieved from the last caught exception: >>> try: ... raise Exception("Test") ... except: ... deferred_exc = DeferredException() >>> deferred_exc.raise_exception() Traceback (most recent call last): ... Exception: Test Alternatively you can set the exception manually: >>> exception = Exception("Test 2") >>> deferred_exc = DeferredException(exception) >>> deferred_exc.raise_exception() Traceback (most recent call last): ... Exception: Test 2 """ self.type = type self.value = value self.traceback = traceback if isinstance(type, Exception): self.type = type.__class__ self.value = type elif not type or not value: self.type, self.value, self.traceback = sys.exc_info() def raise_exception(self): """Raise the stored exception.""" if PY3K: raise self.value.with_traceback(self.traceback) else: raise self.type, self.value, self.traceback def catch(self, *errors): """Check if the stored exception is a subclass of one of the provided exception classes. If this is the case return the matching exception class. Otherwise raise the stored exception. >>> exc = DeferredException(SystemError()) >>> exc.catch(Exception) # Will catch the exception and return it >>> exc.catch(OSError) # Won't catch and raise the stored exception Traceback (most recent call last): ... SystemError This method can be used in errbacks of a Deferred: >>> def dummy_errback(deferred_exception): ... '''Error handler for OSError''' ... deferred_exception.catch(OSError) ... return "catched" The above errback can handle an OSError: >>> deferred = Deferred() >>> deferred.add_errback(dummy_errback) >>> deferred.errback(OSError()) >>> deferred.result 'catched' But fails to handle a SystemError: >>> deferred2 = Deferred() >>> deferred2.add_errback(dummy_errback) >>> deferred2.errback(SystemError()) >>> deferred2.result #doctest: +ELLIPSIS >>> deferred2.result.value SystemError() """ for err in errors: if issubclass(self.type, err): return err self.raise_exception() class Deferred(object): """The Deferred allows to chain callbacks. There are two type of callbacks: normal callbacks and errbacks, which handle an exception in a normal callback. The callbacks are processed in pairs consisting of a normal callback and an errback. A normal callback will return its result to the callback of the next pair. If an exception occurs, it will be handled by the errback of the next pair. If an errback doesn't raise an error again, the callback of the next pair will be called with the return value of the errback. Otherwise the exception of the errback will be returned to the errback of the next pair:: CALLBACK1 ERRBACK1 | \ / | result failure result failure | \ / | | \ / | | X | | / \ | | / \ | | / \ | CALLBACK2 ERRBACK2 | \ / | result failure result failure | \ / | | \ / | | X | | / \ | | / \ | | / \ | CALLBACK3 ERRBACK3 """ def __init__(self): """Return a new Deferred instance.""" self.callbacks = [] self.errbacks = [] self.called = False self.paused = False self._running = False def add_callbacks(self, callback, errback=None, callback_args=None, callback_kwargs=None, errback_args=None, errback_kwargs=None): """Add a pair of callables (function or method) to the callback and errback chain. Keyword arguments: callback -- the next chained challback errback -- the next chained errback callback_args -- list of additional arguments for the callback callback_kwargs -- dict of additional arguments for the callback errback_args -- list of additional arguments for the errback errback_kwargs -- dict of additional arguments for the errback In the following example the first callback pairs raises an exception that is catched by the errback of the second one and processed by the third one. >>> def callback(previous): ... '''Return the previous result.''' ... return "Got: %s" % previous >>> def callback_raise(previous): ... '''Fail and raise an exception.''' ... raise Exception("Test") >>> def errback(error): ... '''Recover from an exception.''' ... #error.catch(Exception) ... return "catched" >>> deferred = Deferred() >>> deferred.callback("start") >>> deferred.result 'start' >>> deferred.add_callbacks(callback_raise, errback) >>> deferred.result #doctest: +ELLIPSIS >>> deferred.add_callbacks(callback, errback) >>> deferred.result 'catched' >>> deferred.add_callbacks(callback, errback) >>> deferred.result 'Got: catched' """ assert isinstance(callback, collections.Callable) assert errback is None or isinstance(errback, collections.Callable) if errback is None: errback = _passthrough self.callbacks.append(((callback, callback_args or ([]), callback_kwargs or ({})), (errback or (_passthrough), errback_args or ([]), errback_kwargs or ({})))) if self.called: self._next() def add_errback(self, func, *args, **kwargs): """Add a callable (function or method) to the errback chain only. If there isn't any exception the result will be passed through to the callback of the next pair. The first argument is the callable instance followed by any additional argument that will be passed to the errback. The errback method will get the most recent DeferredException and and any additional arguments that was specified in add_errback. If the errback can catch the exception it can return a value that will be passed to the next callback in the chain. Otherwise the errback chain will not be processed anymore. See the documentation of defer.DeferredException.catch for further information. >>> def catch_error(deferred_error, ignore=False): ... if ignore: ... return "ignored" ... deferred_error.catch(Exception) ... return "catched" >>> deferred = Deferred() >>> deferred.errback(SystemError()) >>> deferred.add_errback(catch_error, ignore=True) >>> deferred.result 'ignored' """ self.add_callbacks(_passthrough, func, errback_args=args, errback_kwargs=kwargs) def add_callback(self, func, *args, **kwargs): """Add a callable (function or method) to the callback chain only. An error would be passed through to the next errback. The first argument is the callable instance followed by any additional argument that will be passed to the callback. The callback method will get the result of the previous callback and any additional arguments that was specified in add_callback. >>> def callback(previous, counter=False): ... if counter: ... return previous + 1 ... return previous >>> deferred = Deferred() >>> deferred.add_callback(callback, counter=True) >>> deferred.callback(1) >>> deferred.result 2 """ self.add_callbacks(func, _passthrough, callback_args=args, callback_kwargs=kwargs) def errback(self, error=None): """Start processing the errorback chain starting with the provided exception or DeferredException. If an exception is specified it will be wrapped into a DeferredException. It will be send to the first errback or stored as finally result if not any further errback has been specified yet. >>> deferred = Deferred() >>> deferred.errback(Exception("Test Error")) >>> deferred.result #doctest: +ELLIPSIS >>> deferred.result.raise_exception() Traceback (most recent call last): ... Exception: Test Error """ if self.called: raise AlreadyCalledDeferred() if not error: error = DeferredException() elif not isinstance(error, DeferredException): assert isinstance(error, Exception) error = DeferredException(error.__class__, error, None) self.called = True self.result = error self._next() def callback(self, result=None): """Start processing the callback chain starting with the provided result. It will be send to the first callback or stored as finally one if not any further callback has been specified yet. >>> deferred = Deferred() >>> deferred.callback("done") >>> deferred.result 'done' """ if self.called: raise AlreadyCalledDeferred() self.called = True self.result = result self._next() def _continue(self, result): """Continue processing the Deferred with the given result.""" self.result = result self.paused = False if self.called: self._next() def _next(self): """Process the next callback.""" if self._running or self.paused: return while self.callbacks: # Get the next callback pair next_pair = self.callbacks.pop(0) # Continue with the errback if the last result was an exception callback, args, kwargs = next_pair[isinstance(self.result, DeferredException)] try: self.result = callback(self.result, *args, **kwargs) except: self.result = DeferredException() finally: self._running = False if isinstance(self.result, Deferred): # If a Deferred was returned add this deferred as callbacks to # the returned one. As a result the processing of this Deferred # will be paused until all callbacks of the returned Deferred # have been performed self.result.add_callbacks(self._continue, self._continue) self.paused == True break if isinstance(self.result, DeferredException): # Print the exception to stderr and stop if there aren't any # further errbacks to process sys.excepthook(self.result.type, self.result.value, self.result.traceback) return False def defer(func, *args, **kwargs): """Invoke the given function that may or not may be a Deferred. If the return object of the function call is a Deferred return, it. Otherwise wrap it into a Deferred. >>> defer(lambda x: x, 10) #doctest: +ELLIPSIS >>> deferred = defer(lambda x: x, "done") >>> deferred.result 'done' >>> deferred = Deferred() >>> defer(lambda: deferred) == deferred True """ assert isinstance(func, collections.Callable) try: result = func(*args, **kwargs) except: result = DeferredException() if isinstance(result, Deferred): return result deferred = Deferred() deferred.callback(result) return deferred def _passthrough(arg): return arg def return_value(val): """ Return val from a inline_callbacks generator. Note: this is currently implemented by raising an exception derived from BaseException. You might want to change any 'except:' clauses to an 'except Exception:' clause so as not to catch this exception. Also: while this function currently will work when called from within arbitrary functions called from within the generator, do not rely upon this behavior. """ raise _DefGen_Return(val) def _inline_callbacks(result, gen, deferred): """ See inlineCallbacks. """ # This function is complicated by the need to prevent unbounded recursion # arising from repeatedly yielding immediately ready deferreds. This while # loop and the waiting variable solve that by manually unfolding the # recursion. waiting = [True, # waiting for result? None] # result while 1: try: # Send the last result back as the result of the yield expression. is_failure = isinstance(result, DeferredException) if is_failure: if PY3K: excep = result.value.with_traceback(result.traceback) result = gen.throw(excep) else: result = gen.throw(result.type, result.value, result.traceback) else: result = gen.send(result) except StopIteration: # fell off the end, or "return" statement deferred.callback(None) return deferred except _DefGen_Return as err: # returnValue() was called; time to give a result to the original # Deferred. First though, let's try to identify the potentially # confusing situation which results when return_value() is # accidentally invoked from a different function, one that wasn't # decorated with @inline_callbacks. # The traceback starts in this frame (the one for # _inline_callbacks); the next one down should be the application # code. appCodeTrace = sys.exc_info()[2].tb_next if is_failure: # If we invoked this generator frame by throwing an exception # into it, then throwExceptionIntoGenerator will consume an # additional stack frame itself, so we need to skip that too. appCodeTrace = appCodeTrace.tb_next # Now that we've identified the frame being exited by the # exception, let's figure out if returnValue was called from it # directly. returnValue itself consumes a stack frame, so the # application code will have a tb_next, but it will *not* have a # second tb_next. if appCodeTrace.tb_next and appCodeTrace.tb_next.tb_next: # If returnValue was invoked non-local to the frame which it is # exiting, identify the frame that ultimately invoked # returnValue so that we can warn the user, as this behavior is # confusing. ultimateTrace = appCodeTrace while ultimateTrace.tb_next.tb_next: ultimateTrace = ultimateTrace.tb_next filename = ultimateTrace.tb_frame.f_code.co_filename lineno = ultimateTrace.tb_lineno warnings.warn_explicit( "returnValue() in %r causing %r to exit: " "returnValue should only be invoked by functions decorated " "with inlineCallbacks" % ( ultimateTrace.tb_frame.f_code.co_name, appCodeTrace.tb_frame.f_code.co_name), DeprecationWarning, filename, lineno) deferred.callback(err.value) return deferred except: deferred.errback() return deferred if isinstance(result, Deferred): # a deferred was yielded, get the result. def gotResult(res): if waiting[0]: waiting[0] = False waiting[1] = res else: _inline_callbacks(res, gen, deferred) result.add_callbacks(gotResult, gotResult) if waiting[0]: # Haven't called back yet, set flag so that we get reinvoked # and return from the loop waiting[0] = False return deferred result = waiting[1] # Reset waiting to initial values for next loop. gotResult uses # waiting, but this isn't a problem because gotResult is only # executed once, and if it hasn't been executed yet, the return # branch above would have been taken. waiting[0] = True waiting[1] = None return deferred def inline_callbacks(func): """inline_callbacks helps you write Deferred-using code that looks like a regular sequential function. For example:: def thingummy(): thing = yield makeSomeRequestResultingInDeferred() print thing #the result! hoorj! thingummy = inline_callbacks(thingummy) When you call anything that results in a Deferred, you can simply yield it; your generator will automatically be resumed when the Deferred's result is available. The generator will be sent the result of the Deferred with the 'send' method on generators, or if the result was a failure, 'throw'. Your inline_callbacks-enabled generator will return a Deferred object, which will result in the return value of the generator (or will fail with a failure object if your generator raises an unhandled exception). Note that you can't use return result to return a value; use return_value(result) instead. Falling off the end of the generator, or simply using return will cause the Deferred to have a result of None. The Deferred returned from your deferred generator may errback if your generator raised an exception:: def thingummy(): thing = yield makeSomeRequestResultingInDeferred() if thing == 'I love Twisted': # will become the result of the Deferred return_value('TWISTED IS GREAT!') else: # will trigger an errback raise Exception('DESTROY ALL LIFE') thingummy = inline_callbacks(thingummy) """ @wraps(func) def unwind_generator(*args, **kwargs): return _inline_callbacks(None, func(*args, **kwargs), Deferred()) return unwind_generator # vim:tw=4:sw=4:et defer-1.0.6/defer/utils.py0000644000175000017500000001045111573117136016166 0ustar renaterenate00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """Utils for using deferreds with D-Bus.""" # Copyright (C) 2008-2010 Sebastian Heinlein # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. __author__ = "Sebastian Heinlein " __all__ = ("dbus_deferred_method", "deferable") from functools import wraps import inspect import dbus from . import defer, Deferred, DeferredException def dbus_deferred_method(*args, **kwargs): """Export the decorated method on the D-Bus and handle a maybe returned Deferred. This decorator can be applied to methods in the same way as the @dbus.service.method method, but it correctly handles the case where the method returns a Deferred. This decorator was kindly taken from James Henstridge blog post and adopted: http://blogs.gnome.org/jamesh/2009/07/06/watching-iview-with-rygel/ """ def decorator(function): function = dbus.service.method(*args, **kwargs)(function) @wraps(function) def wrapper(*args, **kwargs): def ignore_none_callback(*cb_args): # The deferred method at least returns an tuple containing # only None. Ignore this case. if cb_args == (None,): dbus_callback() else: dbus_callback(*cb_args) dbus_callback = kwargs.pop('_dbus_callback') dbus_errback = kwargs.pop('_dbus_errback') deferred = defer(function, *args, **kwargs) deferred.add_callback(ignore_none_callback) deferred.add_errback(lambda error: dbus_errback(error.value)) # The @wraps decorator has copied over the attributes added by # the @dbus.service.method decorator, but we need to manually # set the async callback attributes. wrapper._dbus_async_callbacks = ('_dbus_callback', '_dbus_errback') return wrapper return decorator def deferable(func): """Add a defer attribute to the decorated function and return a Deferred object. The callback of the Deferred will be passed as reply_handler argument and the errback as the error_handler argument to the decorated function. This decorator allows to easily make use of Deferreds in a DBus client. """ @wraps(func) def _deferable(*args, **kwargs): def on_error(error, deferred): # Make sure that we return a deferred exception if isinstance(error, DeferredException): deferred.errback(error) else: deferred.errback(DeferredException(error)) try: # Check if the defer argument was specified to_defer = kwargs.pop("defer") except KeyError: # Check if this function was called from an inline_callbacks # decorated method stack = inspect.stack() try: to_defer = stack[2][3] == "_inline_callbacks" except IndexError: to_defer = False if to_defer: deferred = Deferred() kwargs["reply_handler"] = deferred.callback kwargs["error_handler"] = lambda err: on_error(err, deferred) func(*args, **kwargs) return deferred return func(*args, **kwargs) return _deferable # vim:tw=4:sw=4:et defer-1.0.6/defer/version.py0000644000175000017500000000002011752515674016512 0ustar renaterenate00000000000000VERSION="1.0.6"