{ "info": { "author": "Bright Interactive", "author_email": "francis@bright-interactive.co.uk", "bugtrack_url": null, "classifiers": [], "description": "Asset Cloud\n===========\n\nAsset Cloud is a Cloud-based, highly configurable light-weight DAM system.\n\nAsset Cloud is the base application of Asset Share, and there are some references to Asset Share throughout the application, mostly in static files and templates.\n\nPlease see the [AssetCloud Wiki](http://wiki.bright-interactive.com/display/knowhow/Asset+Cloud) for more of an overview.\n\nSee the [Project Backlog](https://spreadsheets.google.com/a/bright-interactive.co.uk/spreadsheet/ccc?key=0AgTdJwbo2dsWdEY0MnRWVWlCQ01pVGtJNjcxYXNJRHc&hl=en_US) for features, timescales & planning.\n\nPrerequisites\n-------------\n\n* python 2.7 (wide build, i.e. configured with --enable-unicode=ucs4)\n* virtualenv\n* libjpeg or jpeg\n\nIf you don't want to use a wide build of Python on a *developer* machine then you can add `WIDE_CHAR_TESTS = False` to `project/settings/local_common.py`.\n\nIf you are using MacPorts use:\n\n sudo port install python27 +ucs4\n sudo port install py27-virtualenv\n sudo port install jpeg\n\nIf you are running Mac OSX, you will need the following items to run the Selenium tests:\n\n Google Chrome - Installation instructions and download at https://www.google.com/intl/en/chrome/browser/ \n chromedriver - Installation instructions and download at http://code.google.com/p/chromedriver/downloads/list\n\n\nInstallation\n------------\n\nTo clone the repo:\n\n git clone git@github.com:brightinteractive/assetcloud.git\n\nTo setup:\n\n . ./activate\n\nTo run the project:\n\n . ./activate\n ./manage syncdb --noinput --migrate\n ./manage runserver\n # Login with `admin@bright-interactive.co.uk`/`password`\n\nTo run the tests:\n\n ./manage test apps assetcloud_example\n\nIf you are running the tests on Mac OSX, you will need to configure Selenium to use chromedriver by including the following lines in your local settings file (project/settings/local_common.py):\n\n import os\n WEBDRIVERPLUS_BROWSER ='chrome'\n # Put /usr/local/bin on the PATH so that /usr/local/bin/chromedriver can be found\n os.environ['PATH'] = '/usr/local/bin:' + os.environ['PATH']\n\nBecause Assetcloud is a reusable application, it is very important to always use named URLs.\nTo make sure that this is being done, there is a second testing configuration which runs all the tests on an alternative url layout.\nYou can run tests for this layout using ./manage test apps assetcloud_example --settings=settings.testing_alternative_urls.\nYou don't have to run the full test suite for both configurations, but it's recommended that you do run it for your new tests.\n\nUpgrading to version 0.15.x and above\n-------------------------\n\nVersion 0.15 removed the default UserProfile from the assetcloud code, replacing it with an abstract BaseUserProfile to\nallow custom profiles between apps.\n\n* If you are upgrading from an earlier version and planning to upgrade to 2.0.0, it is advised NOT to create the user profiles\nbefore updating to version 2.0.0, or at least postpone committing your UserProfile migrations so that you can recreate them\ninstead of migrating primary keys! *\n\nTo use it create a model extending the BaseUserProfile in your project's main app and add the following line in\nsettings.py:\n\n AUTH_PROFILE_MODULE=\"my_app_name.MyUserProfileModel\"\n\nYou need to have this option for assetcloud to work, and your UserProfile must extend BaseUserProfile. The simplest\nimplementation of a UserProfile model would be:\n\n class MyUserProfileModel(BaseUserProfile):\n pass\n\nYou will also need to migrate any existing user profiles to your new profile class so you will need a data migration similar to this:\n\n class Migration(DataMigration):\n\n needed_by = (\n ('assetcloud', '0061_auto__del_userprofile'),\n )\n\n def forwards(self, orm):\n\n old_profiles = orm['assetcloud.userprofile'].objects.all()\n\n for old_profile in old_profiles:\n new_profile = orm['assetcloud_example.UserProfile']()\n new_profile.__dict__.update(old_profile.__dict__)\n new_profile.save()\n\nIt is important to add the needed_by dependency to have this migration run before the migration which deletes the existing user profiles the existing user profiles.\nYou will need to manually copy the models dict entry for 'assetcloud.userprofile' from `0060_auto__chg_field_account_storage.py` (the last migration containing assetcloud.userprofile) to this migration to avoid the error `KeyError: \"The model 'userprofile' from the app 'assetcloud' is not available in this migration.\"*`\n\nUpgrading to version 2.2.0 and above\n------------------------------------\n\nIf you were relying on assetcloud's git_tag method in your fabfiles, you will now need to add a new environment variable in your fabfile to define which applications the tests should run against\n\n env.test_apps = ['apps', 'assetcloud_example']\n\n\nUpgrading to version 2.x.x and above\n-------------------------\n\n### Django 1.6 Transactions\n\nYou need to change any fixture references in migrations from relative paths to absolute paths.\n\nYou will also need to remove the following item from the Django Middleware classes in the settings file:\n\n 'django.middleware.transaction.TransactionMiddleware',\n\nand replace it with this:\n\n ATOMIC_REQUESTS = True\n\nSee https://docs.djangoproject.com/en/1.6/topics/db/transactions/#transaction-middleware for more details.\n\n### Upgrade Haystack\n\nIn addtion to the above changes, you will need to replace the existing Haystack configuration with the new Haystack 2.x approach, see:\n\n http://django-haystack.readthedocs.org/en/latest/migration_from_1_to_2.html\n \nSpecifically make sure you upgrade your old style configurations\n \n HAYSTACK_SEARCH_ENGINE = 'solr'\n HAYSTACK_SOLR_URL = 'http://localhost:9001/solr/default'\n\nto the new style configuration\n\n HAYSTACK_CONNECTIONS = {\n 'default': {\n 'ENGINE': 'haystack.backends.solr_backend.SolrEngine',\n 'URL': 'http://localhost:9001/solr/default',\n 'TIMEOUT': 60 * 5,\n 'INCLUDE_SPELLING': True,\n 'BATCH_SIZE': 100,\n },\n }\n \nMake sure to upgrade your local configuration files\n\nIf you are conditionally using settings in your testing configuration you can use something like:\n\n if HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'haystack.backends.whoosh_backend.WhooshEngine':\n HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(TESTING_TEMP_DIR, 'databases/index.whoosh')\n elif HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'haystack.backends.solr_backend.SolrEngine':\n # Replace the last element of the URL with 'test'\n # For example 'http://plumpton:8280/solr/main' will be changed to\n # 'http://plumpton:8280/solr/test'\n url_components = HAYSTACK_CONNECTIONS['default']['URL'].split('/')\n url_components[-1] = 'test'\n HAYSTACK_CONNECTIONS['default']['URL'] = '/'.join(url_components)\n \nTo use our queued index processor you will need to add the setting:\n\n HAYSTACK_SIGNAL_PROCESSOR = \"assetcloud.search_indexes.AssetQueuedSignalProcessor\"\n\n### Upgrade Taggit\n\nVersion 2.0.0 introduced support for Django 1.6.8 and included various other package upgrades to support this version of Django. As part of an upgrade to django-taggit,\nit is necessary to add the following snippet to the common settings file for the project:\n\n SOUTH_MIGRATION_MODULES = {\n 'taggit': 'taggit.south_migrations',\n }\n\nIt is also necessary to run the following command to ensure the correct operation of south migrations:\n\n python manage.py migrate taggit --fake 0001\n \nFor rollouts you can do something in the lines of:\n \n with cd(get_vhost_dir()):\n \n def get_version(package):\n version = run('. activate; pip freeze | grep ' + package)\n if \"==\" in version:\n return version.split(\"==\")[1]\n \n previous_taggit_version = get_version('django-taggit')\n \n ... run the virtual env commands to rebuild ...\n \n new_taggit_version = get_version('django-taggit')\n \n ... then before running the migrations ...\n \n if StrictVersion(previous_taggit_version) < StrictVersion('0.10.0') <= StrictVersion(new_taggit_version):\n run('. activate; ./manage migrate taggit 0001 --fake')\n\n### Upgrade Social auth\n\nSimilar to taggit, social auth introduced migrations in v0.7.18 and the first one needs to be faked:\n\nIt is also necessary to run the following command to ensure the correct operation of south migrations:\n\n python manage.py migrate social_auth --fake 0001\n \nFor rollouts you can do something in the lines of:\n \n with cd(get_vhost_dir()):\n \n def get_version(package):\n version = run('. activate; pip freeze | grep ' + package)\n if \"==\" in version:\n return version.split(\"==\")[1]\n \n previous_social_auth_version = get_version('django-social-auth')\n \n ... run the virtual env commands to rebuild ...\n \n new_social_auth_version = get_version('django-social-auth')\n \n ... then before running the migrations ...\n \n if StrictVersion(previous_social_auth_version) < StrictVersion('0.7.18') <= StrictVersion(new_social_auth_version):\n run('. activate; ./manage migrate social_auth 0001 --fake')\n\n\n### Re-instate Ids in User Profiles\n\nIf you are upgrading from version 0.15.x or newer, you will have to execute another migration in the user profiles to\nreintroduce the id field (Removed when factoring out User Profiles).\n\nTo do so run the following:\n\n ./manage schemamigration your_app_name --auto\n\nWhen asked, just add any value to use as default and then edit the migration as follows (Only tnabot should needto do \nthis tested on mysql, sqlite and postgres):\n\n def forwards(self, orm):\n\n try:\n db.delete_foreign_key(u'tnabot_subscription', u'user_profile_id')\n db.delete_foreign_key(u'tnabot_userprofile', u'user_id')\n except Exception:\n pass\n\n db.delete_primary_key(u'tnabot_userprofile')\n\n # Adding field 'UserProfile.id'\n if db.backend_name == 'mysql':\n db.add_column(u'tnabot_userprofile', u'id',\n self.gf('django.db.models.fields.AutoField')(primary_key=True),\n keep_default=False)\n db.execute('ALTER TABLE `tnabot`.`tnabot_userprofile` CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT')\n elif db.backend_name == 'sqlite3':\n db.add_column(u'tnabot_userprofile', u'id',\n self.gf('django.db.models.fields.AutoField')(primary_key=True, default=0),\n keep_default=False)\n db.execute('UPDATE tnabot_userprofile SET id = user_id')\n db.create_primary_key(u'tnabot_userprofile', u'id')\n elif db.backend_name == 'postgres':\n db.start_transaction()\n db.add_column(u'tnabot_userprofile', u'id',\n self.gf('django.db.models.fields.IntegerField')(null=True),\n keep_default=False)\n db.execute('CREATE SEQUENCE tnabot_userprofile_id_seq')\n db.execute('SELECT setval(\\'tnabot_userprofile_id_seq\\', max(user_id) + 1) FROM tnabot_userprofile')\n db.commit_transaction()\n db.start_transaction()\n db.execute('UPDATE tnabot_userprofile SET id = user_id')\n db.commit_transaction()\n db.execute('ALTER TABLE tnabot_userprofile ALTER COLUMN id SET DEFAULT nextval(\\'tnabot_userprofile_id_seq\\')')\n db.create_primary_key(u'tnabot_userprofile', u'id')\n\n # Changing field 'UserProfile.user'\n db.alter_column(u'tnabot_userprofile', 'user_id', self.gf('django.db.models.fields.related.OneToOneField')(unique=True, to=orm['auth.User']))\n\n db.foreign_key_sql(u'tnabot_subscription', u'user_profile_id', u'tnabot_userprofile', u'id')\n db.foreign_key_sql(u'tnabot_userprofile', u'user_id', u'auth_user', u'id')\n\n def backwards(self, orm):\n raise RuntimeError(\"Cannot reverse this migration.\")\n\n### Make sure you are testing all the needed apps\n\nChange your jenkins configuration to specify which tests you want to be running. If you want to run the assetcloud tests\nalong with yours, you will need to specify it in the test command.\n\nYou will also need to change these in your fabfile.py\n\n### Upgrade Solr (if version < 3.6.2)\n\nYou will need to make sure that you are using solr version 3.6.2 for wildcard searches to work.\n\n cd path/to/get/solr\n wget http://archive.apache.org/dist/lucene/solr/3.6.2/apache-solr-3.6.2.tgz\n tar -xvf apache-solr-3.6.2.tgz\n\nIf you are on a development environment change ~/.fabricrc if you are on a dev environment\n\n solr_config=/home/gg/Apps/apache-solr-3.6.2/example\n\nOn your servers you will need to undeploy the previous solr and do the following as root\n\n cd apache-solr-3.6.2\n cp dist/apache-solr-3.6.2.war /var/lib/tomcat6/webapps/solr.war\n chown tomcat6:tomcat6 /var/lib/tomcat6/webapps/solr.war\n\nCopy the contents of example/solr to your new solr home (eg /var/lib/jenkins/assetcloud-solr)\n\n cp -r example/solr/* /var/lib/jenkins/assetcloud-solr\n \nThen in tomcat manager deploy the app using /solr context path and point to the solr war file.\n\nIf needed, update the solr home directory in /etc/default/tomcat6\n\n JAVA_OPTS=\"$JAVA_OPTS -Dsolr.solr.home=/var/lib/jenkins/assetcloud-solr\"\n\n### Remove ignoretests requirements and settings\n\nDjango 1.6 uses an inclusive test runner which means that you need to define which apps to run the tests on so you don't\nneed to have excluded apps.\n\nDelete\n\n TEST_RUNNER=\"ignoretests.DjangoIgnoreTestSuiteRunner\"\n\nand\n\n IGNORE_TESTS = (\n 'django.contrib.auth',\n 'django.contrib.messages',\n 'polymorphic'\n )\n\n### Account for \\xa0 characters in tests\n\nIn Django 1.6 filters add \\xa0 instead of ' ' in filters. If you have tests which check for that, make sure to update \nthem\n\n\nDatabase Migrations\n-------------------\n\nCheck out the South [documentation](http://south.aeracode.org/docs/) and [tutorial](http://south.aeracode.org/docs/tutorial/index.html)\n\nTo create a new migration after changing models.py:\n\n ./manage schemamigration assetcloud --auto\n\nTo apply new migrations:\n\n ./manage syncdb --migrate\n\nTo list all migrations (and see which have not yet been applied):\n\n ./manage migrate --list\n\n\nSolr Setup\n----------\n\nWe have two available search backends: Whoosh for development and Solr for production. Whoosh is sometimes useful for development, as it works out-of-the-box, but Solr is *much* faster, and supports more functionality.\n\n*Note:* at the moment some functionality (e.g. filtering searches by date range) doesn't work with Whoosh, so it's highly recommended that you use Solr.\n\nInstall Solr on Mac OS X, with the following:\n\n\tmkdir -p /Applications/Developer\n\tcd /Applications/Developer\n\tcurl -O http://archive.apache.org/dist/lucene/solr/3.6.2/apache-solr-3.6.2.tgz\n\ttar zxvf apache-solr-3.6.2.tgz\n\nThen change directory back to your assetcloud project directory.\n\nYou can now update your local settings, and start the Solr server:\n\n\techo \"HAYSTACK_SEARCH_ENGINE = 'solr'\" >> project/settings/local_common.py\n\techo \"HAYSTACK_SOLR_URL = 'http://127.0.0.1:8983/solr/main'\" >> project/settings/local_common.py\n\n\t. ./activate\n fab start_solr\n\nIf you are switching an existing Asset Cloud instance to Solr then you'll need to build the index:\n\n ./manage rebuild_index\n\nYou'll need Solr to be running whenever you use `./manage runserver` or `./manage test`. Your tests should run *much* quicker, and some search functionality will work in slightly more sensible ways.\n\nAlso note that you'll need to restart Solr if the [search indexes](https://github.com/brightinteractive/assetcloud/blob/master/apps/assetcloud/search_indexes.py) get updated.\n\nFor more details, including Solr on the test server, see [the wiki](http://wiki.bright-interactive.com/display/knowhow/Configuring+Asset+Cloud+to+use+the+Solr+Search+Engine).\n\nUsing S3 Storage\n----------------\n\nS3 storage is enabled by default by the following settings in\nproject/settings/common.py:\n\n # Custom assetcloud setting which controls the backend used for Asset Uploads\n ASSET_FILE_STORAGE = 'assetcloud.storage.S3BotoStorage'\n\n # Settings used by the 'storages' app for the 'S3BotoStorage' backend\n AWS_ACCESS_KEY_ID = ...\n AWS_SECRET_ACCESS_KEY = ...\n AWS_STORAGE_BUCKET_NAME = 'assetcloud-test'\n\nDirectly uploading to S3 and having to pull images from S3 everytime we want\nto generate thumbnails is potentially bad for performance. We may eventually use a composite storage backend, which would use an S3 storage backend for persistence, and a local file storage backend for performance.\n\nWe would use django-celery to periodically clean the local cache.\n\nPublishing\n----------\n\nAssetCloud is published on localshop.bright-interactive.com.\n\nFollow the [instructions](https://wiki.bright-interactive.com/display/knowhow/Bright+Interactive+Python+Package+Index+%28Localshop+on+Gold%29) on setting up a new user account on the localhsop.\n\nTo create a tag and publish to localshop, run:\n\n\tfab tag_and_publish:tag=v0.2.0\n\n(replacing v0.2.0 with the version number you wish to use for the tag - see [http://semver.org/] for rules about version numbers).\n\nCreating a tag will need a matching asset cloud package version in apps/assetcloud/__init__.py\n\nPublishing the current version can be done by running\n\n python setup.py publish\n\nContinuous Integration\n----------------------\n\n[Continuous Integration results](http://plumpton:8080/job/AssetCloud/) are built using Hudson, on plumpton.\n\nOne gotcha is that if you update the search indexes, you'll need to make sure you restart Solr (See above) after the first subsequent test run fails.\n\nGeneral Notes\n-------------\n\nUsing git from the command line is fine, but you'll probably also want GitHub's rather excellent [GitHub for Mac](http://mac.github.com/) tool.\n\nThis `README.markdown` file uses [markdown syntax](http://daringfireball.net/projects/markdown/syntax). There is a great markdown editor for Mac, [Mou](http://mouapp.com/), which you might find useful.\n\nFor development Asset Cloud uses a SQLite database, for ease of use. [Base](http://menial.co.uk/software/base/) is really nice sqlite database tool (again for Mac).\n\nIf you want to use PostgreSQL instead make sure that you use psycopg2 version 2.4.1 because version 2.4.2 is incompatible with Django 1.3. In deployment environments, to get dbbackup to work (and if you're not using ident authentication) then you need to create a .pgpass file in the bright user's home directory. This should contain the password for the database in question.\n\n\nDeveloping apps which use AssetCloud\n====================================\n\n\nChoosing a version for AssetCloud development\n---------------------------------------------\n\nSince version 1.0.0 we started using a Semantic Versioning scheme with pre-release extensions.\n\nhttp://semver.org/spec/v2.0.0.html\n\nBackwards incompatible changes should bump the major version\nBackwards compatible changes should bump the minor version\nFixes should bump the patch version unless they introduce backwards incompatibilies, in which case they should bump the major version\nDevelopment should be done using the pre-release extensions in a new version (backwards compatible or not)\n\n\nAssetCloud public API\n---------------------\n\nWe don't have a well-defined API so we consider the API to basically be \"any part of the app which was used in an\nexternal app\" and \"things which require changes in dependant apps\"\n\nThese are likely to be backwards incompatible changes:\n(Update this list when you come across something which applies here)\n\n 1. Defining new settings with no default values.\n 2. Changing a contract test\n\nNote that solely relying on this list is very optimistic. If a change is obviously backwards incompatible it should be\ntreated as such.\n\nClaiming parts of the app as API\n--------------------------------\n\nAs mentioned above, there is no strict definition of a public API for assetcloud, so to prevent your app from breaking\nwith assetcloud updates we have introduced contract tests.\n\nThese are tests which should be considered as vital for the app which is claiming them, meaning that any change to these\ntests should be considered unsafe and should be done with caution. Failures in these tests probably also mean that the\nclaiming app will break.\n\nThere are two ways to define a contract test:\n\n 1. Add some test suites in assetcloud/tests/contract/ making the name of the dependant app clear.\n 2. Decorate any existing test with the ContractTest decorator defining the dependant app name in the app parameter. Note\n that you should decorate a test even if has already been decorated by another application, by adding another decorator.\n\n | @ContractTest(app=\"tnabot\")\n\nThis should act as a guarantee that your app will not be breaking without warning because of an assetcloud version update.\n\nWriting contract tests\n----------------------\n\nThe general recommendation is writing a test for every part of assetcloud you are using in the dependant app. This can be\nuse of models, utility functions, overriding templates and views, imports etc.\n\nIf there are no tests in assetcloud to preserve the functionality you are using, either create one in the general assetcloud\ntest folders and decorate it as a ContractTest or create one in assetcloud's contract test folder.\n\nRemember that the more tests you write, the more guaranteed you are to have the used functionality preserved with assetcloud\nupdates.\n\nThere is a helper ContractTestCase with some useful asserts to make this process easier.\n\nFailing contract tests\n----------------------\n\nIf a test within /assetcloud/tests/contracts or a ContractTest fails during development, then proceed with caution. Changing\nthe test to fix the failure could cause Bad Things to the dependant app. It should be obvious which app depends on the\ntest so you should be able to see how this test will affect it. If in doubt, ask one of the developers of the dependent\napp.\n\nNonetheless, if there need to be changes to any one of these tests, then the change should be considered backwards\nincompatible and the version change should represent that with a major version iteration. The change should be documented\nfor the developers who will be updating the dependant app.\n\n\nPublishing Releases to Localshop\n================================\n\nFirst make sure you have created a user and set up access to http://localshop.bright-interactive.com by following the instructions in https://wiki.bright-interactive.com/display/knowhow/Bright+Interactive+Python+Package+Index+(Localshop+on+Gold).\n\nSet the `__version__` string in `apps/assetcloud/__init__.py`, commit this change, push it and then run:\n\n # Run the tests - do not publish if the tests fail or you haven't/can't run them\n ./manage test apps assetcloud_example\n # Publish to localshop\n ./setup.py publish\n # Tag (change 1.0.0 to the version you are publishing!)\n\tgit tag -a v1.0.0 -m 'Version 1.0.0'\n\tgit push --tags\n\n\tor\n\n\tfab tag_and_publish:v1.0.0\n", "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/brightinteractive/assetcloud/", "keywords": null, "license": "BSD", "maintainer": null, "maintainer_email": null, "name": "assetcloud", "package_url": "https://pypi.org/project/assetcloud/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/assetcloud/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/brightinteractive/assetcloud/" }, "release_url": "https://pypi.org/project/assetcloud/2.3.1/", "requires_dist": null, "requires_python": null, "summary": "Lightweight Digital Asset Management", "version": "2.3.1" }, "last_serial": 1538661, "releases": { "2.3.0": [ { "comment_text": "", "digests": { "md5": "fdaaf37542ba761b6e0022237fdf44e2", "sha256": "336d66607bee587a4eb34045187261ca8e5b39e4fabd1331987702256a0bbc47" }, "downloads": -1, "filename": "assetcloud-2.3.0.tar.gz", "has_sig": false, "md5_digest": "fdaaf37542ba761b6e0022237fdf44e2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1269058, "upload_time": "2015-05-07T15:26:15", "url": "https://files.pythonhosted.org/packages/2f/53/007cea96a1369bec97470460cc8a37bc24deefdb58cd3f2a68e7c25061d7/assetcloud-2.3.0.tar.gz" } ], "2.3.1": [ { "comment_text": "", "digests": { "md5": "b37cef82787581202700aff8b0b0e287", "sha256": "13b13acc0dcce9e8b3c5f90bd0c23c3346f6f5e0bf7583e8f8c557818aa0a29e" }, "downloads": -1, "filename": "assetcloud-2.3.1.tar.gz", "has_sig": false, "md5_digest": "b37cef82787581202700aff8b0b0e287", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1269076, "upload_time": "2015-05-08T10:13:56", "url": "https://files.pythonhosted.org/packages/60/3a/cc3727e6a2abadd3b419f96352cdbf296e518500ceacf0dc1b5640675dee/assetcloud-2.3.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b37cef82787581202700aff8b0b0e287", "sha256": "13b13acc0dcce9e8b3c5f90bd0c23c3346f6f5e0bf7583e8f8c557818aa0a29e" }, "downloads": -1, "filename": "assetcloud-2.3.1.tar.gz", "has_sig": false, "md5_digest": "b37cef82787581202700aff8b0b0e287", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1269076, "upload_time": "2015-05-08T10:13:56", "url": "https://files.pythonhosted.org/packages/60/3a/cc3727e6a2abadd3b419f96352cdbf296e518500ceacf0dc1b5640675dee/assetcloud-2.3.1.tar.gz" } ] }