{ "info": { "author": "Jeremy Carbaugh", "author_email": "jcarbaugh@sunlightfoundation.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python" ], "description": "================\ndjango-mediasync\n================\n\nOne of the more significant development roadblocks we have relates to local vs. \ndeployed media. Ideally all media (graphics, css, scripts) development would \noccur locally and not use production media. Then, when ready to deploy, the \nmedia should be pushed to production. That way there can be significant changes \nto media without disturbing the production web site.\n\nThe goal of mediasync is to develop locally and then flip a switch in production \nthat makes all the media URLs point to remote media URLs instead of the local \nmedia directory.\n\nAll code is under a BSD-style license, see LICENSE for details.\n\nSource: http://github.com/sunlightlabs/django-mediasync/\n\n\n------------\nRequirements\n------------\n\n* django >= 1.0\n* boto >= 1.8d\n* slimmer == 0.1.30 (optional)\n* python-cloudfiles == 1.7.5 (optional, for Rackspace Cloud Files backend)\n\n----------------------------\nUpgrading from mediasync 1.x\n----------------------------\n\n#. Update your mediasync settings as described in the next section.\n#. Run *./manage.py syncmedia --force* to force updates of all files:\n\t* gzip instead of deflate compression\n\t* sync both compressed and original versions of files\n#. add \"django.core.context_processors.request\" to TEMPLATE_CONTEXT_PROCESSORS\n\n-------------------------------------\n_`An important note about Django 1.3`\n-------------------------------------\n\nWhen DEBUG = True and the project is run with *manage.py runserver*, Django 1.3\nautomatically adds django.views.static.serve to urlpatterns. While this feature\nmakes local development easier for most people, it screws everything up if\nyou've added mediasync.urls to urlpatterns. As of now, the only way I can find\nto disable the automatic addition of django.views.static.serve is to use a full\nURL for STATIC_URL instead of just a path::\n\n STATIC_URL = \"http://localhost:8000/static/\"\n\n-------------\nConfiguration\n-------------\n\nsettings.py\n===========\n\nAdd to *INSTALLED_APPS*::\n\n 'mediasync'\n\nAdd to *TEMPLATE_CONTEXT_PROCESSORS*::\n\n\t'django.core.context_processors.request'\n\nMake sure your *STATIC_ROOT* setting is the correct path to your media::\n\n STATIC_ROOT = '/path/to/media'\n\nWhen media is being served locally (instead of from S3 or Cloud Files), \nmediasync serves media through a Django view. Set your *STATIC_URL* to what \nyou'd like that local media URL to be. This can be whatever you'd like, as long \nas you're using the {% media_url %} tag (more details on this later)::\n\n\tSTATIC_URL = 'http://localhost:8000/devmedia/'\n\n*STATIC_URL* is the URL that will be used in debug mode. Otherwise, \nthe *STATIC_URL* will be loaded from the backend settings. Please see\n`An important note about Django 1.3`_.\n\nThe following settings dict must also be added::\n\n MEDIASYNC = {\n 'BACKEND': 'path.to.backend',\n }\n\nIf you want to use a different media URL than that specified \nin *settings.STATIC_URL*, you can add *STATIC_URL* to the *MEDIASYNC* \nsettings dict::\n\n MEDIASYNC = {\n ...\n 'STATIC_URL': '/url/to/media/', # becomes http://yourhost.com/url/to/media/\n ...\n }\n\nSame goes for *STATIC_ROOT*::\n\n MEDIASYNC = {\n ...\n 'STATIC_ROOT': '/path/to/media/',\n ...\n }\n\nmediasync supports pluggable backends. Please see below for information on \nthe provided backends as well as directions on implementing your own.\n\nMedia expiration\n----------------\n\nIf the client supports media expiration, all files are set to expire 365 days \nafter the file was synced. You may override this value by adding \n*EXPIRATION_DAYS* to the MEDIASYNC settings dict.\n\n::\n\n # Expire in 10 years.\n MEDIASYNC['EXPIRATION_DAYS'] = 365 * 10\n\nServing media remote (S3/Cloud Files) or locally\n------------------------------------------------\n\nThe media URL is selected based on the *SERVE_REMOTE* attribute in the\n*MEDIASYNC* dict in settings.py. When *True*, media will be served locally \ninstead of from S3.\n\n::\n\n # This would force mediasync to serve all media through the value\n # specified in settings.STATIC_URL.\n MEDIASYNC['SERVE_REMOTE'] = False\n \n # This would serve all media through S3/Cloud Files.\n MEDIASYNC['SERVE_REMOTE'] = True\n \n # This would serve media locally while in DEBUG mode, and remotely when\n # in production (DEBUG == False).\n MEDIASYNC['SERVE_REMOTE'] = not DEBUG\n \nWhen serving files locally, you can emulate the CSS/JS combo/minifying\nbehavior we get from using media processors by specifying the following.\n\n::\n\n MEDIASYNC['SERVE_REMOTE'] = False\n MEDIASYNC['EMULATE_COMBO'] = True\n\nNote that this will only work if your *STATIC_URL* is pointing at your\nDjango dev server. Also keep in mind that some processors may take a while,\nand is best used to check things over before rolling out to production.\n\nDOCTYPE\n-------\n\nlink and script tags are written using XHTML syntax. The rendering can be \noverridden by using the *DOCTYPE* setting. Allowed values are *'html4'*, \n*'html5'*, or *'xhtml'*. The default in mediasync 2.0 is html5, just as\nthe DOCTYPE on your site should be.\n\n::\n\n MEDIASYNC['DOCTYPE'] = 'html5'\n\nFor each doctype, the following tags are rendered:\n\nhtml4\n~~~~~\n\n::\n\n \n \n\nhtml5\n~~~~~\n\n::\n\n \n \n\nxhtml\n~~~~~\n\n::\n\n \n \n\n\nSSL\n---\n\nmediasync will attempt to intelligently determine if your media should be\nserved using HTTPS. In order to use automatic SSL detection,\n*django.core.context_processors.request* must be added to\n*TEMPLATE_CONTEXT_PROCESSORS* in settings.py::\n\n TEMPLATE_CONTEXT_PROCESSORS = (\n ...\n 'django.core.context_processors.request',\n ...\n )\n\nThe *USE_SSL* mediasync setting can be used to override the SSL\nURL detection.\n\n::\n\n # Force HTTPS.\n MEDIASYNC['USE_SSL'] = True \n\nor\n\n:: \n\n # Force HTTP.\n MEDIASYNC['USE_SSL'] = False\n\nSome backends will be unable to use SSL. In these cases *USE_SSL* and SSL\ndetection will be ignored.\n\nurls.py\n=======\n\nTo serve local media through mediasync, add a reference to mediasync.urls in\nyour main urls.py file.\n\n::\n\n urlpatterns = ('',\n ...\n url(r'^', include('mediasync.urls)),\n ...\n )\n\nBackends\n========\n\nmediasync now supports pluggable backends. A backend is a Python module that \ncontains a Client class that implements a mediasync-provided BaseClient class.\n\nS3\n--\n\n::\n\n MEDIASYNC['BACKEND'] = 'mediasync.backends.s3'\n\nSettings\n~~~~~~~~\n\nThe following settings are required in the mediasync settings dict::\n\n MEDIASYNC = {\n \t'AWS_KEY': \"s3_key\",\n \t'AWS_SECRET': \"s3_secret\",\n \t'AWS_BUCKET': \"bucket_name\",\n }\n\nOptionally you may specify a path prefix::\n\n\tMEDIASYNC['AWS_PREFIX'] = \"key_prefix\"\n\nAssuming a correct DNS CNAME entry, setting *AWS_BUCKET* to \n*assets.sunlightlabs.com* and *AWS_PREFIX* to *myproject/media* would \nsync the media directory to http://assets.sunlightlabs.com/myproject/media/.\n\nAmazon allows users to create DNS CNAME entries to map custom domain names \nto an AWS bucket. MEDIASYNC can be configured to use the bucket as the media \nURL by setting *AWS_BUCKET_CNAME* to *True*.\n\n::\n\n\tMEDIASYNC['AWS_BUCKET_CNAME'] = True\n\nIf you would prefer to not use gzip compression with the S3 client, it can be\ndisabled::\n\n MEDIASYNC['AWS_GZIP'] = False\n\nTips\n~~~~\n\nSince files are given a far future expires header, one needs a way to do \n\"cache busting\" when you want the browser to fetch new files before the expire \ndate arrives. One of the best and easiest ways to accomplish this is to alter \nthe path to the media files with some sort of version string using the key \nprefix setting::\n\n MEDIASYNC['AWS_PREFIX'] = \"myproject/media/v20001201\"\n\nGiven that and the above DNS CNAME example, the media directory URL would end \nup being http://assets.sunlightlabs.com/myproject/media/v20001201/. Whenever \nyou need to update the media files, simply update the key prefix with a new \nversioned string.\n\nA *CACHE_BUSTER* settings can be added to the main *MEDIASYNC* settings \ndict to add a query string parameter to all media URLs. The cache buster can \neither be a value or a callable which is passed the media URL as a parameter.\n\n::\n\n\tMEDIASYNC['CACHE_BUSTER'] = 1234567890\n\nThe above setting will generate a media path similar to::\n\n\thttp://yourhost.com/url/to/media/image.png?1234567890\n\t\nAn important thing to note is that if you're running your Django site in a\nmulti-threaded or multi-node setup, you'll want to be careful about using a \ntime-based cache buster value. Each worker/thread will probably have a slightly \ndifferent value for datetime.now(), which means your users will find themselves\nhaving cache misses randomly from page to page. \n\nRackspace Cloud Files\n---------------------\n\n::\n\n MEDIASYNC['BACKEND'] = 'mediasync.backends.cloudfiles'\n\nSettings\n~~~~~~~~\n\nThe following settings are required in the mediasync settings dict::\n\n MEDIASYNC = {\n \t'CLOUDFILES_CONTAINER': 'container_name',\n \t'CLOUDFILES_USERNAME': 'cf_username',\n \t'CLOUDFILES_API_KEY': 'cf_apikey',\n }\n\nTips\n~~~~\n\nThe Cloud Files backend lacks support for the following features:\n\n* setting HTTP Expires header\n* setting HTTP Cache-Control header\n* content compression (gzip)\n* SSL support\n* conditional sync based on file checksum\n\nCustom backends\n---------------\n\nYou can create a custom backend by creating a Python module containing a Client \nclass. This class must inherit from mediasync.backends.BaseClient. Additionally, \nyou must implement two methods::\n\n\tdef remote_media_url(self, with_ssl):\n\t ...\n\n*remote_media_url* returns the full base URL for remote media. This can be \neither a static URL or one generated from mediasync settings::\n\n\tdef put(self, filedata, content_type, remote_path, force=False):\n\t ...\n\nput is responsible for pushing a file to the backend storage.\n\n* filedata - the contents of the file\n* content_type - the mime type of the file\n* remote_path - the remote path (relative from remote_media_url) to which \n the file should be written\n* force - if True, write file to remote storage even if it already exists\n\nIf the client supports gzipped content, you will need to override supports_gzip\nto return True::\n\n\tdef supports_gzip(self):\n\t\treturn True\n\nFile Processors\n===============\n\nFile processors allow you to modify the content of a file as it is being\nsynced or served statically. \n\nMediasync ships with three processor modules:\n\n1. ``slim`` is a minifier written in Python and requires the\n `slimmer` Python package. The Python package can be found here:\n http://pypi.python.org/pypi/slimmer/\n\n2. ``yuicompressor`` is a minifier written in Java and can be downloaded\n from YUI's download page: http://developer.yahoo.com/yui/compressor/.\n This processor also requires an additional setting, as defined below.\n `yuicompressor` is new and should be considered experimental until \n the mediasync 2.1 release.\n\n3. ``closurecompiler`` is a javascript compiler provided by Google.\n\nCustom processors can be specified using the *PROCESSORS* entry in the\nmediasync settings dict. *PROCESSORS* should be a list of processor entries.\nEach processor entry can be a callable or a string path to a callable. If the\npath is to a class definition, the class will be instantiated into an object.\nThe processor callable should return a string of the processed file data, None\nif it chooses to not process the file, or raise *mediasync.SyncException* if\nsomething goes terribly wrong. The callable should take the following arguments::\n\n\tdef proc(filedata, content_type, remote_path, is_active):\n\t\t...\n\nfiledata\n\tthe content of the file as a string\n\ncontent_type\n\tthe mimetype of the file being processed\n\nremote_path\n\tthe path to which the file is being synced (contains the file name)\n\nis_active\n\tTrue if the processor should... process\n\nIf the *PROCESSORS* setting is used, you will need to include the defaults\nif you plan on using them::\n\n\t'PROCESSORS': (\n\t 'mediasync.processors.slim.css_minifier',\n\t 'mediasync.processors.slim.js_minifier',\n\t\t...\n\t),\n\nmediasync will attempt to use `slimmer` by default if you have the package\ninstalled and do not use the PROCESSORS setting.\n\nGoogle Closure Compiler\n-----------------------\n\nGoogle's JavaScript Closure Compiler provides an API that allows files to be\ncompressed without installing anything locally. To use the service::\n\n 'PROCESSORS': ('mediasync.processors.closurecompiler.compile',)\n\nYUI Compressor\n--------------\n\nTo configure YUI Compressor you need to define a `PROCESSORS` and\n`YUI_COMPRESSOR_PATH` as follows, assuming you placed the \".jar\" file in\nyour `~/bin` path::\n\n 'PROCESSORS': ('mediasync.processors.yuicompressor.css_minifier',\n 'mediasync.processors.yuicompressor.js_minifier'),\n 'YUI_COMPRESSOR_PATH': '~/bin/yuicompressor.jar',\n\n--------\nFeatures\n--------\n\nIgnored Directories\n===================\n\nAny directory in *STATIC_ROOT* that is hidden or starts with an underscore \nwill be ignored during syncing.\n\n\nTemplate Tags\n=============\n\nWhen referring to media in HTML templates you can use custom template tags. \nThese tags can by accessed by loading the media template tag collection.\n\n::\n\n\t{% load media %}\n\nAny tag that has a path argument can use either a string or a variable::\n\n {% media_url \"images/avatar.png\" }\n {% media_url user.profile.avatar_path %}\n\nIf you'd like to make the mediasync tags global, you can add the following to\nyour master urls.py file::\n\n from django.template import add_to_builtins\n add_to_builtins('mediasync.templatetags.media')\n\nSome backends (S3) support https URLs when the requesting page is secure.\nIn order for the https to be detected, the request must be placed in the\ntemplate context with the key 'request'. This can be done automatically by\nadding 'django.core.context_processors.request' to *TEMPLATE_CONTEXT_PROCESSORS*\nin settings.py\n\nmedia_url\n---------\n\nRenders the STATIC_URL from settings.py with trailing slashes removed.\n\n::\n\n\t\n\nSTATIC_URL takes an optional argument that is the media path. Using the argument\nallows mediasync to add the CACHE_BUSTER to the URL if one is specified.\n\n::\n\n\t\n\nIf *CACHE_BUSTER* is set to 12345, the above example will render as::\n\n\t\n\t\n*NOTE*: Don't use this tag to serve CSS or JS files. Use the js and css tags\nthat were specifically designed for the purpose.\n\n\njs\n--\n\nRenders a script tag with the correct include.\n\n::\n\n\t{% js \"myfile.js\" %}\n\n\ncss\n---\n\nRenders a tag to include the stylesheet. It takes an optional second \nparameter for the media attribute; the default media is \"screen, projector\".\n\n::\n\n\t{% css \"myfile.css\" %} \n\t{% css \"myfile.css\" \"screen\" %} \n\n\ncss_print\n---------\n\nShortcut to render as a print stylesheet.\n\n::\n\n\t{% css_print \"myfile.css\" %}\n\nwhich is equivalent to\n\n::\n\n\t{% css \"myfile.css\" \"print\" %}\n\nWriting Style Sheets\n====================\n\nUsers are encouraged to write stylesheets using relative URLS. The media \ndirectory is synced with S3 as is, so relative local paths will still work \nwhen pushed remotely.\n\n::\n\n\tbackground: url(../images/arrow_left.png);\n\n\nJoined files\n============\n\nWhen serving media in production, it is beneficial to combine JavaScript and \nCSS into single files. This reduces the number of connections the browser needs \nto make to the web server. Fewer connections can dramatically decrease page \nload times and reduce the server-side load.\n\nJoined files are specified in the *MEDIASYNC* dict using *JOINED*. This is\na dict that maps individual media to an alias for the joined files. \n\n::\n\n 'JOINED': {\n 'styles/joined.css': ['styles/reset.css','styles/text.css'],\n 'scripts/joined.js': ['scripts/jquery.js','scripts/processing.js'],\n },\n\nFiles listed in *JOINED* will be combined and pushed to S3 with the name of \nthe alias. The individual CSS files will also be pushed to S3. Aliases must end \nin either .css or .js in order for the content-type to be set appropriately.\n\nThe existing template tags may be used to refer to the joined media. Simply use \nthe joined alias as the argument::\n\n\t{% css_print \"joined.css\" %}\n\nWhen served locally, template tags will render an HTML tag for each of the files \nthat make up the joined file::\n\n\t\n\t\n\nWhen served remotely, one HTML tag will be rendered with the name of the joined file::\n\n\t\n\nSmart GZIP for S3\n=================\n\nIn previous versions of mediasync's S3 client, certain content was always pushed\nin a compressed format. This can cause major issues with clients that do not\nsupport gzip. New in version 2.0, mediasync will push both a gzipped and an\nuncompressed version of the file to S3. The template tags look at the request\nand direct the user to the appropriate file based on the ACCEPT_ENCODING HTTP\nheader. Assuming a file styles/layout.css, the following would be synced to S3::\n\n\tstyles/layout.css\n\tstyles/layout.css.gz\n\nSignals\n=======\n\nmediasync provides two signals that allow you to hook into the syncing\nprocess. *pre_sync* is sent after the client is opened, but before the first\nfile is synced. *post_sync* is sent after the last file is synced, but before\nthe client is closed. This allows you to call commands on the client without\nhaving to worry about its state. The signals allow you to do common tasks such\nas calling Django 1.3's collectstatic command, process SASS stylesheets, or\nclean up files generated during a pre_sync process.\n\ncollectstatic receiver\n----------------------\n\nA receiver for calling the collectstatic management command is provided::\n\n from mediasync.signals import pre_sync, collectstatic_receiver\n \n # run collectstatic before syncing media\n pre_sync.connect(collectstatic_receiver)\n\nSASS receiver\n-------------\n\nA receiver for compiling SASS into CSS is provided::\n\n from mediasync.signals import pre_sync, sass_receiver\n \n # compile SASS files before syncing media\n pre_sync.connect(sass_receiver)\n\nAny file in static root that has the *sass* or *scss* file extension will be\ncompiled into CSS. The compiled CSS file will be placed in the same directory\nand the original extension will be replaced with *css*. If a file exists with\nthe same *css* extension, it will be overwritten.\n\nBy default mediasync uses the *sass* command with no options. If you would\nlike to specify your own command, specify *SASS_COMMAND* in settings::\n\n MEDIASYNC = {\n ...\n 'SASS_COMMAND': 'sass -scss -l',\n ...\n }\n\n-----------------\nRunning MEDIASYNC\n-----------------\n\n::\n\n ./manage.py syncmedia\n\n----------\nChange Log\n----------\n\n2.2.0\n======================\n\n* added pre_sync and post_sync signals\n* provide basic receiver for calling collectstatic before syncing\n* provide receiver for compiling SASS before syncing\n* show media directory listing when serving locally in debug mode\n* add processor for Google's Closure Compiler API for JavaScript\n* template tags can now take a variable as the path argument\n\n2.1.0\n=====\n\n* default to using STATIC_URL and STATIC_ROOT (Django 1.3), falling back\n to MEDIA_URL and MEDIA_ROOT if the STATIC_* settings are not set\n* add AWS_GZIP setting to optionally disable gzip compression in S3 client\n\nThanks to Rob Hudson and Dolan Antenucci for their contributions to this\nrelease.\n\n2.0.0\n=====\n\n* updated Rackspace Cloud Files backend\n* use gzip instead of deflate for compression (better browser support)\n* smart gzip client support detection\n* add pluggable backends\n* add pluggable file processors\n* experimental YUI Compressor\n* settings refactor\n* allow override of *settings.MEDIA_URL*\n* Improvements to the logic that decides which files to sync. Safely ignore\n a wider variety of hidden files/directories.\n* Make template tags aware of whether the current page is SSL-secured. If it\n is, ask the backend for an SSL media URL (if implemented by your backend).\n* made SERVE_REMOTE setting the sole factor in determining if\n media should be served locally or remotely\n* add many more tests\n* deprecate CSS_PATH and JS_PATH\n\nThanks to Greg Taylor, Peter Sanchez, Jonathan Drosdeck, Rich Leland,\nand Rob Hudson for their contributions to this release.\n\n1.0.1\n=====\n\n* add application/javascript and application/x-javascript to JavaScript\n mimetypes\n* break out of CSS and JS mimetypes\n* add support for HTTPS URLs to S3\n* allow for storage of S3 keys in ~/.boto configuration file\n\nThanks to Rob Hudson and Peter Sanchez for their contributions.\n\n1.0.0\n=====\n\nInitial release.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/sunlightlabs/django-mediasync/", "keywords": null, "license": "BSD License", "maintainer": null, "maintainer_email": null, "name": "django-mediasync", "package_url": "https://pypi.org/project/django-mediasync/", "platform": "any", "project_url": "https://pypi.org/project/django-mediasync/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/sunlightlabs/django-mediasync/" }, "release_url": "https://pypi.org/project/django-mediasync/2.2.0/", "requires_dist": null, "requires_python": null, "summary": "Django static media development and distribution tools", "version": "2.2.0" }, "last_serial": 790063, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "64022b02878df83535ee3fbc88d36a31", "sha256": "647f097481177914b8ab9a78517500deac477d96f7e1a090752ffe436b0e98b7" }, "downloads": -1, "filename": "django-mediasync-1.0.tar.gz", "has_sig": false, "md5_digest": "64022b02878df83535ee3fbc88d36a31", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12624, "upload_time": "2009-10-26T15:32:51", "url": "https://files.pythonhosted.org/packages/38/8a/443c8c527d1b0df739b705d0dcea94215dbada19bd659cd02ed21a4245dc/django-mediasync-1.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "2aea51d077a3dd88f033f357ed2bf2ac", "sha256": "e8657db621a41d514b38205f88295f00d756fd34a8f1549cb65c5d720df8b0ff" }, "downloads": -1, "filename": "django-mediasync-1.0.1.tar.gz", "has_sig": false, "md5_digest": "2aea51d077a3dd88f033f357ed2bf2ac", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11679, "upload_time": "2010-03-17T20:39:28", "url": "https://files.pythonhosted.org/packages/5c/5c/a74520ea5a883d18ed10de6153ad7b320e0822eaa2174d46474b397bb07d/django-mediasync-1.0.1.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "f6467caafdc49c24cfd885984568183b", "sha256": "a71a0458beb6924e02a0d01c4493cb6ecf2d9bc47bc90af33f6bd096b6b2738e" }, "downloads": -1, "filename": "django-mediasync-2.0.0.tar.gz", "has_sig": false, "md5_digest": "f6467caafdc49c24cfd885984568183b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29888, "upload_time": "2011-01-20T18:05:21", "url": "https://files.pythonhosted.org/packages/36/31/a56811c11bba35364e6f7072d8e6a24219c1c7250dd5b5450d353bdf6dae/django-mediasync-2.0.0.tar.gz" } ], "2.1.0": [ { "comment_text": "", "digests": { "md5": "2689b412246460cab0766f4bab359c2f", "sha256": "fde47a7295b637d967260fdc3a312b2e4dbf08ab492314085116f90eea004ab5" }, "downloads": -1, "filename": "django-mediasync-2.1.0.tar.gz", "has_sig": false, "md5_digest": "2689b412246460cab0766f4bab359c2f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30306, "upload_time": "2011-03-04T20:27:46", "url": "https://files.pythonhosted.org/packages/92/b8/d7465a13b7d4869ef40be223c1a6f63bf8b54e7b05b74ea33f5cf371da9d/django-mediasync-2.1.0.tar.gz" } ], "2.2.0": [ { "comment_text": "", "digests": { "md5": "df0c71b8c0d98e09a514fa3e578933c3", "sha256": "cdbc0bbcc3299f449bc595fe2d1fe59a77e0da1dc00374935f1e9dda3da59b45" }, "downloads": -1, "filename": "django-mediasync-2.2.0.tar.gz", "has_sig": false, "md5_digest": "df0c71b8c0d98e09a514fa3e578933c3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34372, "upload_time": "2011-07-08T21:34:10", "url": "https://files.pythonhosted.org/packages/8c/98/0e13774c645f092ce221e9b2e44f6c195dc4abfc5fe34b04ad86409790da/django-mediasync-2.2.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "df0c71b8c0d98e09a514fa3e578933c3", "sha256": "cdbc0bbcc3299f449bc595fe2d1fe59a77e0da1dc00374935f1e9dda3da59b45" }, "downloads": -1, "filename": "django-mediasync-2.2.0.tar.gz", "has_sig": false, "md5_digest": "df0c71b8c0d98e09a514fa3e578933c3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34372, "upload_time": "2011-07-08T21:34:10", "url": "https://files.pythonhosted.org/packages/8c/98/0e13774c645f092ce221e9b2e44f6c195dc4abfc5fe34b04ad86409790da/django-mediasync-2.2.0.tar.gz" } ] }