Mini-AMF

Mini-AMF provides Action Message Format (AMF) serialization and deserialization support for Python, compatible with the Adobe Flash Player. It supports Python 2.7 and 3.4+.

https://travis-ci.org/zackw/mini-amf.svg?branch=master https://coveralls.io/repos/zackw/mini-amf/badge.svg

Mini-AMF is a trimmed-down version of the original PyAMF, which (as far as I can tell) is no longer being maintained. It provides only the core serialization and deserialization primitives, and support for reading and writing LSO objects on disk. Support for Flex-specific types, “remoting”, and integration with web frameworks has all been removed. (Adapter classes are still supported.)

Mini-AMF is lightly maintained by Zack Weinberg. All bug reports and pull requests will be heard and responded to, but I have no plans to develop the software any further myself. Please note that patches to restore support for old versions of Python 2 will not be accepted, as this interferes with support for Python 3. Please also note that “remoting” and server integration will probably be easier to maintain in their own separate packages, one per framework.

What’s AMF?

AMF is a binary message serialization format geared for remote procedure calls, native to the Adobe Flash Player and Adobe Integrated Runtime. There are two versions of the format, AMF0 and AMF3. AMF3 is more compact than AMF0, and and supports data types that are available only in ActionScript 3.0, such as ByteArray.

Contents

Download

Mini-AMF is released under the MIT license. For installation instructions, see the included Installation Guide.

Latest Stable Release - 1.0

Gzipped Tar Mini-AMF-1.0.0.tar.gz

Latest Development Source Code

The Git repository URL for the Mini-AMF project is at https://github.com/zackw/mini-amf.

The latest revision of Mini-AMF can be checked out with the following command:

git clone https://github.com/zackw/mini-amf.git

For installing this development version:

cd mini-amf
python setup.py develop

Older releases

Older releases are archived on https://pypi.python.org/packages/source/M/Mini-AMF/.

Installation Guide

Mini-AMF requires Python 2.7 or 3.4+, and DefusedXML.

Easy Installation

The easiest way to install Mini-AMF is with pip:

pip install mini-amf

Manual Installation

First install DefusedXML. If you wish to build the C accelerator module, you will also need a C compiler and the libraries for compiling Python extensions.

Download and unpack the Mini-AMF archive of your choice:

tar zxfv Mini-AMF-<version>.tar.gz
cd Mini-AMF-<version>

Then install using the setup.py script:

python setup.py install

This will byte-compile the Python source code and install it in the site-packages directory of your Python installation.

Unit Tests

Unit tests can also be run via setup.py. No additional modules are required:

python setup.py test

C Accelerator Module

The C accelerator module is broken, and will not be compiled or installed by default. If you want to experiment with it, supply the --with-accel option:

python setup.py --with-accel test

You will need Cython to build the module, and do not be surprised when the test runner crashes.

Documentation

To build the main documentation you need Sphinx 1.0 or newer.

From the doc subdirectory of the source distribution, run this command:

sphinx-build -b html . build

This will generate HTML documentation in the doc/build/html folder. This documentation is identical to the content on the main Mini-AMF website.

Architecture

Features

Here’s a brief description of the features in Mini-AMF. The CHANGES document contains a more detailed summary of all new features.

  • AMF0 encoder/decoder for legacy Adobe Flash Players (version 6-8)
  • AMF3 encoder/decoder for the new AMF format in Adobe Flash Player 9 and newer
  • Adapter framework
  • Local Shared Object support

Also see the plans for future development.

Type Map

Overview

The following is a guide to the ActionScript to Python type mappings.

Basic Types

The following types are available in Adobe Flash Player 6 and newer:

ActionScript Type Python Type
null None
undefined, void miniamf.Undefined
String unicode
Boolean bool
Number float
Date datetime.datetime
XML xml.etree.ElementTree.Element
Array list, tuple
Object dict
RecordSet miniamf.amf0.RecordSet
Typed Object (other than the above) class instance (registered via miniamf.register_class())
AMF3

The following types are available in the Adobe Flash Player 9 and newer:

ActionScript Type Python Type
int, uint int
ByteArray miniamf.amf3.ByteArray
DataInput miniamf.amf3.DataInput
DataOutput miniamf.amf3.DataOutput

Adapter Framework

Introduction

The Adapter Framework allows Mini-AMF to integrate nicely with other Python libraries. This includes setting up type conversions, class mappings, etc.

Adapters Overview

We currently have adapters for some of Python’s extended data structure types:

Extended types are converted to basic data types that AMF can serialize. An array.array, for instance, will arrive on the far end as a list.

How It Works

The adapter framework hooks into Python’s module loader, so you do not need to explicitly load adapter modules. When you import both miniamf and a library that Mini-AMF provides adapters for, the adapters will be activated. You can do this in either order:

import array
import miniamf

or

import miniamf
import array
Building Your Own Adapter

Your custom module:

1
2
3
4
5
# mymodule.py

class CustomClass(object):
    def __iter__(self):
        return iter([1, 2, 3])

Glue code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from miniamf.adapters import register_adapter


def when_imported(mod):
    """
    This function is called immediately after mymodule has been
    imported.  It configures Mini-AMF to encode a list when an instance
    of mymodule.CustomClass is encountered.
    """
    import miniamf

    miniamf.add_type(mod.CustomClass, lambda obj: list(obj))


register_adapter('mymodule', when_imported)

Class Mapping

Mini-AMF allows you to register aliases for remote Python classes that can be mapped to their corresponding Actionscript classes.

In this example we use the Python classes below.

1
2
3
4
5
6
7
8
class User(object):
    def __init__(self, name, password):
        self.name = name
        self.password = password

class Permission(object):
    def __init__(self, type):
        self.type = type

With the corresponding Actionscript 3.0 classes that were registered in the Flash Player using the flash.net.registerClassAlias utility:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class User
{
    public var name:String;
    public var pass:String;

    public function User(name:String, pass:String)
    {
        this.name = name;
        this.pass = pass
    }
}

public class Permission
{
    public var type:String;

    public function Permission(type:String)
    {
        this.type = type;
    }
}
Registering Classes

Classes can be registered and removed using the following tools:

  • miniamf.register_class()
  • miniamf.unregister_class()
  • miniamf.get_class_alias()
  • miniamf.register_package()

Continue reading for examples of these APIs.

Single Class

To register a class alias for a single class:

>>> miniamf.register_class("org.miniamf.User", User)

Find the alias registered to the class:

>>> print miniamf.get_class_alias(User)
org.miniamf.User

And to unregister by alias:

>>> miniamf.unregister_class("org.miniamf.User")

Or unregister by class:

>>> miniamf.unregister_class(User)
Multiple Classes

If you want to register multiple classes at the same time, or all classes in a module:

>>> import mymodule
>>> miniamf.register_package(mymodule, 'org.miniamf')

Now all instances of mymodule.User will appear in Actionscript under the alias ‘org.miniamf.User’. Same goes for mymodule.Permission - the Actionscript alias is ‘org.miniamf.Permission’. The reverse is also true, any objects with the correct aliases will now be instances of the relevant Python class.

This function respects the __all__ attribute of the module but you can have further control of what not to auto alias by populating the ignore argument with a list of classes that should be ignored.

This function provides the ability to register the module it is being called in, an example:

>>> miniamf.register_package('org.miniamf')

You can also supply a list of classes to register. An example, taking the example classes:

>>> miniamf.register_package([User, Permission], 'org.miniamf')

Future Development

This software is essentially finished. Mini-AMF provides complete support for encoding and decoding AMF versions 0 and 3. What with the general deprecation of Flash on the Web, I do not expect that there will be newer versions of AMF to support.

The older PyAMF software also supported types peculiar to Adobe Flex, had direct support for AMF-based RPC (“remoting”), and contained adapter classes for integration with several ORMs and web frameworks. All of that has been removed, primarily in the name of making it easier to support Python 3, and secondarily because the adapter classes were all broken when used with the current versions of their frameworks. I have no plans to add any of that back; I think server integration is properly a separate package, or perhaps several packages, one per framework.

PyAMF also included a C extension module for speed. The source code to this module is still included in Mini-AMF, but it is broken and has been disabled by default (you can activate it by giving setup.py the command line option --with-accel). I may eventually get around to fixing it.

Maintainers

Mini-AMF is lightly maintained by Zack Weinberg. To report bugs in Mini-AMF, please use Github issues.

Mini-AMF is not supported by anyone. We do not have the manpower to help you use it, nor to help you debug your program that uses it.

Former PyAMF maintainers

The people originally responsible for writing PyAMF, and maintaining it through its 0.8 release:

nick
Nick Joyce
thijs
Thijs Triemstra
feisley
Jacob Feisley
arnar
Arnar Birgisson
mvantellingen
Michael van Tellingen
gerard
Gerard Escalante
dthompso
Dave Thompson

Contributors

This section lists people who have contributed in some way to Mini-AMF or PyAMF. It is incomplete; if you feel that you or anyone else should be on this list, please let us know, and we’ll be glad to correct the problem.

  • Evert Pot
  • Bob Ippolito
  • Joachim Bauch
  • Antti Kaihola
  • Simon Zack

Thanks also to everyone who keeps sending feedback, helping us improve Mini-AMF.

Reporting Bugs in Mini-AMF

Bug reports should be submitted to the Github issue tracker.

See also

How to Report Bugs Effectively
Article which goes into some detail about how to create a useful bug report. This describes what kind of information is useful and why it is useful.
Bug Writing Guidelines
Information about writing a good bug report. Some of this is specific to the Mozilla project, but describes general good practices.

License

Copyright © 2007-2015 The PyAMF Project. Copyright © 2017 Zack Weinberg.

Mini-AMF is available under the terms of the MIT license:

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.

Changelog

This document contains a detailed log of the history of Mini-AMF.

0.9 (2017-03-07)

  • First release as Mini-AMF.
  • Supports Python 3.4 and greater.
  • Removed features:
    • Flex
    • Remoting
    • AppEngine, Django, SQLAlchemy, Twisted, and WSGI integration
    • Compatibility with Python 2.6 and older
  • C accelerator module disabled (it’s broken, even with Python 2)

0.8 (2015-12-17)

0.7.2 (2015-02-18)

  • Add support for Cython >= 0.15 (should be backward compatible with future releases)
  • Fix an issue in cpyamf where the class alias would not be cached correctly.

0.7.1 (2015-02-16)

  • Add support for Cython <= 0.22
  • Fix a bug in the AppEngine adapters where writeNull doesn’t exist in the C extensions

0.7 (2015-02-10)

  • Dropped support for Python 2.5. A Python 3 port is underway.
  • Fix a rare string collision bug with AMF3 #36
  • Updated to use the latest version of Cython (0.21.2) #34
  • Added Travis/coveralls support.
  • Add post processing callbacks to finalise the decoded payloads. #45
  • Added support for google.appengine.ext.ndb. #47
  • pyamf.Undefined now evaluates to False in a boolean expression (ticket 827)
  • Fixed an issue in the client where ‘; charset=utf8’ would be appended to the Content-Type response header (ticket 822)
  • Add support for collections.OrderedDict and collections.Counter (ticket 816, ticket 815)
  • pyamf.codec._Codec.__init__ now supports duck-typing. (ticket 835)
  • Enabled subclassed list/tuple to be overridden by pyamf.add_type before defaulting to writing a sequence. (ticket 834)
  • Numerical keys in a pyamf.MixedArray would cause an exception. Affects pure python decoder only. (ticket 843)
  • Fixed a segfault (the first ever!) in cpyamf caused by encoding subclassed tuples/list/sets. Thanks to wolever for the heavy lifting (ticket 830)
  • Add support for weakref’d objects (ticket 832)

0.6.1 (28-02-2011)

  • Switched to Distribute as the future of Python packaging (ticket 682)

0.6 (21-10-2010)

  • Ability to exclude ‘stock’ attributes with AppEngine Datastore/SQLAlchemy (ticket 790)
  • Fixed issue with Django models db_column not matching the attr name (ticket 807)
  • Added generator support (ticket 793, ticket 800)
  • Fixed issue with amf3.use_proxy_default=True and Flex messaging (ticket 794)
  • Support for AppEngine’s BlobReferenceProperty (ticket 787)
  • Improved unit test discovery with unittest2 (ticket 780)
  • Ability to define attribute synonyms (ticket 779)
  • Provide support for AMF3 remoting packets (BlazeDS acting as a client) (ticket 737, ticket 766)
  • AMF0 Remoting error tracebacks will be a list rather than a string (ticket 767, ticket 663)
  • Moved documentation from the Trac wiki to a local Sphinx documentation build (ticket 752, ticket 672, ticket 670, ticket 662, ticket 661, ticket 657)
  • Switch the PyAMF client to use urllib2. Provides support for proxying and gzipped responses. Thanks to @PaulWinkeler for the heavy lifting (ticket 751, ticket 622, ticket 590, ticket 566, ticket 778)
  • Added support for SQLAlchemy 0.6 (ticket 747, ticket 748)
  • Added support for the lxml library (ticket 735)
  • Introduced a new adapter for Elixir, a thin wrapper around SQLAlchemy (ticket 724)
  • Simplified type_map in Encoder classes (ticket 746)
  • Fixed a small bug when handling empty M2M relationships with unpersisted Django objects (ticket 741)
  • Updates to support Plasma (ticket 736)
  • Fixed a small bug in BaseGateway.removeService, thanks agronholm for the patch (ticket 729)
  • Pure Python AMF3 Decoding performance improvements (up to x3) (ticket 723)
  • Non-ascii characters in the exception message would cause a UnicodeError (ticket 727)
  • All ORM adapters will no longer set properties as static attributes (ticket 677)
  • Default to using __new__ for instance creation if available. (ticket 700)
  • Ability to unregister_type_alias (ticket 707)
  • __amf__.proxy actually works (ticket 712)
  • Django adapter now uses get_all_field_names to find model properties (ticket 625)
  • Added ClassAlias.bases and deep class tree support for typed classes (ticket 715)
  • use_references keyword arg has been removed from amf3.Encoder.write* (ticket 713)
  • ClassAlias.getEncodableAttributes now will return a single dict of properties (ticket 714)
  • PyAMF Client will raise an exception if the remote gateway returns a service error (ticket 260)
  • Fixed a reference bug with unsaved Django model instances. Thanks to wolver for the patch and tests (ticket 691).
  • Fixed a small bug in decoding Django relations when declared as static. Thanks to wolver for the patch. (ticket 693)
  • Removed exceptions from all Context and pyamf.util.Indexed* classes (ticket 660)
  • Empty Django relations are now encoded as None, not pyamf.Undefined (ticket 659)
  • pyamf.ClientType removed, as it is not spec compliant (ticket 651)

0.5.1 (2009-09-19)

  • pyamf.register_package can now accept a list of classes (ticket 650)
  • Fixed a regression in TwistedGateway where services would be called twice (ticket 648)
  • Fixed a bug with encoding anonymous trait references (ticket 644)
  • Moved IndexedCollection into cpyamf (ticket 424)
  • amf3.encode_int now encodes signed 29bit ints, not unsigned. Thanks to gerard for the report, investigation and patch! (ticket 646)

0.5 (2009-09-07)

  • Added the ability to modify the timezones of dates being de/encoded for legacy systems. (ticket 612)
  • Fixed a Django reference bug where parent.child.parent is parent would encode 3 objects and not 2. (ticket 642)
  • Setting None on a Django DateField would blow up the encoder (ticket 632)
  • rootCause in ErrorFault objects are now populated with the traceback object. (ticket 637)
  • Support for encoding/decoding BlazeDS specific messages (ticket 581)
  • Removed tracebacks from exception messages if debug=False (ticket 552)
  • Support for google.appengine.ext.db.polymodel.PolyModel (ticket 633)
  • Support for Django File/ImageField (ticket 631)
  • Support for Django model inheritance (ticket 626)
  • Rewrote attribute handling code. Added the ability to exclude, set read-only and static attributes. See http://pyamf.org/architecture/attributecontrol.html for more details (ticket 601)
  • Exposed the amf request object if expose_request=True. Twisted/Django/Google have an amf_request property on the http request object. WSGI has an entry in the environ dict now - pyamf.request (ticket 234)
  • Added support for the array module (ticket 468)
  • Fixed an issue with Django model AutoFields being set to 0 by the Flex client (ticket 556)
  • Added support for the collections module. (ticket 474)
  • Added type checks for class objects. (ticket 473)
  • GAE FloatProperty can now accept int without issue (ticket 609)
  • Revamped the lazy imports module to use sys.meta_path instead. Fixes all erroneous import errors (ticket 485).
  • Django models will now accept dynamic properties (ticket 575)
  • Django PK properties will be set first to allow related properties to apply correctly (ticket 599)
  • p.r.encode/p.r.decode both have a new logger kwarg. Supply a logging.Logger instance if you want to see debug output (ticket 588)
  • pyamf.TypedObjectClassAlias now forces the class type (ticket 537)
  • If a call to Decoder.readElement results in an IOError exception, the original position of the stream will be restored (ticket 573)
  • Replaced hardcoded Python implementation title in p.r.gateway.SERVER_NAME (ticket 541)
  • Provide a user friendly way to handle datetime.time objects (ticket 498)
  • Removed the useless pyamf.logging module (ticket 577)
  • Added a new register_package helper function to make bulk class registration easier. Check the docstring for more info. (ticket 576)
  • cpyamf.amf3._decode_int now propagates exceptions correctly (ticket 506)
  • Fixed an incorrect OverflowError when encoding large integers in AMF3 (ticket 519)
  • Added append to pyamf.util.BufferedByteStream (ticket 574)
  • Added Epydoc signatures to all util.StringIOProxy, util.DataTypeMixIn and util.BufferedByteStream classes (ticket 440)
  • Removed dependancy on fpconst. Platforms with broken platforms are detected and handled correctly internally (ticket 564)
  • amf0.Encoder now supports attribute ordering (ticket 558)
  • Removed duplicate method Context.reset, in favour of Context.clear (ticket 527)
  • Rewrote cpyamf.util.BufferedByteStream to not depend on cStringIO. Added a C based api for stream functions (ticket 513)
  • Unified exceptions for BufferedByteStream so that only IOError is raised. (ticket 520)
  • Made raising pyamf.ReferenceError optional for all Indexed* and Context classes. Refactored AMF3 so that only one ClassDefinition is created per class (ticket 524)
  • Strict type checking now on pyamf.util.BufferedByteStream (ticket 512)
  • Removed the default loggers from p.r.gateway.*. To re-enable supply a logger instance as a keyword arg to the gateway constructor (ticket 525)
  • Removed pyamf.util.make_classic_instance (as it is not used) (ticket 521)
  • Removed pyamf.util.get_mro, in favour of inspect.getmro() (ticket 526)
  • Removed pyamf.util.Indexed[Collection|Map].remove (ticket 518)

0.4.2 (2009-04-20)

  • Support for decoding the source property on ArrayCollection (ticket 488)
  • Fixed an issue in the GAE adapter where dynamic properties would be missing on referenced objects. (ticket 511)
  • Fixed a critical issue with AMF0 reference counting when encoding remoting responses. (ticket 510)
  • Strengthened HTTP header handling in the client (ticket 492)
  • Support for Django i18n ugettext_lazy (ticket 496)
  • Added support for microseconds for datetime objects. Thanks to Derek Payton for the patch. (ticket 490)
  • Added support for property types on SQLAlchemy mapped classes (ticket 491)
  • Added support for property types for Google AppEngine db.Model and db.Expando. (ticket 487)

0.4.1 (2009-02-23)

  • amf0.Encoder.use_amf3 has been extended to cover all object types (ticket 453, ticket 467)
  • Property types on Django models will now encode as expected. (ticket 480)
  • Django models.ForeignKey properties will be followed only if previously accessed outside of PyAMF. _[attr]_cache is no longer encoded. (ticket 456)
  • Encoding {0:0, '0':1} will now raise an AttributeError. (ticket 458)
  • Google AppEngine adapter improvements - see ticket for details (ticket 479)
  • amf0.Encoder will encode all elements as AMF3 if use_amf3 option is set to True (ticket 453)
  • Unicode handling in __repr__ functions has been improved (ticket 455)
  • object attributes and dict keys are now utf8 encoded bytestrings. Python **kwargs doesn’t accept unicode key objects. (ticket 463)
  • Django models.TimeField, models.DateField will now be converted to the correct type (datetime.time and datetime.date respectively). fields.NOT_PROVIDED is also checked for by converting to pyamf.Undefined and back again. (ticket 457)

0.4 (2009-01-18)

  • cpyamf now deals with exceptional floats the same way as pure Python - especially on Windows (ticket 448)
  • Support for SQLAlchemy 0.5.1 (ticket 449)
  • amf0.Encoder now has a use_amf3 flag which determines which XML type to return to the client (ticket 435)
  • BufferedByteStream.truncate(length) now actually does something useful (ticket 444)
  • setup.py now gets the version number from pyamf/__init__.py source (ticket 429)

0.4rc3 (2009-01-14)

  • Support for SQLAlchemy 0.5.0 (ticket 436)
  • pyamf.util.DataTypeMixIn/cpyamf.util.BufferedByteStream can now encode/decode 24bit un/signed integers. (ticket 422)
  • pyamf.util.StringIOProxy/cpyamf.util.BufferedByteStream both have new consume methods that will chop of the tail of the stream (already read stream). (ticket 423)
  • Now checking for all types of supported xml lib types for encoding, but will only use the first implementation for decoding (ticket 426)
  • fpconst dependancy is now only required if the platform requires it (ticket 356)
  • Decoding negative timestamps on certain platforms (namely Windows) are now supported (ticket 390)

0.4rc2 (2009-01-05)

  • Support for SQLAlchemy 0.4.0 (ticket 410)

0.4rc1 (2008-12-31)

  • Support for encoding/decoding SQLAlchemy ORM objects with a new adapter. Lots of people involved in this one, but special thanks to Dave Thompson and Michael Van Tellingen for making this happen. (ticket 277)
  • All gateways now log exceptions when exceptions are raised during en/decoding. (ticket 394)
  • Flex messaging now uses correct static attributes for encoding. Determining static/dynamic attributes on objects is now easier (ticket 357)
  • Added use_proxy option to amf3 which will automagically convert ObjectProxy to dict and ArrayCollection to list on decoding, and vice versa on encode. Thanks to dthompso for the excellent patch (ticket 355)
  • flex.ArrayCollection now subclasses list instead of dict as non-int keys are not allowed. IList interface has been implemented. (ticket 349)
  • Encoding registered subclass of list that define the ‘externalised’ metadata will be encoded as an object.
  • Encoders how have a ‘strict’ mode. Not generally useful for the time being but will help with developments in the future. Type mapped functions now require a second ‘encoder’ attribute. (ticket 378)
  • Added adapter to handle the decimal module and, if strict is set to False, silently converts a Decimal instance to a float (ticket 376)
  • ClassAlias can now be subclassed and three new methods have been added: applyAttributes, createInstance, getAttributes all which help to provide fine control for object/instance manipulation (ticket 348)
  • Added support for __slots__ (ticket 347)
  • Fixed problem when decoding objects that map to GAE db.Model objects with required properties (ticket 342)
  • ByteArray now does not throw an error when used in the Remoting framework (ticket 379)
  • A new adapter that converts sets.ImmutableSet and sets.Set to tuples before encoding. (ticket 280)
  • A revamped google app engine adapter that checks for the _key attribute in an aliased class and first loads the object from the datastore and then applies that properties in the object stream. (ticket 307)
  • New helper function to make it easier to manually add adapters (ticket 350)
  • Ability to disable the c extension with passing –disable-ext to setup.py (ticket 381, ticket 391)
  • Python C-extension for the pyamf.util.BufferedByteStream class. Originally contributed by Gerard Escalante (ticket 225, ticket 405)
  • New API to add headers such as cookies in pyamf.remoting.client (ticket 337)
  • Now clearing the context between remoting requests (ticket 309)
  • Fixed issue with AMF3 class definition references (ticket 341)
  • More helpful description for register_class args check (ticket 334)
  • pyamf.register_class now checks to ensure that __init__ args do not have any arguments (ticket 322)
  • Added RemoteObject support for AsyncMessage (ticket 292)
  • pyamf.remoting.ErrorFault.__repr__ now displays the traceback info (if it exists). (ticket 331)
  • Both Encoders will now raise pyamf.EncodeError if a function is encoded (ticket 311)
  • Twisted Gateway would fall over when returning tuples (ticket 313)
  • The remoting gateways now send a customizable Server header (ticket 317)
  • The remoting client now sends a customizable User-Agent header (ticket 306)
  • Added ability to set the HTTP referer in remoting client (ticket 316)
  • Fixed issue where the AMF3 encoder assumed objects with a ‘tag’ attribute needed XML encoding. Reported by cy-man (ticket 303)
  • Solved issue with repr for AbstractMessage. Reported by datafunk (ticket 283)
  • Content-type was missing in POST requests from the AMF client. Reported by magog (ticket 304)
  • Added the disconnect Command operation (ticket 325)
  • Fixed issue with the unit tests for Django (ticket 281)
  • Removed the NetworkIOMixIn class (ticket 232)

0.3.1 (2008-05-04)

  • Importing module now has tests (ticket 266)
  • Django model adapter now imported only when django.db.models is imported (ticket 261)
  • Google Model/Expando encoding now works out of the box
  • Fixed issue with Remote Object destination (ticket 270)
  • Added a new gateway for the Google App Engine - see pyamf.remoting.gateway.google.WebAppGateway (ticket 253)
  • amf0 Encoder now takes amf3 contexts into account (ticket 268)
  • amf*.encode helpers can now accept multiple arguments (ticket 267)
  • Removed the dependancy of fpconst for Python 2.5 or newer (ticket 243)
  • Solved issue with AMFPHP exceptions in AMF client (ticket 258)
  • Fixed issue with url parsing in AMF client (ticket 256)
  • Client no longer raises httplib.ResponseNotReady when making multiple requests using the same RemotingService (ticket 254)

0.3 (2008-04-14)

  • Added compatibility module for Google App Engine (ticket 247)
  • Fixed the signed interpretation of compressed integers in AMF3 (ticket 241)
  • Classic class decoding would throw an AttributeError (ticket 248)
  • Reloading adapter modules caused errors in Django, Pylons and Google App Engine. Resolved by removing dependancy on Importing module and incorporating into pyamf.util (ticket 250)
  • Adapter framework can now be fired when only loading submodules (ticket 246)
  • Made util.BufferedByteStream endian aware (ticket 231)
  • Fixed issue with Twisted threads (ticket 233)

0.2 (2008-03-12)

  • Removed amfinfo console_script (ticket 226)
  • Encoders/Decoders now check for __getstate__/__setstate__ respectively (ticket 209)
  • Gateway import hack has now been removed - permanently (ticket 224)
  • Encoding/decoding performance has been increased 2x for AMF0 and up-to 10x(!) for AMF3 (ticket 198)
  • Logging is now possible in all the supported gateways (ticket 173)
  • A new preprocessor function that runs after authentication, but before invoking the service method (ticket 196)
  • authenticator can now be decorated with expose_request (ticket 195)
  • Python 2.3 support (ticket 33)
  • Python 2.6 support (ticket 222)
  • Made PyAMF distributable as zip-based Python Egg (ticket 193)

0.1.1 (2008-02-18)

  • AMF3 encoder reported incorrect byte length header for non-ASCII string data. Patch supplied by akaihola. (ticket 194)
  • Decoder context not cleared between reading the remoting header and body. Reported by gerard (ticket 192)

0.1 (2008-02-11)

  • New error handling api useful for registering custom exception classes (ticket 185)
  • When a client receives a remoting error, an exception is generated (ticket 167)
  • expose_request per service control vastly improved (ticket 169)
  • Authentication per service control vastly improved (ticket 166)
  • uuid is no longer installed when using Python 2.5 or newer (ticket 182)
  • The inheritance tree was not consulted when encoding attributes (ticket 172)
  • TypedObjects didn’t work with old style classes (ticket 171)
  • ErrorFault now prints details (ticket 168)
  • Added expose_request to TwistedGateway (ticket 165)
  • TwistedGateway now expects deferred from service functions (ticket 164)

0.1b (2008-01-13)

  • IExternalizable now takes its methods from the class and fine grain control over attr encoding (ticket 110)
  • Added an adapter framework that gets imported when the related module is imported. See http://pyamf.org/architecture/adapters.html for more info
  • Added ‘expose_environ’ argument to WSGIGateway to expose the WSGI environ as the first arg in the called services.
  • Implemented Local Shared Object (LSO) support (ticket 11)
  • ByteArray now implements IDataInput and IDataOutput instead of StringIOProxy (ticket 151)
  • dicts are now used as the default for anonymous objects (ticket 131)
  • remoting.client mostly fully supports the predefined headers (defined at http://osflash.org/documentation/amf/envelopes/remoting/headers). The only one missing is amf_server_debug (ticket 39)
  • LazyImporter objects now set the __file__ attribute to None, so that querying sys.modules don’t accidentally import the underlying module (ticket 147)
  • Fixed argument positioning for RemoteObject processing. Thanks akaihola! (ticket 145)
  • ElementTree requirement is now ignored when using Python >= 2.5 (ticket 144)
  • Added tests for TwistedGateway (ticket 132)
  • Workaround for Python 2.4 float shortcomings (ticket 78)
  • Service Browser (‘DescribeService’ header) requests supported. (ticket 138)
  • Remoting client now supports authentication. (ticket 137)
  • Proper encoding for aliased subclassed builtin types, specifically flex.ArrayCollection.
  • Added support for easy encoding of Django object queries (Foo.objects.all())
  • Added ‘add_type’ allowing finer grain control of how a class is encoded in an AMF stream. (ticket 130)
  • ‘authenticator’ keyword added to all gateways (moved from ServiceRequest) (ticket 129)
  • Added expose_request argument to DjangoGateway to expose the underlying HTTP Request object as the first arg in the called services. (ticket 103)

0.1.0a (2007-12-12)

  • AMF0 and AMF3 encoders/decoders
  • Additional support for IExternalizable, ArrayCollection, ObjectProxy, ByteArray, RecordSet and RemoteObject
  • Remoting gateways for Twisted, WSGI, and Django
  • Authentication/setCredentials support
  • zlib compression support for ByteArray
  • Remoting client with httplib

0.0.1 (2007-10-19)

  • Started project based on previous work done in the RTMPy (http://rtmpy.org) project.

About these documents

These documents are generated from reStructuredText sources by Sphinx, a document processor specifically written for the official Python documentation.

See Reporting Bugs in Mini-AMF for how to report bugs in Mini-AMF.