gcloud 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (768) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +4 -0
  3. data/Makefile +4 -0
  4. data/Manifest +760 -1
  5. data/bin/gcloud +7 -0
  6. data/bin/{gcutil → gcutil.symlink} +0 -0
  7. data/bin/gsutil-symlink +377 -0
  8. data/gcloud.gemspec +5 -5
  9. data/packages/gsutil/CHECKSUM +1 -0
  10. data/packages/gsutil/COPYING +202 -0
  11. data/packages/gsutil/LICENSE.third_party +295 -0
  12. data/packages/gsutil/MANIFEST.in +5 -0
  13. data/packages/gsutil/README +38 -0
  14. data/packages/gsutil/README.pkg +49 -0
  15. data/packages/gsutil/ReleaseNotes.txt +780 -0
  16. data/packages/gsutil/VERSION +1 -0
  17. data/packages/gsutil/boto/Changelog.rst +35 -0
  18. data/packages/gsutil/boto/LICENSE +18 -0
  19. data/packages/gsutil/boto/MANIFEST.in +12 -0
  20. data/packages/gsutil/boto/README.rst +163 -0
  21. data/packages/gsutil/boto/bin/asadmin +290 -0
  22. data/packages/gsutil/boto/bin/bundle_image +27 -0
  23. data/packages/gsutil/boto/bin/cfadmin +108 -0
  24. data/packages/gsutil/boto/bin/cq +89 -0
  25. data/packages/gsutil/boto/bin/cwutil +140 -0
  26. data/packages/gsutil/boto/bin/elbadmin +284 -0
  27. data/packages/gsutil/boto/bin/fetch_file +43 -0
  28. data/packages/gsutil/boto/bin/glacier +154 -0
  29. data/packages/gsutil/boto/bin/instance_events +145 -0
  30. data/packages/gsutil/boto/bin/kill_instance +35 -0
  31. data/packages/gsutil/boto/bin/launch_instance +252 -0
  32. data/packages/gsutil/boto/bin/list_instances +90 -0
  33. data/packages/gsutil/boto/bin/lss3 +77 -0
  34. data/packages/gsutil/boto/bin/mturk +465 -0
  35. data/packages/gsutil/boto/bin/pyami_sendmail +52 -0
  36. data/packages/gsutil/boto/bin/route53 +205 -0
  37. data/packages/gsutil/boto/bin/s3put +374 -0
  38. data/packages/gsutil/boto/bin/sdbadmin +194 -0
  39. data/packages/gsutil/boto/bin/taskadmin +116 -0
  40. data/packages/gsutil/boto/boto/__init__.py +793 -0
  41. data/packages/gsutil/boto/boto/__init__.pyc +0 -0
  42. data/packages/gsutil/boto/boto/auth.py +682 -0
  43. data/packages/gsutil/boto/boto/auth.pyc +0 -0
  44. data/packages/gsutil/boto/boto/auth_handler.py +58 -0
  45. data/packages/gsutil/boto/boto/auth_handler.pyc +0 -0
  46. data/packages/gsutil/boto/boto/beanstalk/__init__.py +65 -0
  47. data/packages/gsutil/boto/boto/beanstalk/exception.py +64 -0
  48. data/packages/gsutil/boto/boto/beanstalk/layer1.py +1153 -0
  49. data/packages/gsutil/boto/boto/beanstalk/response.py +703 -0
  50. data/packages/gsutil/boto/boto/beanstalk/wrapper.py +29 -0
  51. data/packages/gsutil/boto/boto/cacerts/__init__.py +22 -0
  52. data/packages/gsutil/boto/boto/cacerts/__init__.pyc +0 -0
  53. data/packages/gsutil/boto/boto/cacerts/cacerts.txt +633 -0
  54. data/packages/gsutil/boto/boto/cloudformation/__init__.py +68 -0
  55. data/packages/gsutil/boto/boto/cloudformation/connection.py +364 -0
  56. data/packages/gsutil/boto/boto/cloudformation/stack.py +360 -0
  57. data/packages/gsutil/boto/boto/cloudformation/template.py +43 -0
  58. data/packages/gsutil/boto/boto/cloudfront/__init__.py +324 -0
  59. data/packages/gsutil/boto/boto/cloudfront/distribution.py +745 -0
  60. data/packages/gsutil/boto/boto/cloudfront/exception.py +26 -0
  61. data/packages/gsutil/boto/boto/cloudfront/identity.py +122 -0
  62. data/packages/gsutil/boto/boto/cloudfront/invalidation.py +216 -0
  63. data/packages/gsutil/boto/boto/cloudfront/logging.py +38 -0
  64. data/packages/gsutil/boto/boto/cloudfront/object.py +48 -0
  65. data/packages/gsutil/boto/boto/cloudfront/origin.py +150 -0
  66. data/packages/gsutil/boto/boto/cloudfront/signers.py +60 -0
  67. data/packages/gsutil/boto/boto/cloudsearch/__init__.py +45 -0
  68. data/packages/gsutil/boto/boto/cloudsearch/document.py +265 -0
  69. data/packages/gsutil/boto/boto/cloudsearch/domain.py +394 -0
  70. data/packages/gsutil/boto/boto/cloudsearch/layer1.py +738 -0
  71. data/packages/gsutil/boto/boto/cloudsearch/layer2.py +67 -0
  72. data/packages/gsutil/boto/boto/cloudsearch/optionstatus.py +248 -0
  73. data/packages/gsutil/boto/boto/cloudsearch/search.py +365 -0
  74. data/packages/gsutil/boto/boto/cloudsearch/sourceattribute.py +75 -0
  75. data/packages/gsutil/boto/boto/compat.py +28 -0
  76. data/packages/gsutil/boto/boto/compat.pyc +0 -0
  77. data/packages/gsutil/boto/boto/connection.py +1081 -0
  78. data/packages/gsutil/boto/boto/connection.pyc +0 -0
  79. data/packages/gsutil/boto/boto/contrib/__init__.py +22 -0
  80. data/packages/gsutil/boto/boto/contrib/ymlmessage.py +52 -0
  81. data/packages/gsutil/boto/boto/core/README +58 -0
  82. data/packages/gsutil/boto/boto/core/__init__.py +23 -0
  83. data/packages/gsutil/boto/boto/core/auth.py +78 -0
  84. data/packages/gsutil/boto/boto/core/credentials.py +154 -0
  85. data/packages/gsutil/boto/boto/core/dictresponse.py +178 -0
  86. data/packages/gsutil/boto/boto/core/service.py +67 -0
  87. data/packages/gsutil/boto/boto/datapipeline/__init__.py +0 -0
  88. data/packages/gsutil/boto/boto/datapipeline/exceptions.py +42 -0
  89. data/packages/gsutil/boto/boto/datapipeline/layer1.py +546 -0
  90. data/packages/gsutil/boto/boto/dynamodb/__init__.py +66 -0
  91. data/packages/gsutil/boto/boto/dynamodb/batch.py +262 -0
  92. data/packages/gsutil/boto/boto/dynamodb/condition.py +170 -0
  93. data/packages/gsutil/boto/boto/dynamodb/exceptions.py +64 -0
  94. data/packages/gsutil/boto/boto/dynamodb/item.py +196 -0
  95. data/packages/gsutil/boto/boto/dynamodb/layer1.py +575 -0
  96. data/packages/gsutil/boto/boto/dynamodb/layer2.py +798 -0
  97. data/packages/gsutil/boto/boto/dynamodb/schema.py +112 -0
  98. data/packages/gsutil/boto/boto/dynamodb/table.py +540 -0
  99. data/packages/gsutil/boto/boto/dynamodb/types.py +326 -0
  100. data/packages/gsutil/boto/boto/ec2/__init__.py +96 -0
  101. data/packages/gsutil/boto/boto/ec2/address.py +103 -0
  102. data/packages/gsutil/boto/boto/ec2/autoscale/__init__.py +781 -0
  103. data/packages/gsutil/boto/boto/ec2/autoscale/activity.py +74 -0
  104. data/packages/gsutil/boto/boto/ec2/autoscale/group.py +337 -0
  105. data/packages/gsutil/boto/boto/ec2/autoscale/instance.py +60 -0
  106. data/packages/gsutil/boto/boto/ec2/autoscale/launchconfig.py +209 -0
  107. data/packages/gsutil/boto/boto/ec2/autoscale/policy.py +166 -0
  108. data/packages/gsutil/boto/boto/ec2/autoscale/request.py +38 -0
  109. data/packages/gsutil/boto/boto/ec2/autoscale/scheduled.py +60 -0
  110. data/packages/gsutil/boto/boto/ec2/autoscale/tag.py +84 -0
  111. data/packages/gsutil/boto/boto/ec2/blockdevicemapping.py +141 -0
  112. data/packages/gsutil/boto/boto/ec2/bundleinstance.py +78 -0
  113. data/packages/gsutil/boto/boto/ec2/buyreservation.py +84 -0
  114. data/packages/gsutil/boto/boto/ec2/cloudwatch/__init__.py +603 -0
  115. data/packages/gsutil/boto/boto/ec2/cloudwatch/alarm.py +316 -0
  116. data/packages/gsutil/boto/boto/ec2/cloudwatch/datapoint.py +40 -0
  117. data/packages/gsutil/boto/boto/ec2/cloudwatch/dimension.py +38 -0
  118. data/packages/gsutil/boto/boto/ec2/cloudwatch/listelement.py +31 -0
  119. data/packages/gsutil/boto/boto/ec2/cloudwatch/metric.py +175 -0
  120. data/packages/gsutil/boto/boto/ec2/connection.py +3409 -0
  121. data/packages/gsutil/boto/boto/ec2/ec2object.py +107 -0
  122. data/packages/gsutil/boto/boto/ec2/elb/__init__.py +553 -0
  123. data/packages/gsutil/boto/boto/ec2/elb/healthcheck.py +89 -0
  124. data/packages/gsutil/boto/boto/ec2/elb/instancestate.py +62 -0
  125. data/packages/gsutil/boto/boto/ec2/elb/listelement.py +36 -0
  126. data/packages/gsutil/boto/boto/ec2/elb/listener.py +75 -0
  127. data/packages/gsutil/boto/boto/ec2/elb/loadbalancer.py +324 -0
  128. data/packages/gsutil/boto/boto/ec2/elb/policies.py +89 -0
  129. data/packages/gsutil/boto/boto/ec2/elb/securitygroup.py +38 -0
  130. data/packages/gsutil/boto/boto/ec2/group.py +39 -0
  131. data/packages/gsutil/boto/boto/ec2/image.py +350 -0
  132. data/packages/gsutil/boto/boto/ec2/instance.py +661 -0
  133. data/packages/gsutil/boto/boto/ec2/instanceinfo.py +51 -0
  134. data/packages/gsutil/boto/boto/ec2/instancestatus.py +207 -0
  135. data/packages/gsutil/boto/boto/ec2/keypair.py +113 -0
  136. data/packages/gsutil/boto/boto/ec2/launchspecification.py +105 -0
  137. data/packages/gsutil/boto/boto/ec2/networkinterface.py +247 -0
  138. data/packages/gsutil/boto/boto/ec2/placementgroup.py +51 -0
  139. data/packages/gsutil/boto/boto/ec2/regioninfo.py +34 -0
  140. data/packages/gsutil/boto/boto/ec2/reservedinstance.py +227 -0
  141. data/packages/gsutil/boto/boto/ec2/securitygroup.py +357 -0
  142. data/packages/gsutil/boto/boto/ec2/snapshot.py +170 -0
  143. data/packages/gsutil/boto/boto/ec2/spotdatafeedsubscription.py +63 -0
  144. data/packages/gsutil/boto/boto/ec2/spotinstancerequest.py +188 -0
  145. data/packages/gsutil/boto/boto/ec2/spotpricehistory.py +55 -0
  146. data/packages/gsutil/boto/boto/ec2/tag.py +87 -0
  147. data/packages/gsutil/boto/boto/ec2/vmtype.py +58 -0
  148. data/packages/gsutil/boto/boto/ec2/volume.py +293 -0
  149. data/packages/gsutil/boto/boto/ec2/volumestatus.py +200 -0
  150. data/packages/gsutil/boto/boto/ec2/zone.py +80 -0
  151. data/packages/gsutil/boto/boto/ecs/__init__.py +90 -0
  152. data/packages/gsutil/boto/boto/ecs/item.py +153 -0
  153. data/packages/gsutil/boto/boto/elasticache/__init__.py +62 -0
  154. data/packages/gsutil/boto/boto/elasticache/layer1.py +1252 -0
  155. data/packages/gsutil/boto/boto/elastictranscoder/__init__.py +62 -0
  156. data/packages/gsutil/boto/boto/elastictranscoder/exceptions.py +46 -0
  157. data/packages/gsutil/boto/boto/elastictranscoder/layer1.py +509 -0
  158. data/packages/gsutil/boto/boto/emr/__init__.py +73 -0
  159. data/packages/gsutil/boto/boto/emr/bootstrap_action.py +44 -0
  160. data/packages/gsutil/boto/boto/emr/connection.py +531 -0
  161. data/packages/gsutil/boto/boto/emr/emrobject.py +176 -0
  162. data/packages/gsutil/boto/boto/emr/instance_group.py +43 -0
  163. data/packages/gsutil/boto/boto/emr/step.py +281 -0
  164. data/packages/gsutil/boto/boto/exception.py +476 -0
  165. data/packages/gsutil/boto/boto/exception.pyc +0 -0
  166. data/packages/gsutil/boto/boto/file/README +49 -0
  167. data/packages/gsutil/boto/boto/file/__init__.py +28 -0
  168. data/packages/gsutil/boto/boto/file/bucket.py +112 -0
  169. data/packages/gsutil/boto/boto/file/connection.py +33 -0
  170. data/packages/gsutil/boto/boto/file/key.py +199 -0
  171. data/packages/gsutil/boto/boto/file/simpleresultset.py +30 -0
  172. data/packages/gsutil/boto/boto/fps/__init__.py +21 -0
  173. data/packages/gsutil/boto/boto/fps/connection.py +369 -0
  174. data/packages/gsutil/boto/boto/fps/exception.py +344 -0
  175. data/packages/gsutil/boto/boto/fps/response.py +175 -0
  176. data/packages/gsutil/boto/boto/glacier/__init__.py +57 -0
  177. data/packages/gsutil/boto/boto/glacier/concurrent.py +409 -0
  178. data/packages/gsutil/boto/boto/glacier/exceptions.py +58 -0
  179. data/packages/gsutil/boto/boto/glacier/job.py +152 -0
  180. data/packages/gsutil/boto/boto/glacier/layer1.py +637 -0
  181. data/packages/gsutil/boto/boto/glacier/layer2.py +93 -0
  182. data/packages/gsutil/boto/boto/glacier/response.py +48 -0
  183. data/packages/gsutil/boto/boto/glacier/utils.py +163 -0
  184. data/packages/gsutil/boto/boto/glacier/vault.py +387 -0
  185. data/packages/gsutil/boto/boto/glacier/writer.py +242 -0
  186. data/packages/gsutil/boto/boto/gs/__init__.py +22 -0
  187. data/packages/gsutil/boto/boto/gs/__init__.pyc +0 -0
  188. data/packages/gsutil/boto/boto/gs/acl.py +304 -0
  189. data/packages/gsutil/boto/boto/gs/acl.pyc +0 -0
  190. data/packages/gsutil/boto/boto/gs/bucket.py +870 -0
  191. data/packages/gsutil/boto/boto/gs/bucket.pyc +0 -0
  192. data/packages/gsutil/boto/boto/gs/bucketlistresultset.py +64 -0
  193. data/packages/gsutil/boto/boto/gs/bucketlistresultset.pyc +0 -0
  194. data/packages/gsutil/boto/boto/gs/connection.py +103 -0
  195. data/packages/gsutil/boto/boto/gs/connection.pyc +0 -0
  196. data/packages/gsutil/boto/boto/gs/cors.py +169 -0
  197. data/packages/gsutil/boto/boto/gs/cors.pyc +0 -0
  198. data/packages/gsutil/boto/boto/gs/key.py +704 -0
  199. data/packages/gsutil/boto/boto/gs/key.pyc +0 -0
  200. data/packages/gsutil/boto/boto/gs/resumable_upload_handler.py +659 -0
  201. data/packages/gsutil/boto/boto/gs/resumable_upload_handler.pyc +0 -0
  202. data/packages/gsutil/boto/boto/gs/user.py +54 -0
  203. data/packages/gsutil/boto/boto/gs/user.pyc +0 -0
  204. data/packages/gsutil/boto/boto/handler.py +44 -0
  205. data/packages/gsutil/boto/boto/handler.pyc +0 -0
  206. data/packages/gsutil/boto/boto/https_connection.py +124 -0
  207. data/packages/gsutil/boto/boto/https_connection.pyc +0 -0
  208. data/packages/gsutil/boto/boto/iam/__init__.py +74 -0
  209. data/packages/gsutil/boto/boto/iam/connection.py +1317 -0
  210. data/packages/gsutil/boto/boto/iam/summarymap.py +42 -0
  211. data/packages/gsutil/boto/boto/jsonresponse.py +163 -0
  212. data/packages/gsutil/boto/boto/jsonresponse.pyc +0 -0
  213. data/packages/gsutil/boto/boto/manage/__init__.py +23 -0
  214. data/packages/gsutil/boto/boto/manage/cmdshell.py +241 -0
  215. data/packages/gsutil/boto/boto/manage/propget.py +64 -0
  216. data/packages/gsutil/boto/boto/manage/server.py +556 -0
  217. data/packages/gsutil/boto/boto/manage/task.py +175 -0
  218. data/packages/gsutil/boto/boto/manage/test_manage.py +34 -0
  219. data/packages/gsutil/boto/boto/manage/volume.py +420 -0
  220. data/packages/gsutil/boto/boto/mashups/__init__.py +23 -0
  221. data/packages/gsutil/boto/boto/mashups/interactive.py +97 -0
  222. data/packages/gsutil/boto/boto/mashups/iobject.py +115 -0
  223. data/packages/gsutil/boto/boto/mashups/order.py +211 -0
  224. data/packages/gsutil/boto/boto/mashups/server.py +395 -0
  225. data/packages/gsutil/boto/boto/mturk/__init__.py +23 -0
  226. data/packages/gsutil/boto/boto/mturk/connection.py +1027 -0
  227. data/packages/gsutil/boto/boto/mturk/layoutparam.py +55 -0
  228. data/packages/gsutil/boto/boto/mturk/notification.py +103 -0
  229. data/packages/gsutil/boto/boto/mturk/price.py +48 -0
  230. data/packages/gsutil/boto/boto/mturk/qualification.py +137 -0
  231. data/packages/gsutil/boto/boto/mturk/question.py +455 -0
  232. data/packages/gsutil/boto/boto/mws/__init__.py +21 -0
  233. data/packages/gsutil/boto/boto/mws/connection.py +813 -0
  234. data/packages/gsutil/boto/boto/mws/exception.py +75 -0
  235. data/packages/gsutil/boto/boto/mws/response.py +655 -0
  236. data/packages/gsutil/boto/boto/plugin.py +90 -0
  237. data/packages/gsutil/boto/boto/plugin.pyc +0 -0
  238. data/packages/gsutil/boto/boto/provider.py +337 -0
  239. data/packages/gsutil/boto/boto/provider.pyc +0 -0
  240. data/packages/gsutil/boto/boto/pyami/__init__.py +22 -0
  241. data/packages/gsutil/boto/boto/pyami/__init__.pyc +0 -0
  242. data/packages/gsutil/boto/boto/pyami/bootstrap.py +134 -0
  243. data/packages/gsutil/boto/boto/pyami/config.py +229 -0
  244. data/packages/gsutil/boto/boto/pyami/config.pyc +0 -0
  245. data/packages/gsutil/boto/boto/pyami/copybot.cfg +60 -0
  246. data/packages/gsutil/boto/boto/pyami/copybot.py +97 -0
  247. data/packages/gsutil/boto/boto/pyami/helloworld.py +28 -0
  248. data/packages/gsutil/boto/boto/pyami/installers/__init__.py +64 -0
  249. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/__init__.py +22 -0
  250. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/apache.py +43 -0
  251. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/ebs.py +238 -0
  252. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/installer.py +96 -0
  253. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/mysql.py +109 -0
  254. data/packages/gsutil/boto/boto/pyami/installers/ubuntu/trac.py +139 -0
  255. data/packages/gsutil/boto/boto/pyami/launch_ami.py +178 -0
  256. data/packages/gsutil/boto/boto/pyami/scriptbase.py +44 -0
  257. data/packages/gsutil/boto/boto/pyami/startup.py +60 -0
  258. data/packages/gsutil/boto/boto/rds/__init__.py +1194 -0
  259. data/packages/gsutil/boto/boto/rds/dbinstance.py +357 -0
  260. data/packages/gsutil/boto/boto/rds/dbsecuritygroup.py +177 -0
  261. data/packages/gsutil/boto/boto/rds/dbsnapshot.py +108 -0
  262. data/packages/gsutil/boto/boto/rds/event.py +49 -0
  263. data/packages/gsutil/boto/boto/rds/parametergroup.py +201 -0
  264. data/packages/gsutil/boto/boto/rds/regioninfo.py +32 -0
  265. data/packages/gsutil/boto/boto/regioninfo.py +63 -0
  266. data/packages/gsutil/boto/boto/regioninfo.pyc +0 -0
  267. data/packages/gsutil/boto/boto/resultset.py +169 -0
  268. data/packages/gsutil/boto/boto/resultset.pyc +0 -0
  269. data/packages/gsutil/boto/boto/roboto/__init__.py +1 -0
  270. data/packages/gsutil/boto/boto/roboto/awsqueryrequest.py +504 -0
  271. data/packages/gsutil/boto/boto/roboto/awsqueryservice.py +121 -0
  272. data/packages/gsutil/boto/boto/roboto/param.py +147 -0
  273. data/packages/gsutil/boto/boto/route53/__init__.py +75 -0
  274. data/packages/gsutil/boto/boto/route53/connection.py +403 -0
  275. data/packages/gsutil/boto/boto/route53/exception.py +27 -0
  276. data/packages/gsutil/boto/boto/route53/hostedzone.py +56 -0
  277. data/packages/gsutil/boto/boto/route53/record.py +306 -0
  278. data/packages/gsutil/boto/boto/route53/status.py +42 -0
  279. data/packages/gsutil/boto/boto/route53/zone.py +412 -0
  280. data/packages/gsutil/boto/boto/s3/__init__.py +84 -0
  281. data/packages/gsutil/boto/boto/s3/__init__.pyc +0 -0
  282. data/packages/gsutil/boto/boto/s3/acl.py +164 -0
  283. data/packages/gsutil/boto/boto/s3/acl.pyc +0 -0
  284. data/packages/gsutil/boto/boto/s3/bucket.py +1634 -0
  285. data/packages/gsutil/boto/boto/s3/bucket.pyc +0 -0
  286. data/packages/gsutil/boto/boto/s3/bucketlistresultset.py +139 -0
  287. data/packages/gsutil/boto/boto/s3/bucketlistresultset.pyc +0 -0
  288. data/packages/gsutil/boto/boto/s3/bucketlogging.py +83 -0
  289. data/packages/gsutil/boto/boto/s3/bucketlogging.pyc +0 -0
  290. data/packages/gsutil/boto/boto/s3/connection.py +540 -0
  291. data/packages/gsutil/boto/boto/s3/connection.pyc +0 -0
  292. data/packages/gsutil/boto/boto/s3/cors.py +210 -0
  293. data/packages/gsutil/boto/boto/s3/cors.pyc +0 -0
  294. data/packages/gsutil/boto/boto/s3/deletemarker.py +55 -0
  295. data/packages/gsutil/boto/boto/s3/deletemarker.pyc +0 -0
  296. data/packages/gsutil/boto/boto/s3/key.py +1712 -0
  297. data/packages/gsutil/boto/boto/s3/key.pyc +0 -0
  298. data/packages/gsutil/boto/boto/s3/keyfile.py +134 -0
  299. data/packages/gsutil/boto/boto/s3/keyfile.pyc +0 -0
  300. data/packages/gsutil/boto/boto/s3/lifecycle.py +231 -0
  301. data/packages/gsutil/boto/boto/s3/lifecycle.pyc +0 -0
  302. data/packages/gsutil/boto/boto/s3/multidelete.py +138 -0
  303. data/packages/gsutil/boto/boto/s3/multidelete.pyc +0 -0
  304. data/packages/gsutil/boto/boto/s3/multipart.py +315 -0
  305. data/packages/gsutil/boto/boto/s3/multipart.pyc +0 -0
  306. data/packages/gsutil/boto/boto/s3/prefix.py +42 -0
  307. data/packages/gsutil/boto/boto/s3/prefix.pyc +0 -0
  308. data/packages/gsutil/boto/boto/s3/resumable_download_handler.py +339 -0
  309. data/packages/gsutil/boto/boto/s3/resumable_download_handler.pyc +0 -0
  310. data/packages/gsutil/boto/boto/s3/tagging.py +71 -0
  311. data/packages/gsutil/boto/boto/s3/tagging.pyc +0 -0
  312. data/packages/gsutil/boto/boto/s3/user.py +49 -0
  313. data/packages/gsutil/boto/boto/s3/user.pyc +0 -0
  314. data/packages/gsutil/boto/boto/s3/website.py +237 -0
  315. data/packages/gsutil/boto/boto/s3/website.pyc +0 -0
  316. data/packages/gsutil/boto/boto/sdb/__init__.py +67 -0
  317. data/packages/gsutil/boto/boto/sdb/connection.py +617 -0
  318. data/packages/gsutil/boto/boto/sdb/db/__init__.py +20 -0
  319. data/packages/gsutil/boto/boto/sdb/db/blob.py +75 -0
  320. data/packages/gsutil/boto/boto/sdb/db/key.py +59 -0
  321. data/packages/gsutil/boto/boto/sdb/db/manager/__init__.py +85 -0
  322. data/packages/gsutil/boto/boto/sdb/db/manager/sdbmanager.py +732 -0
  323. data/packages/gsutil/boto/boto/sdb/db/manager/xmlmanager.py +517 -0
  324. data/packages/gsutil/boto/boto/sdb/db/model.py +294 -0
  325. data/packages/gsutil/boto/boto/sdb/db/property.py +703 -0
  326. data/packages/gsutil/boto/boto/sdb/db/query.py +85 -0
  327. data/packages/gsutil/boto/boto/sdb/db/sequence.py +226 -0
  328. data/packages/gsutil/boto/boto/sdb/db/test_db.py +231 -0
  329. data/packages/gsutil/boto/boto/sdb/domain.py +377 -0
  330. data/packages/gsutil/boto/boto/sdb/item.py +181 -0
  331. data/packages/gsutil/boto/boto/sdb/queryresultset.py +92 -0
  332. data/packages/gsutil/boto/boto/sdb/regioninfo.py +32 -0
  333. data/packages/gsutil/boto/boto/services/__init__.py +23 -0
  334. data/packages/gsutil/boto/boto/services/bs.py +179 -0
  335. data/packages/gsutil/boto/boto/services/message.py +58 -0
  336. data/packages/gsutil/boto/boto/services/result.py +136 -0
  337. data/packages/gsutil/boto/boto/services/service.py +161 -0
  338. data/packages/gsutil/boto/boto/services/servicedef.py +91 -0
  339. data/packages/gsutil/boto/boto/services/sonofmmm.cfg +43 -0
  340. data/packages/gsutil/boto/boto/services/sonofmmm.py +81 -0
  341. data/packages/gsutil/boto/boto/services/submit.py +88 -0
  342. data/packages/gsutil/boto/boto/ses/__init__.py +54 -0
  343. data/packages/gsutil/boto/boto/ses/connection.py +521 -0
  344. data/packages/gsutil/boto/boto/ses/exceptions.py +77 -0
  345. data/packages/gsutil/boto/boto/sns/__init__.py +78 -0
  346. data/packages/gsutil/boto/boto/sns/connection.py +431 -0
  347. data/packages/gsutil/boto/boto/sqs/__init__.py +56 -0
  348. data/packages/gsutil/boto/boto/sqs/attributes.py +46 -0
  349. data/packages/gsutil/boto/boto/sqs/batchresults.py +95 -0
  350. data/packages/gsutil/boto/boto/sqs/connection.py +417 -0
  351. data/packages/gsutil/boto/boto/sqs/jsonmessage.py +43 -0
  352. data/packages/gsutil/boto/boto/sqs/message.py +253 -0
  353. data/packages/gsutil/boto/boto/sqs/queue.py +478 -0
  354. data/packages/gsutil/boto/boto/sqs/regioninfo.py +32 -0
  355. data/packages/gsutil/boto/boto/storage_uri.py +835 -0
  356. data/packages/gsutil/boto/boto/storage_uri.pyc +0 -0
  357. data/packages/gsutil/boto/boto/sts/__init__.py +55 -0
  358. data/packages/gsutil/boto/boto/sts/connection.py +207 -0
  359. data/packages/gsutil/boto/boto/sts/credentials.py +215 -0
  360. data/packages/gsutil/boto/boto/swf/__init__.py +60 -0
  361. data/packages/gsutil/boto/boto/swf/exceptions.py +44 -0
  362. data/packages/gsutil/boto/boto/swf/layer1.py +1512 -0
  363. data/packages/gsutil/boto/boto/swf/layer1_decisions.py +287 -0
  364. data/packages/gsutil/boto/boto/swf/layer2.py +342 -0
  365. data/packages/gsutil/boto/boto/utils.py +927 -0
  366. data/packages/gsutil/boto/boto/utils.pyc +0 -0
  367. data/packages/gsutil/boto/boto/vpc/__init__.py +910 -0
  368. data/packages/gsutil/boto/boto/vpc/customergateway.py +54 -0
  369. data/packages/gsutil/boto/boto/vpc/dhcpoptions.py +72 -0
  370. data/packages/gsutil/boto/boto/vpc/internetgateway.py +72 -0
  371. data/packages/gsutil/boto/boto/vpc/routetable.py +109 -0
  372. data/packages/gsutil/boto/boto/vpc/subnet.py +57 -0
  373. data/packages/gsutil/boto/boto/vpc/vpc.py +54 -0
  374. data/packages/gsutil/boto/boto/vpc/vpnconnection.py +60 -0
  375. data/packages/gsutil/boto/boto/vpc/vpngateway.py +83 -0
  376. data/packages/gsutil/boto/docs/BotoCheatSheet.pdf +0 -0
  377. data/packages/gsutil/boto/docs/Makefile +89 -0
  378. data/packages/gsutil/boto/docs/make.bat +113 -0
  379. data/packages/gsutil/boto/docs/source/_templates/layout.html +3 -0
  380. data/packages/gsutil/boto/docs/source/autoscale_tut.rst +220 -0
  381. data/packages/gsutil/boto/docs/source/boto_config_tut.rst +125 -0
  382. data/packages/gsutil/boto/docs/source/boto_theme/static/boto.css_t +239 -0
  383. data/packages/gsutil/boto/docs/source/boto_theme/static/pygments.css +61 -0
  384. data/packages/gsutil/boto/docs/source/boto_theme/theme.conf +3 -0
  385. data/packages/gsutil/boto/docs/source/cloudfront_tut.rst +196 -0
  386. data/packages/gsutil/boto/docs/source/cloudsearch_tut.rst +411 -0
  387. data/packages/gsutil/boto/docs/source/cloudwatch_tut.rst +116 -0
  388. data/packages/gsutil/boto/docs/source/conf.py +32 -0
  389. data/packages/gsutil/boto/docs/source/contributing.rst +204 -0
  390. data/packages/gsutil/boto/docs/source/documentation.rst +59 -0
  391. data/packages/gsutil/boto/docs/source/dynamodb_tut.rst +339 -0
  392. data/packages/gsutil/boto/docs/source/ec2_tut.rst +86 -0
  393. data/packages/gsutil/boto/docs/source/elb_tut.rst +257 -0
  394. data/packages/gsutil/boto/docs/source/emr_tut.rst +108 -0
  395. data/packages/gsutil/boto/docs/source/index.rst +146 -0
  396. data/packages/gsutil/boto/docs/source/rds_tut.rst +108 -0
  397. data/packages/gsutil/boto/docs/source/ref/autoscale.rst +62 -0
  398. data/packages/gsutil/boto/docs/source/ref/beanstalk.rst +26 -0
  399. data/packages/gsutil/boto/docs/source/ref/boto.rst +47 -0
  400. data/packages/gsutil/boto/docs/source/ref/cloudformation.rst +34 -0
  401. data/packages/gsutil/boto/docs/source/ref/cloudfront.rst +68 -0
  402. data/packages/gsutil/boto/docs/source/ref/cloudsearch.rst +59 -0
  403. data/packages/gsutil/boto/docs/source/ref/cloudwatch.rst +27 -0
  404. data/packages/gsutil/boto/docs/source/ref/contrib.rst +32 -0
  405. data/packages/gsutil/boto/docs/source/ref/datapipeline.rst +26 -0
  406. data/packages/gsutil/boto/docs/source/ref/dynamodb.rst +61 -0
  407. data/packages/gsutil/boto/docs/source/ref/ec2.rst +140 -0
  408. data/packages/gsutil/boto/docs/source/ref/ecs.rst +19 -0
  409. data/packages/gsutil/boto/docs/source/ref/elasticache.rst +19 -0
  410. data/packages/gsutil/boto/docs/source/ref/elastictranscoder.rst +26 -0
  411. data/packages/gsutil/boto/docs/source/ref/elb.rst +47 -0
  412. data/packages/gsutil/boto/docs/source/ref/emr.rst +34 -0
  413. data/packages/gsutil/boto/docs/source/ref/file.rst +34 -0
  414. data/packages/gsutil/boto/docs/source/ref/fps.rst +19 -0
  415. data/packages/gsutil/boto/docs/source/ref/glacier.rst +63 -0
  416. data/packages/gsutil/boto/docs/source/ref/gs.rst +72 -0
  417. data/packages/gsutil/boto/docs/source/ref/iam.rst +27 -0
  418. data/packages/gsutil/boto/docs/source/ref/index.rst +40 -0
  419. data/packages/gsutil/boto/docs/source/ref/manage.rst +47 -0
  420. data/packages/gsutil/boto/docs/source/ref/mturk.rst +54 -0
  421. data/packages/gsutil/boto/docs/source/ref/mws.rst +33 -0
  422. data/packages/gsutil/boto/docs/source/ref/pyami.rst +103 -0
  423. data/packages/gsutil/boto/docs/source/ref/rds.rst +47 -0
  424. data/packages/gsutil/boto/docs/source/ref/route53.rst +34 -0
  425. data/packages/gsutil/boto/docs/source/ref/s3.rst +111 -0
  426. data/packages/gsutil/boto/docs/source/ref/sdb.rst +45 -0
  427. data/packages/gsutil/boto/docs/source/ref/sdb_db.rst +83 -0
  428. data/packages/gsutil/boto/docs/source/ref/services.rst +61 -0
  429. data/packages/gsutil/boto/docs/source/ref/ses.rst +21 -0
  430. data/packages/gsutil/boto/docs/source/ref/sns.rst +17 -0
  431. data/packages/gsutil/boto/docs/source/ref/sqs.rst +61 -0
  432. data/packages/gsutil/boto/docs/source/ref/sts.rst +25 -0
  433. data/packages/gsutil/boto/docs/source/ref/swf.rst +22 -0
  434. data/packages/gsutil/boto/docs/source/ref/vpc.rst +54 -0
  435. data/packages/gsutil/boto/docs/source/s3_tut.rst +450 -0
  436. data/packages/gsutil/boto/docs/source/security_groups.rst +82 -0
  437. data/packages/gsutil/boto/docs/source/ses_tut.rst +171 -0
  438. data/packages/gsutil/boto/docs/source/simpledb_tut.rst +188 -0
  439. data/packages/gsutil/boto/docs/source/sqs_tut.rst +246 -0
  440. data/packages/gsutil/boto/docs/source/vpc_tut.rst +100 -0
  441. data/packages/gsutil/boto/pylintrc +305 -0
  442. data/packages/gsutil/boto/requirements.txt +10 -0
  443. data/packages/gsutil/boto/setup.py +89 -0
  444. data/packages/gsutil/boto/tests/__init__.py +20 -0
  445. data/packages/gsutil/boto/tests/db/test_lists.py +96 -0
  446. data/packages/gsutil/boto/tests/db/test_password.py +128 -0
  447. data/packages/gsutil/boto/tests/db/test_query.py +152 -0
  448. data/packages/gsutil/boto/tests/db/test_sequence.py +109 -0
  449. data/packages/gsutil/boto/tests/devpay/__init__.py +0 -0
  450. data/packages/gsutil/boto/tests/devpay/test_s3.py +181 -0
  451. data/packages/gsutil/boto/tests/fps/__init__.py +0 -0
  452. data/packages/gsutil/boto/tests/fps/test.py +100 -0
  453. data/packages/gsutil/boto/tests/fps/test_verify_signature.py +12 -0
  454. data/packages/gsutil/boto/tests/integration/__init__.py +0 -0
  455. data/packages/gsutil/boto/tests/integration/beanstalk/test_wrapper.py +209 -0
  456. data/packages/gsutil/boto/tests/integration/cloudformation/__init__.py +21 -0
  457. data/packages/gsutil/boto/tests/integration/cloudformation/test_cert_verification.py +40 -0
  458. data/packages/gsutil/boto/tests/integration/cloudformation/test_connection.py +110 -0
  459. data/packages/gsutil/boto/tests/integration/cloudsearch/__init__.py +21 -0
  460. data/packages/gsutil/boto/tests/integration/cloudsearch/test_cert_verification.py +40 -0
  461. data/packages/gsutil/boto/tests/integration/datapipeline/test_layer1.py +122 -0
  462. data/packages/gsutil/boto/tests/integration/dynamodb/__init__.py +20 -0
  463. data/packages/gsutil/boto/tests/integration/dynamodb/test_cert_verification.py +40 -0
  464. data/packages/gsutil/boto/tests/integration/dynamodb/test_layer1.py +266 -0
  465. data/packages/gsutil/boto/tests/integration/dynamodb/test_layer2.py +484 -0
  466. data/packages/gsutil/boto/tests/integration/dynamodb/test_table.py +84 -0
  467. data/packages/gsutil/boto/tests/integration/ec2/__init__.py +20 -0
  468. data/packages/gsutil/boto/tests/integration/ec2/autoscale/__init__.py +21 -0
  469. data/packages/gsutil/boto/tests/integration/ec2/autoscale/test_cert_verification.py +40 -0
  470. data/packages/gsutil/boto/tests/integration/ec2/autoscale/test_connection.py +167 -0
  471. data/packages/gsutil/boto/tests/integration/ec2/cloudwatch/__init__.py +20 -0
  472. data/packages/gsutil/boto/tests/integration/ec2/cloudwatch/test_cert_verification.py +40 -0
  473. data/packages/gsutil/boto/tests/integration/ec2/cloudwatch/test_connection.py +277 -0
  474. data/packages/gsutil/boto/tests/integration/ec2/elb/__init__.py +20 -0
  475. data/packages/gsutil/boto/tests/integration/ec2/elb/test_cert_verification.py +40 -0
  476. data/packages/gsutil/boto/tests/integration/ec2/elb/test_connection.py +130 -0
  477. data/packages/gsutil/boto/tests/integration/ec2/test_cert_verification.py +40 -0
  478. data/packages/gsutil/boto/tests/integration/ec2/test_connection.py +192 -0
  479. data/packages/gsutil/boto/tests/integration/ec2/vpc/__init__.py +0 -0
  480. data/packages/gsutil/boto/tests/integration/ec2/vpc/test_connection.py +95 -0
  481. data/packages/gsutil/boto/tests/integration/elasticache/__init__.py +0 -0
  482. data/packages/gsutil/boto/tests/integration/elasticache/test_layer1.py +67 -0
  483. data/packages/gsutil/boto/tests/integration/elastictranscoder/__init__.py +0 -0
  484. data/packages/gsutil/boto/tests/integration/elastictranscoder/test_cert_verification.py +35 -0
  485. data/packages/gsutil/boto/tests/integration/elastictranscoder/test_layer1.py +115 -0
  486. data/packages/gsutil/boto/tests/integration/emr/__init__.py +20 -0
  487. data/packages/gsutil/boto/tests/integration/emr/test_cert_verification.py +40 -0
  488. data/packages/gsutil/boto/tests/integration/glacier/__init__.py +22 -0
  489. data/packages/gsutil/boto/tests/integration/glacier/test_cert_verification.py +40 -0
  490. data/packages/gsutil/boto/tests/integration/glacier/test_layer1.py +44 -0
  491. data/packages/gsutil/boto/tests/integration/glacier/test_layer2.py +45 -0
  492. data/packages/gsutil/boto/tests/integration/gs/__init__.py +0 -0
  493. data/packages/gsutil/boto/tests/integration/gs/cb_test_harness.py +71 -0
  494. data/packages/gsutil/boto/tests/integration/gs/test_basic.py +379 -0
  495. data/packages/gsutil/boto/tests/integration/gs/test_generation_conditionals.py +399 -0
  496. data/packages/gsutil/boto/tests/integration/gs/test_resumable_downloads.py +358 -0
  497. data/packages/gsutil/boto/tests/integration/gs/test_resumable_uploads.py +525 -0
  498. data/packages/gsutil/boto/tests/integration/gs/test_storage_uri.py +125 -0
  499. data/packages/gsutil/boto/tests/integration/gs/test_versioning.py +268 -0
  500. data/packages/gsutil/boto/tests/integration/gs/testcase.py +116 -0
  501. data/packages/gsutil/boto/tests/integration/gs/util.py +63 -0
  502. data/packages/gsutil/boto/tests/integration/iam/__init__.py +20 -0
  503. data/packages/gsutil/boto/tests/integration/iam/test_cert_verification.py +40 -0
  504. data/packages/gsutil/boto/tests/integration/mws/__init__.py +0 -0
  505. data/packages/gsutil/boto/tests/integration/mws/test.py +100 -0
  506. data/packages/gsutil/boto/tests/integration/rds/__init__.py +21 -0
  507. data/packages/gsutil/boto/tests/integration/rds/test_cert_verification.py +40 -0
  508. data/packages/gsutil/boto/tests/integration/route53/__init__.py +20 -0
  509. data/packages/gsutil/boto/tests/integration/route53/test_cert_verification.py +40 -0
  510. data/packages/gsutil/boto/tests/integration/route53/test_zone.py +132 -0
  511. data/packages/gsutil/boto/tests/integration/s3/__init__.py +20 -0
  512. data/packages/gsutil/boto/tests/integration/s3/mock_storage_service.py +589 -0
  513. data/packages/gsutil/boto/tests/integration/s3/other_cacerts.txt +70 -0
  514. data/packages/gsutil/boto/tests/integration/s3/test_bucket.py +263 -0
  515. data/packages/gsutil/boto/tests/integration/s3/test_cert_verification.py +40 -0
  516. data/packages/gsutil/boto/tests/integration/s3/test_connection.py +245 -0
  517. data/packages/gsutil/boto/tests/integration/s3/test_cors.py +78 -0
  518. data/packages/gsutil/boto/tests/integration/s3/test_encryption.py +115 -0
  519. data/packages/gsutil/boto/tests/integration/s3/test_https_cert_validation.py +141 -0
  520. data/packages/gsutil/boto/tests/integration/s3/test_key.py +375 -0
  521. data/packages/gsutil/boto/tests/integration/s3/test_mfa.py +95 -0
  522. data/packages/gsutil/boto/tests/integration/s3/test_multidelete.py +181 -0
  523. data/packages/gsutil/boto/tests/integration/s3/test_multipart.py +139 -0
  524. data/packages/gsutil/boto/tests/integration/s3/test_pool.py +246 -0
  525. data/packages/gsutil/boto/tests/integration/s3/test_versioning.py +158 -0
  526. data/packages/gsutil/boto/tests/integration/sdb/__init__.py +20 -0
  527. data/packages/gsutil/boto/tests/integration/sdb/test_cert_verification.py +40 -0
  528. data/packages/gsutil/boto/tests/integration/sdb/test_connection.py +119 -0
  529. data/packages/gsutil/boto/tests/integration/ses/__init__.py +0 -0
  530. data/packages/gsutil/boto/tests/integration/ses/test_cert_verification.py +40 -0
  531. data/packages/gsutil/boto/tests/integration/ses/test_connection.py +38 -0
  532. data/packages/gsutil/boto/tests/integration/sns/__init__.py +20 -0
  533. data/packages/gsutil/boto/tests/integration/sns/test_cert_verification.py +40 -0
  534. data/packages/gsutil/boto/tests/integration/sqs/__init__.py +20 -0
  535. data/packages/gsutil/boto/tests/integration/sqs/test_cert_verification.py +40 -0
  536. data/packages/gsutil/boto/tests/integration/sqs/test_connection.py +217 -0
  537. data/packages/gsutil/boto/tests/integration/sts/__init__.py +20 -0
  538. data/packages/gsutil/boto/tests/integration/sts/test_cert_verification.py +40 -0
  539. data/packages/gsutil/boto/tests/integration/sts/test_session_token.py +65 -0
  540. data/packages/gsutil/boto/tests/integration/swf/__init__.py +0 -0
  541. data/packages/gsutil/boto/tests/integration/swf/test_cert_verification.py +40 -0
  542. data/packages/gsutil/boto/tests/integration/swf/test_layer1.py +246 -0
  543. data/packages/gsutil/boto/tests/integration/swf/test_layer1_workflow_execution.py +173 -0
  544. data/packages/gsutil/boto/tests/mturk/__init__.py +0 -0
  545. data/packages/gsutil/boto/tests/mturk/_init_environment.py +28 -0
  546. data/packages/gsutil/boto/tests/mturk/all_tests.py +24 -0
  547. data/packages/gsutil/boto/tests/mturk/cleanup_tests.py +47 -0
  548. data/packages/gsutil/boto/tests/mturk/common.py +45 -0
  549. data/packages/gsutil/boto/tests/mturk/create_free_text_question_regex.doctest +100 -0
  550. data/packages/gsutil/boto/tests/mturk/create_hit.doctest +92 -0
  551. data/packages/gsutil/boto/tests/mturk/create_hit_binary.doctest +94 -0
  552. data/packages/gsutil/boto/tests/mturk/create_hit_external.py +21 -0
  553. data/packages/gsutil/boto/tests/mturk/create_hit_from_hit_type.doctest +103 -0
  554. data/packages/gsutil/boto/tests/mturk/create_hit_test.py +21 -0
  555. data/packages/gsutil/boto/tests/mturk/create_hit_with_qualifications.py +16 -0
  556. data/packages/gsutil/boto/tests/mturk/hit_persistence.py +27 -0
  557. data/packages/gsutil/boto/tests/mturk/mocks.py +11 -0
  558. data/packages/gsutil/boto/tests/mturk/reviewable_hits.doctest +129 -0
  559. data/packages/gsutil/boto/tests/mturk/run-doctest.py +13 -0
  560. data/packages/gsutil/boto/tests/mturk/search_hits.doctest +16 -0
  561. data/packages/gsutil/boto/tests/mturk/selenium_support.py +61 -0
  562. data/packages/gsutil/boto/tests/mturk/support.py +7 -0
  563. data/packages/gsutil/boto/tests/mturk/test_disable_hit.py +11 -0
  564. data/packages/gsutil/boto/tests/test.py +59 -0
  565. data/packages/gsutil/boto/tests/unit/__init__.py +79 -0
  566. data/packages/gsutil/boto/tests/unit/auth/__init__.py +0 -0
  567. data/packages/gsutil/boto/tests/unit/auth/test_sigv4.py +73 -0
  568. data/packages/gsutil/boto/tests/unit/beanstalk/__init__.py +0 -0
  569. data/packages/gsutil/boto/tests/unit/beanstalk/test_layer1.py +128 -0
  570. data/packages/gsutil/boto/tests/unit/cloudformation/__init__.py +0 -0
  571. data/packages/gsutil/boto/tests/unit/cloudformation/test_connection.py +605 -0
  572. data/packages/gsutil/boto/tests/unit/cloudformation/test_stack.py +63 -0
  573. data/packages/gsutil/boto/tests/unit/cloudfront/__init__.py +0 -0
  574. data/packages/gsutil/boto/tests/unit/cloudfront/test_invalidation_list.py +113 -0
  575. data/packages/gsutil/boto/tests/unit/cloudfront/test_signed_urls.py +354 -0
  576. data/packages/gsutil/boto/tests/unit/cloudsearch/__init__.py +1 -0
  577. data/packages/gsutil/boto/tests/unit/cloudsearch/test_connection.py +241 -0
  578. data/packages/gsutil/boto/tests/unit/cloudsearch/test_document.py +324 -0
  579. data/packages/gsutil/boto/tests/unit/cloudsearch/test_search.py +325 -0
  580. data/packages/gsutil/boto/tests/unit/dynamodb/__init__.py +0 -0
  581. data/packages/gsutil/boto/tests/unit/dynamodb/test_batch.py +103 -0
  582. data/packages/gsutil/boto/tests/unit/dynamodb/test_layer2.py +119 -0
  583. data/packages/gsutil/boto/tests/unit/dynamodb/test_types.py +82 -0
  584. data/packages/gsutil/boto/tests/unit/ec2/__init__.py +0 -0
  585. data/packages/gsutil/boto/tests/unit/ec2/autoscale/__init__.py +0 -0
  586. data/packages/gsutil/boto/tests/unit/ec2/autoscale/test_group.py +162 -0
  587. data/packages/gsutil/boto/tests/unit/ec2/test_address.py +39 -0
  588. data/packages/gsutil/boto/tests/unit/ec2/test_blockdevicemapping.py +79 -0
  589. data/packages/gsutil/boto/tests/unit/ec2/test_connection.py +480 -0
  590. data/packages/gsutil/boto/tests/unit/ec2/test_instance.py +243 -0
  591. data/packages/gsutil/boto/tests/unit/ec2/test_networkinterface.py +140 -0
  592. data/packages/gsutil/boto/tests/unit/ec2/test_volume.py +248 -0
  593. data/packages/gsutil/boto/tests/unit/emr/test_emr_responses.py +373 -0
  594. data/packages/gsutil/boto/tests/unit/glacier/__init__.py +0 -0
  595. data/packages/gsutil/boto/tests/unit/glacier/test_concurrent.py +120 -0
  596. data/packages/gsutil/boto/tests/unit/glacier/test_job.py +60 -0
  597. data/packages/gsutil/boto/tests/unit/glacier/test_layer1.py +98 -0
  598. data/packages/gsutil/boto/tests/unit/glacier/test_layer2.py +266 -0
  599. data/packages/gsutil/boto/tests/unit/glacier/test_utils.py +116 -0
  600. data/packages/gsutil/boto/tests/unit/glacier/test_vault.py +100 -0
  601. data/packages/gsutil/boto/tests/unit/glacier/test_writer.py +185 -0
  602. data/packages/gsutil/boto/tests/unit/provider/__init__.py +0 -0
  603. data/packages/gsutil/boto/tests/unit/provider/test_provider.py +176 -0
  604. data/packages/gsutil/boto/tests/unit/rds/__init__.py +0 -0
  605. data/packages/gsutil/boto/tests/unit/rds/test_connection.py +131 -0
  606. data/packages/gsutil/boto/tests/unit/s3/__init__.py +0 -0
  607. data/packages/gsutil/boto/tests/unit/s3/test_cors_configuration.py +77 -0
  608. data/packages/gsutil/boto/tests/unit/s3/test_key.py +75 -0
  609. data/packages/gsutil/boto/tests/unit/s3/test_keyfile.py +101 -0
  610. data/packages/gsutil/boto/tests/unit/s3/test_lifecycle.py +97 -0
  611. data/packages/gsutil/boto/tests/unit/s3/test_tagging.py +47 -0
  612. data/packages/gsutil/boto/tests/unit/s3/test_uri.py +257 -0
  613. data/packages/gsutil/boto/tests/unit/s3/test_website.py +188 -0
  614. data/packages/gsutil/boto/tests/unit/sns/__init__.py +0 -0
  615. data/packages/gsutil/boto/tests/unit/sns/test_connection.py +99 -0
  616. data/packages/gsutil/boto/tests/unit/sqs/__init__.py +0 -0
  617. data/packages/gsutil/boto/tests/unit/sqs/test_connection.py +98 -0
  618. data/packages/gsutil/boto/tests/unit/sqs/test_queue.py +40 -0
  619. data/packages/gsutil/boto/tests/unit/sts/test_connection.py +74 -0
  620. data/packages/gsutil/boto/tests/unit/test_connection.py +60 -0
  621. data/packages/gsutil/boto/tests/unit/utils/test_utils.py +109 -0
  622. data/packages/gsutil/boto/tox.ini +8 -0
  623. data/packages/gsutil/gslib/README +5 -0
  624. data/packages/gsutil/gslib/__init__.py +22 -0
  625. data/packages/gsutil/gslib/__init__.pyc +0 -0
  626. data/packages/gsutil/gslib/addlhelp/__init__.py +15 -0
  627. data/packages/gsutil/gslib/addlhelp/acls.py +234 -0
  628. data/packages/gsutil/gslib/addlhelp/anon.py +57 -0
  629. data/packages/gsutil/gslib/addlhelp/command_opts.py +116 -0
  630. data/packages/gsutil/gslib/addlhelp/dev.py +139 -0
  631. data/packages/gsutil/gslib/addlhelp/metadata.py +186 -0
  632. data/packages/gsutil/gslib/addlhelp/naming.py +173 -0
  633. data/packages/gsutil/gslib/addlhelp/prod.py +160 -0
  634. data/packages/gsutil/gslib/addlhelp/projects.py +130 -0
  635. data/packages/gsutil/gslib/addlhelp/subdirs.py +110 -0
  636. data/packages/gsutil/gslib/addlhelp/support.py +86 -0
  637. data/packages/gsutil/gslib/addlhelp/versioning.py +242 -0
  638. data/packages/gsutil/gslib/addlhelp/wildcards.py +170 -0
  639. data/packages/gsutil/gslib/bucket_listing_ref.py +175 -0
  640. data/packages/gsutil/gslib/bucket_listing_ref.pyc +0 -0
  641. data/packages/gsutil/gslib/command.py +722 -0
  642. data/packages/gsutil/gslib/command.pyc +0 -0
  643. data/packages/gsutil/gslib/command_runner.py +101 -0
  644. data/packages/gsutil/gslib/command_runner.pyc +0 -0
  645. data/packages/gsutil/gslib/commands/__init__.py +15 -0
  646. data/packages/gsutil/gslib/commands/__init__.pyc +0 -0
  647. data/packages/gsutil/gslib/commands/cat.py +131 -0
  648. data/packages/gsutil/gslib/commands/cat.pyc +0 -0
  649. data/packages/gsutil/gslib/commands/chacl.py +532 -0
  650. data/packages/gsutil/gslib/commands/chacl.pyc +0 -0
  651. data/packages/gsutil/gslib/commands/config.py +694 -0
  652. data/packages/gsutil/gslib/commands/config.pyc +0 -0
  653. data/packages/gsutil/gslib/commands/cp.py +1818 -0
  654. data/packages/gsutil/gslib/commands/cp.pyc +0 -0
  655. data/packages/gsutil/gslib/commands/disablelogging.py +101 -0
  656. data/packages/gsutil/gslib/commands/disablelogging.pyc +0 -0
  657. data/packages/gsutil/gslib/commands/enablelogging.py +149 -0
  658. data/packages/gsutil/gslib/commands/enablelogging.pyc +0 -0
  659. data/packages/gsutil/gslib/commands/getacl.py +82 -0
  660. data/packages/gsutil/gslib/commands/getacl.pyc +0 -0
  661. data/packages/gsutil/gslib/commands/getcors.py +121 -0
  662. data/packages/gsutil/gslib/commands/getcors.pyc +0 -0
  663. data/packages/gsutil/gslib/commands/getdefacl.py +86 -0
  664. data/packages/gsutil/gslib/commands/getdefacl.pyc +0 -0
  665. data/packages/gsutil/gslib/commands/getlogging.py +137 -0
  666. data/packages/gsutil/gslib/commands/getlogging.pyc +0 -0
  667. data/packages/gsutil/gslib/commands/getversioning.py +116 -0
  668. data/packages/gsutil/gslib/commands/getversioning.pyc +0 -0
  669. data/packages/gsutil/gslib/commands/getwebcfg.py +122 -0
  670. data/packages/gsutil/gslib/commands/getwebcfg.pyc +0 -0
  671. data/packages/gsutil/gslib/commands/help.py +218 -0
  672. data/packages/gsutil/gslib/commands/help.pyc +0 -0
  673. data/packages/gsutil/gslib/commands/ls.py +578 -0
  674. data/packages/gsutil/gslib/commands/ls.pyc +0 -0
  675. data/packages/gsutil/gslib/commands/mb.py +172 -0
  676. data/packages/gsutil/gslib/commands/mb.pyc +0 -0
  677. data/packages/gsutil/gslib/commands/mv.py +159 -0
  678. data/packages/gsutil/gslib/commands/mv.pyc +0 -0
  679. data/packages/gsutil/gslib/commands/perfdiag.py +903 -0
  680. data/packages/gsutil/gslib/commands/perfdiag.pyc +0 -0
  681. data/packages/gsutil/gslib/commands/rb.py +113 -0
  682. data/packages/gsutil/gslib/commands/rb.pyc +0 -0
  683. data/packages/gsutil/gslib/commands/rm.py +239 -0
  684. data/packages/gsutil/gslib/commands/rm.pyc +0 -0
  685. data/packages/gsutil/gslib/commands/setacl.py +138 -0
  686. data/packages/gsutil/gslib/commands/setacl.pyc +0 -0
  687. data/packages/gsutil/gslib/commands/setcors.py +145 -0
  688. data/packages/gsutil/gslib/commands/setcors.pyc +0 -0
  689. data/packages/gsutil/gslib/commands/setdefacl.py +105 -0
  690. data/packages/gsutil/gslib/commands/setdefacl.pyc +0 -0
  691. data/packages/gsutil/gslib/commands/setmeta.py +428 -0
  692. data/packages/gsutil/gslib/commands/setmeta.pyc +0 -0
  693. data/packages/gsutil/gslib/commands/setversioning.py +114 -0
  694. data/packages/gsutil/gslib/commands/setversioning.pyc +0 -0
  695. data/packages/gsutil/gslib/commands/setwebcfg.py +190 -0
  696. data/packages/gsutil/gslib/commands/setwebcfg.pyc +0 -0
  697. data/packages/gsutil/gslib/commands/test.py +228 -0
  698. data/packages/gsutil/gslib/commands/test.pyc +0 -0
  699. data/packages/gsutil/gslib/commands/update.py +305 -0
  700. data/packages/gsutil/gslib/commands/update.pyc +0 -0
  701. data/packages/gsutil/gslib/commands/version.py +150 -0
  702. data/packages/gsutil/gslib/commands/version.pyc +0 -0
  703. data/packages/gsutil/gslib/exception.py +76 -0
  704. data/packages/gsutil/gslib/exception.pyc +0 -0
  705. data/packages/gsutil/gslib/help_provider.py +81 -0
  706. data/packages/gsutil/gslib/help_provider.pyc +0 -0
  707. data/packages/gsutil/gslib/name_expansion.py +550 -0
  708. data/packages/gsutil/gslib/name_expansion.pyc +0 -0
  709. data/packages/gsutil/gslib/no_op_auth_plugin.py +30 -0
  710. data/packages/gsutil/gslib/plurality_checkable_iterator.py +56 -0
  711. data/packages/gsutil/gslib/plurality_checkable_iterator.pyc +0 -0
  712. data/packages/gsutil/gslib/project_id.py +67 -0
  713. data/packages/gsutil/gslib/project_id.pyc +0 -0
  714. data/packages/gsutil/gslib/storage_uri_builder.py +56 -0
  715. data/packages/gsutil/gslib/storage_uri_builder.pyc +0 -0
  716. data/packages/gsutil/gslib/tests/__init__.py +15 -0
  717. data/packages/gsutil/gslib/tests/__init__.pyc +0 -0
  718. data/packages/gsutil/gslib/tests/test_chacl.py +236 -0
  719. data/packages/gsutil/gslib/tests/test_cp.py +267 -0
  720. data/packages/gsutil/gslib/tests/test_data/test.gif +0 -0
  721. data/packages/gsutil/gslib/tests/test_data/test.mp3 +0 -0
  722. data/packages/gsutil/gslib/tests/test_ls.py +66 -0
  723. data/packages/gsutil/gslib/tests/test_mv.py +69 -0
  724. data/packages/gsutil/gslib/tests/test_naming.py +989 -0
  725. data/packages/gsutil/gslib/tests/test_perfdiag.py +41 -0
  726. data/packages/gsutil/gslib/tests/test_plurality_checkable_iterator.py +67 -0
  727. data/packages/gsutil/gslib/tests/test_rm.py +143 -0
  728. data/packages/gsutil/gslib/tests/test_setacl.py +152 -0
  729. data/packages/gsutil/gslib/tests/test_setcors.py +168 -0
  730. data/packages/gsutil/gslib/tests/test_setmeta.py +91 -0
  731. data/packages/gsutil/gslib/tests/test_setversioning.py +44 -0
  732. data/packages/gsutil/gslib/tests/test_setwebcfg.py +63 -0
  733. data/packages/gsutil/gslib/tests/test_thread_pool.py +92 -0
  734. data/packages/gsutil/gslib/tests/test_wildcard_iterator.py +364 -0
  735. data/packages/gsutil/gslib/tests/testcase/__init__.py +18 -0
  736. data/packages/gsutil/gslib/tests/testcase/base.py +89 -0
  737. data/packages/gsutil/gslib/tests/testcase/integration_testcase.py +197 -0
  738. data/packages/gsutil/gslib/tests/testcase/unit_testcase.py +230 -0
  739. data/packages/gsutil/gslib/tests/util.py +125 -0
  740. data/packages/gsutil/gslib/tests/util.pyc +0 -0
  741. data/packages/gsutil/gslib/thread_pool.py +79 -0
  742. data/packages/gsutil/gslib/thread_pool.pyc +0 -0
  743. data/packages/gsutil/gslib/util.py +151 -0
  744. data/packages/gsutil/gslib/util.pyc +0 -0
  745. data/packages/gsutil/gslib/wildcard_iterator.py +492 -0
  746. data/packages/gsutil/gslib/wildcard_iterator.pyc +0 -0
  747. data/packages/gsutil/gsutil +377 -0
  748. data/packages/gsutil/gsutil.spec.in +75 -0
  749. data/packages/gsutil/oauth2_plugin/__init__.py +22 -0
  750. data/packages/gsutil/oauth2_plugin/__init__.pyc +0 -0
  751. data/packages/gsutil/oauth2_plugin/oauth2_client.py +642 -0
  752. data/packages/gsutil/oauth2_plugin/oauth2_client.pyc +0 -0
  753. data/packages/gsutil/oauth2_plugin/oauth2_client_test.py +374 -0
  754. data/packages/gsutil/oauth2_plugin/oauth2_helper.py +110 -0
  755. data/packages/gsutil/oauth2_plugin/oauth2_helper.pyc +0 -0
  756. data/packages/gsutil/oauth2_plugin/oauth2_plugin.py +24 -0
  757. data/packages/gsutil/oauth2_plugin/oauth2_plugin.pyc +0 -0
  758. data/packages/gsutil/pkg_gen.sh +54 -0
  759. data/packages/gsutil/pkg_util.py +60 -0
  760. data/packages/gsutil/setup.py +141 -0
  761. data/packages/gsutil/third_party/__init__.py +0 -0
  762. data/packages/gsutil/third_party/__init__.pyc +0 -0
  763. data/packages/gsutil/third_party/fancy_urllib/README +21 -0
  764. data/packages/gsutil/third_party/fancy_urllib/__init__.py +398 -0
  765. data/packages/gsutil/third_party/fancy_urllib/__init__.pyc +0 -0
  766. data/tasks/rubygem.rake +3 -1
  767. metadata +770 -7
  768. metadata.gz.sig +0 -0
@@ -0,0 +1,294 @@
1
+ # Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a
4
+ # copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish, dis-
7
+ # tribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the fol-
9
+ # lowing conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included
12
+ # in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16
+ # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17
+ # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
+ # IN THE SOFTWARE.
21
+
22
+ from boto.sdb.db.manager import get_manager
23
+ from boto.sdb.db.property import Property
24
+ from boto.sdb.db.key import Key
25
+ from boto.sdb.db.query import Query
26
+ import boto
27
+
28
+ class ModelMeta(type):
29
+ "Metaclass for all Models"
30
+
31
+ def __init__(cls, name, bases, dict):
32
+ super(ModelMeta, cls).__init__(name, bases, dict)
33
+ # Make sure this is a subclass of Model - mainly copied from django ModelBase (thanks!)
34
+ cls.__sub_classes__ = []
35
+ try:
36
+ if filter(lambda b: issubclass(b, Model), bases):
37
+ for base in bases:
38
+ base.__sub_classes__.append(cls)
39
+ cls._manager = get_manager(cls)
40
+ # look for all of the Properties and set their names
41
+ for key in dict.keys():
42
+ if isinstance(dict[key], Property):
43
+ property = dict[key]
44
+ property.__property_config__(cls, key)
45
+ prop_names = []
46
+ props = cls.properties()
47
+ for prop in props:
48
+ if not prop.__class__.__name__.startswith('_'):
49
+ prop_names.append(prop.name)
50
+ setattr(cls, '_prop_names', prop_names)
51
+ except NameError:
52
+ # 'Model' isn't defined yet, meaning we're looking at our own
53
+ # Model class, defined below.
54
+ pass
55
+
56
+ class Model(object):
57
+ __metaclass__ = ModelMeta
58
+ __consistent__ = False # Consistent is set off by default
59
+ id = None
60
+
61
+ @classmethod
62
+ def get_lineage(cls):
63
+ l = [c.__name__ for c in cls.mro()]
64
+ l.reverse()
65
+ return '.'.join(l)
66
+
67
+ @classmethod
68
+ def kind(cls):
69
+ return cls.__name__
70
+
71
+ @classmethod
72
+ def _get_by_id(cls, id, manager=None):
73
+ if not manager:
74
+ manager = cls._manager
75
+ return manager.get_object(cls, id)
76
+
77
+ @classmethod
78
+ def get_by_id(cls, ids=None, parent=None):
79
+ if isinstance(ids, list):
80
+ objs = [cls._get_by_id(id) for id in ids]
81
+ return objs
82
+ else:
83
+ return cls._get_by_id(ids)
84
+
85
+ get_by_ids = get_by_id
86
+
87
+ @classmethod
88
+ def get_by_key_name(cls, key_names, parent=None):
89
+ raise NotImplementedError("Key Names are not currently supported")
90
+
91
+ @classmethod
92
+ def find(cls, limit=None, next_token=None, **params):
93
+ q = Query(cls, limit=limit, next_token=next_token)
94
+ for key, value in params.items():
95
+ q.filter('%s =' % key, value)
96
+ return q
97
+
98
+ @classmethod
99
+ def all(cls, limit=None, next_token=None):
100
+ return cls.find(limit=limit, next_token=next_token)
101
+
102
+ @classmethod
103
+ def get_or_insert(key_name, **kw):
104
+ raise NotImplementedError("get_or_insert not currently supported")
105
+
106
+ @classmethod
107
+ def properties(cls, hidden=True):
108
+ properties = []
109
+ while cls:
110
+ for key in cls.__dict__.keys():
111
+ prop = cls.__dict__[key]
112
+ if isinstance(prop, Property):
113
+ if hidden or not prop.__class__.__name__.startswith('_'):
114
+ properties.append(prop)
115
+ if len(cls.__bases__) > 0:
116
+ cls = cls.__bases__[0]
117
+ else:
118
+ cls = None
119
+ return properties
120
+
121
+ @classmethod
122
+ def find_property(cls, prop_name):
123
+ property = None
124
+ while cls:
125
+ for key in cls.__dict__.keys():
126
+ prop = cls.__dict__[key]
127
+ if isinstance(prop, Property):
128
+ if not prop.__class__.__name__.startswith('_') and prop_name == prop.name:
129
+ property = prop
130
+ if len(cls.__bases__) > 0:
131
+ cls = cls.__bases__[0]
132
+ else:
133
+ cls = None
134
+ return property
135
+
136
+ @classmethod
137
+ def get_xmlmanager(cls):
138
+ if not hasattr(cls, '_xmlmanager'):
139
+ from boto.sdb.db.manager.xmlmanager import XMLManager
140
+ cls._xmlmanager = XMLManager(cls, None, None, None,
141
+ None, None, None, None, False)
142
+ return cls._xmlmanager
143
+
144
+ @classmethod
145
+ def from_xml(cls, fp):
146
+ xmlmanager = cls.get_xmlmanager()
147
+ return xmlmanager.unmarshal_object(fp)
148
+
149
+ def __init__(self, id=None, **kw):
150
+ self._loaded = False
151
+ # first try to initialize all properties to their default values
152
+ for prop in self.properties(hidden=False):
153
+ try:
154
+ setattr(self, prop.name, prop.default_value())
155
+ except ValueError:
156
+ pass
157
+ if 'manager' in kw:
158
+ self._manager = kw['manager']
159
+ self.id = id
160
+ for key in kw:
161
+ if key != 'manager':
162
+ # We don't want any errors populating up when loading an object,
163
+ # so if it fails we just revert to it's default value
164
+ try:
165
+ setattr(self, key, kw[key])
166
+ except Exception, e:
167
+ boto.log.exception(e)
168
+
169
+ def __repr__(self):
170
+ return '%s<%s>' % (self.__class__.__name__, self.id)
171
+
172
+ def __str__(self):
173
+ return str(self.id)
174
+
175
+ def __eq__(self, other):
176
+ return other and isinstance(other, Model) and self.id == other.id
177
+
178
+ def _get_raw_item(self):
179
+ return self._manager.get_raw_item(self)
180
+
181
+ def load(self):
182
+ if self.id and not self._loaded:
183
+ self._manager.load_object(self)
184
+
185
+ def reload(self):
186
+ if self.id:
187
+ self._loaded = False
188
+ self._manager.load_object(self)
189
+
190
+ def put(self, expected_value=None):
191
+ """
192
+ Save this object as it is, with an optional expected value
193
+
194
+ :param expected_value: Optional tuple of Attribute, and Value that
195
+ must be the same in order to save this object. If this
196
+ condition is not met, an SDBResponseError will be raised with a
197
+ Confict status code.
198
+ :type expected_value: tuple or list
199
+ :return: This object
200
+ :rtype: :class:`boto.sdb.db.model.Model`
201
+ """
202
+ self._manager.save_object(self, expected_value)
203
+ return self
204
+
205
+ save = put
206
+
207
+ def put_attributes(self, attrs):
208
+ """
209
+ Save just these few attributes, not the whole object
210
+
211
+ :param attrs: Attributes to save, key->value dict
212
+ :type attrs: dict
213
+ :return: self
214
+ :rtype: :class:`boto.sdb.db.model.Model`
215
+ """
216
+ assert(isinstance(attrs, dict)), "Argument must be a dict of key->values to save"
217
+ for prop_name in attrs:
218
+ value = attrs[prop_name]
219
+ prop = self.find_property(prop_name)
220
+ assert(prop), "Property not found: %s" % prop_name
221
+ self._manager.set_property(prop, self, prop_name, value)
222
+ self.reload()
223
+ return self
224
+
225
+ def delete_attributes(self, attrs):
226
+ """
227
+ Delete just these attributes, not the whole object.
228
+
229
+ :param attrs: Attributes to save, as a list of string names
230
+ :type attrs: list
231
+ :return: self
232
+ :rtype: :class:`boto.sdb.db.model.Model`
233
+ """
234
+ assert(isinstance(attrs, list)), "Argument must be a list of names of keys to delete."
235
+ self._manager.domain.delete_attributes(self.id, attrs)
236
+ self.reload()
237
+ return self
238
+
239
+ save_attributes = put_attributes
240
+
241
+ def delete(self):
242
+ self._manager.delete_object(self)
243
+
244
+ def key(self):
245
+ return Key(obj=self)
246
+
247
+ def set_manager(self, manager):
248
+ self._manager = manager
249
+
250
+ def to_dict(self):
251
+ props = {}
252
+ for prop in self.properties(hidden=False):
253
+ props[prop.name] = getattr(self, prop.name)
254
+ obj = {'properties' : props,
255
+ 'id' : self.id}
256
+ return {self.__class__.__name__ : obj}
257
+
258
+ def to_xml(self, doc=None):
259
+ xmlmanager = self.get_xmlmanager()
260
+ doc = xmlmanager.marshal_object(self, doc)
261
+ return doc
262
+
263
+ @classmethod
264
+ def find_subclass(cls, name):
265
+ """Find a subclass with a given name"""
266
+ if name == cls.__name__:
267
+ return cls
268
+ for sc in cls.__sub_classes__:
269
+ r = sc.find_subclass(name)
270
+ if r != None:
271
+ return r
272
+
273
+ class Expando(Model):
274
+
275
+ def __setattr__(self, name, value):
276
+ if name in self._prop_names:
277
+ object.__setattr__(self, name, value)
278
+ elif name.startswith('_'):
279
+ object.__setattr__(self, name, value)
280
+ elif name == 'id':
281
+ object.__setattr__(self, name, value)
282
+ else:
283
+ self._manager.set_key_value(self, name, value)
284
+ object.__setattr__(self, name, value)
285
+
286
+ def __getattr__(self, name):
287
+ if not name.startswith('_'):
288
+ value = self._manager.get_key_value(self, name)
289
+ if value:
290
+ object.__setattr__(self, name, value)
291
+ return value
292
+ raise AttributeError
293
+
294
+
@@ -0,0 +1,703 @@
1
+ # Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a
4
+ # copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish, dis-
7
+ # tribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the fol-
9
+ # lowing conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included
12
+ # in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16
+ # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17
+ # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
+ # IN THE SOFTWARE.
21
+
22
+ import datetime
23
+ from key import Key
24
+ from boto.utils import Password
25
+ from boto.sdb.db.query import Query
26
+ import re
27
+ import boto
28
+ import boto.s3.key
29
+ from boto.sdb.db.blob import Blob
30
+
31
+
32
+ class Property(object):
33
+
34
+ data_type = str
35
+ type_name = ''
36
+ name = ''
37
+ verbose_name = ''
38
+
39
+ def __init__(self, verbose_name=None, name=None, default=None,
40
+ required=False, validator=None, choices=None, unique=False):
41
+ self.verbose_name = verbose_name
42
+ self.name = name
43
+ self.default = default
44
+ self.required = required
45
+ self.validator = validator
46
+ self.choices = choices
47
+ if self.name:
48
+ self.slot_name = '_' + self.name
49
+ else:
50
+ self.slot_name = '_'
51
+ self.unique = unique
52
+
53
+ def __get__(self, obj, objtype):
54
+ if obj:
55
+ obj.load()
56
+ return getattr(obj, self.slot_name)
57
+ else:
58
+ return None
59
+
60
+ def __set__(self, obj, value):
61
+ self.validate(value)
62
+
63
+ # Fire off any on_set functions
64
+ try:
65
+ if obj._loaded and hasattr(obj, "on_set_%s" % self.name):
66
+ fnc = getattr(obj, "on_set_%s" % self.name)
67
+ value = fnc(value)
68
+ except Exception:
69
+ boto.log.exception("Exception running on_set_%s" % self.name)
70
+
71
+ setattr(obj, self.slot_name, value)
72
+
73
+ def __property_config__(self, model_class, property_name):
74
+ self.model_class = model_class
75
+ self.name = property_name
76
+ self.slot_name = '_' + self.name
77
+
78
+ def default_validator(self, value):
79
+ if isinstance(value, basestring) or value == self.default_value():
80
+ return
81
+ if not isinstance(value, self.data_type):
82
+ raise TypeError('Validation Error, %s.%s expecting %s, got %s' % (self.model_class.__name__, self.name, self.data_type, type(value)))
83
+
84
+ def default_value(self):
85
+ return self.default
86
+
87
+ def validate(self, value):
88
+ if self.required and value == None:
89
+ raise ValueError('%s is a required property' % self.name)
90
+ if self.choices and value and not value in self.choices:
91
+ raise ValueError('%s not a valid choice for %s.%s' % (value, self.model_class.__name__, self.name))
92
+ if self.validator:
93
+ self.validator(value)
94
+ else:
95
+ self.default_validator(value)
96
+ return value
97
+
98
+ def empty(self, value):
99
+ return not value
100
+
101
+ def get_value_for_datastore(self, model_instance):
102
+ return getattr(model_instance, self.name)
103
+
104
+ def make_value_from_datastore(self, value):
105
+ return value
106
+
107
+ def get_choices(self):
108
+ if callable(self.choices):
109
+ return self.choices()
110
+ return self.choices
111
+
112
+
113
+ def validate_string(value):
114
+ if value == None:
115
+ return
116
+ elif isinstance(value, str) or isinstance(value, unicode):
117
+ if len(value) > 1024:
118
+ raise ValueError('Length of value greater than maxlength')
119
+ else:
120
+ raise TypeError('Expecting String, got %s' % type(value))
121
+
122
+
123
+ class StringProperty(Property):
124
+
125
+ type_name = 'String'
126
+
127
+ def __init__(self, verbose_name=None, name=None, default='',
128
+ required=False, validator=validate_string,
129
+ choices=None, unique=False):
130
+ Property.__init__(self, verbose_name, name, default, required,
131
+ validator, choices, unique)
132
+
133
+
134
+ class TextProperty(Property):
135
+
136
+ type_name = 'Text'
137
+
138
+ def __init__(self, verbose_name=None, name=None, default='',
139
+ required=False, validator=None, choices=None,
140
+ unique=False, max_length=None):
141
+ Property.__init__(self, verbose_name, name, default, required,
142
+ validator, choices, unique)
143
+ self.max_length = max_length
144
+
145
+ def validate(self, value):
146
+ value = super(TextProperty, self).validate(value)
147
+ if not isinstance(value, str) and not isinstance(value, unicode):
148
+ raise TypeError('Expecting Text, got %s' % type(value))
149
+ if self.max_length and len(value) > self.max_length:
150
+ raise ValueError('Length of value greater than maxlength %s' % self.max_length)
151
+
152
+
153
+ class PasswordProperty(StringProperty):
154
+ """
155
+
156
+ Hashed property whose original value can not be
157
+ retrieved, but still can be compared.
158
+
159
+ Works by storing a hash of the original value instead
160
+ of the original value. Once that's done all that
161
+ can be retrieved is the hash.
162
+
163
+ The comparison
164
+
165
+ obj.password == 'foo'
166
+
167
+ generates a hash of 'foo' and compares it to the
168
+ stored hash.
169
+
170
+ Underlying data type for hashing, storing, and comparing
171
+ is boto.utils.Password. The default hash function is
172
+ defined there ( currently sha512 in most cases, md5
173
+ where sha512 is not available )
174
+
175
+ It's unlikely you'll ever need to use a different hash
176
+ function, but if you do, you can control the behavior
177
+ in one of two ways:
178
+
179
+ 1) Specifying hashfunc in PasswordProperty constructor
180
+
181
+ import hashlib
182
+
183
+ class MyModel(model):
184
+ password = PasswordProperty(hashfunc=hashlib.sha224)
185
+
186
+ 2) Subclassing Password and PasswordProperty
187
+
188
+ class SHA224Password(Password):
189
+ hashfunc=hashlib.sha224
190
+
191
+ class SHA224PasswordProperty(PasswordProperty):
192
+ data_type=MyPassword
193
+ type_name="MyPassword"
194
+
195
+ class MyModel(Model):
196
+ password = SHA224PasswordProperty()
197
+
198
+ """
199
+ data_type = Password
200
+ type_name = 'Password'
201
+
202
+ def __init__(self, verbose_name=None, name=None, default='', required=False,
203
+ validator=None, choices=None, unique=False, hashfunc=None):
204
+
205
+ """
206
+ The hashfunc parameter overrides the default hashfunc in boto.utils.Password.
207
+
208
+ The remaining parameters are passed through to StringProperty.__init__"""
209
+
210
+ StringProperty.__init__(self, verbose_name, name, default, required,
211
+ validator, choices, unique)
212
+ self.hashfunc = hashfunc
213
+
214
+ def make_value_from_datastore(self, value):
215
+ p = self.data_type(value, hashfunc=self.hashfunc)
216
+ return p
217
+
218
+ def get_value_for_datastore(self, model_instance):
219
+ value = StringProperty.get_value_for_datastore(self, model_instance)
220
+ if value and len(value):
221
+ return str(value)
222
+ else:
223
+ return None
224
+
225
+ def __set__(self, obj, value):
226
+ if not isinstance(value, self.data_type):
227
+ p = self.data_type(hashfunc=self.hashfunc)
228
+ p.set(value)
229
+ value = p
230
+ Property.__set__(self, obj, value)
231
+
232
+ def __get__(self, obj, objtype):
233
+ return self.data_type(StringProperty.__get__(self, obj, objtype), hashfunc=self.hashfunc)
234
+
235
+ def validate(self, value):
236
+ value = Property.validate(self, value)
237
+ if isinstance(value, self.data_type):
238
+ if len(value) > 1024:
239
+ raise ValueError('Length of value greater than maxlength')
240
+ else:
241
+ raise TypeError('Expecting %s, got %s' % (type(self.data_type), type(value)))
242
+
243
+
244
+ class BlobProperty(Property):
245
+ data_type = Blob
246
+ type_name = "blob"
247
+
248
+ def __set__(self, obj, value):
249
+ if value != self.default_value():
250
+ if not isinstance(value, Blob):
251
+ oldb = self.__get__(obj, type(obj))
252
+ id = None
253
+ if oldb:
254
+ id = oldb.id
255
+ b = Blob(value=value, id=id)
256
+ value = b
257
+ Property.__set__(self, obj, value)
258
+
259
+
260
+ class S3KeyProperty(Property):
261
+
262
+ data_type = boto.s3.key.Key
263
+ type_name = 'S3Key'
264
+ validate_regex = "^s3:\/\/([^\/]*)\/(.*)$"
265
+
266
+ def __init__(self, verbose_name=None, name=None, default=None,
267
+ required=False, validator=None, choices=None, unique=False):
268
+ Property.__init__(self, verbose_name, name, default, required,
269
+ validator, choices, unique)
270
+
271
+ def validate(self, value):
272
+ value = super(S3KeyProperty, self).validate(value)
273
+ if value == self.default_value() or value == str(self.default_value()):
274
+ return self.default_value()
275
+ if isinstance(value, self.data_type):
276
+ return
277
+ match = re.match(self.validate_regex, value)
278
+ if match:
279
+ return
280
+ raise TypeError('Validation Error, expecting %s, got %s' % (self.data_type, type(value)))
281
+
282
+ def __get__(self, obj, objtype):
283
+ value = Property.__get__(self, obj, objtype)
284
+ if value:
285
+ if isinstance(value, self.data_type):
286
+ return value
287
+ match = re.match(self.validate_regex, value)
288
+ if match:
289
+ s3 = obj._manager.get_s3_connection()
290
+ bucket = s3.get_bucket(match.group(1), validate=False)
291
+ k = bucket.get_key(match.group(2))
292
+ if not k:
293
+ k = bucket.new_key(match.group(2))
294
+ k.set_contents_from_string("")
295
+ return k
296
+ else:
297
+ return value
298
+
299
+ def get_value_for_datastore(self, model_instance):
300
+ value = Property.get_value_for_datastore(self, model_instance)
301
+ if value:
302
+ return "s3://%s/%s" % (value.bucket.name, value.name)
303
+ else:
304
+ return None
305
+
306
+
307
+ class IntegerProperty(Property):
308
+
309
+ data_type = int
310
+ type_name = 'Integer'
311
+
312
+ def __init__(self, verbose_name=None, name=None, default=0, required=False,
313
+ validator=None, choices=None, unique=False, max=2147483647, min=-2147483648):
314
+ Property.__init__(self, verbose_name, name, default, required, validator, choices, unique)
315
+ self.max = max
316
+ self.min = min
317
+
318
+ def validate(self, value):
319
+ value = int(value)
320
+ value = Property.validate(self, value)
321
+ if value > self.max:
322
+ raise ValueError('Maximum value is %d' % self.max)
323
+ if value < self.min:
324
+ raise ValueError('Minimum value is %d' % self.min)
325
+ return value
326
+
327
+ def empty(self, value):
328
+ return value is None
329
+
330
+ def __set__(self, obj, value):
331
+ if value == "" or value == None:
332
+ value = 0
333
+ return Property.__set__(self, obj, value)
334
+
335
+
336
+ class LongProperty(Property):
337
+
338
+ data_type = long
339
+ type_name = 'Long'
340
+
341
+ def __init__(self, verbose_name=None, name=None, default=0, required=False,
342
+ validator=None, choices=None, unique=False):
343
+ Property.__init__(self, verbose_name, name, default, required, validator, choices, unique)
344
+
345
+ def validate(self, value):
346
+ value = long(value)
347
+ value = Property.validate(self, value)
348
+ min = -9223372036854775808
349
+ max = 9223372036854775807
350
+ if value > max:
351
+ raise ValueError('Maximum value is %d' % max)
352
+ if value < min:
353
+ raise ValueError('Minimum value is %d' % min)
354
+ return value
355
+
356
+ def empty(self, value):
357
+ return value is None
358
+
359
+
360
+ class BooleanProperty(Property):
361
+
362
+ data_type = bool
363
+ type_name = 'Boolean'
364
+
365
+ def __init__(self, verbose_name=None, name=None, default=False, required=False,
366
+ validator=None, choices=None, unique=False):
367
+ Property.__init__(self, verbose_name, name, default, required, validator, choices, unique)
368
+
369
+ def empty(self, value):
370
+ return value is None
371
+
372
+
373
+ class FloatProperty(Property):
374
+
375
+ data_type = float
376
+ type_name = 'Float'
377
+
378
+ def __init__(self, verbose_name=None, name=None, default=0.0, required=False,
379
+ validator=None, choices=None, unique=False):
380
+ Property.__init__(self, verbose_name, name, default, required, validator, choices, unique)
381
+
382
+ def validate(self, value):
383
+ value = float(value)
384
+ value = Property.validate(self, value)
385
+ return value
386
+
387
+ def empty(self, value):
388
+ return value is None
389
+
390
+
391
+ class DateTimeProperty(Property):
392
+ """This class handles both the datetime.datetime object
393
+ And the datetime.date objects. It can return either one,
394
+ depending on the value stored in the database"""
395
+
396
+ data_type = datetime.datetime
397
+ type_name = 'DateTime'
398
+
399
+ def __init__(self, verbose_name=None, auto_now=False, auto_now_add=False, name=None,
400
+ default=None, required=False, validator=None, choices=None, unique=False):
401
+ Property.__init__(self, verbose_name, name, default, required, validator, choices, unique)
402
+ self.auto_now = auto_now
403
+ self.auto_now_add = auto_now_add
404
+
405
+ def default_value(self):
406
+ if self.auto_now or self.auto_now_add:
407
+ return self.now()
408
+ return Property.default_value(self)
409
+
410
+ def validate(self, value):
411
+ if value == None:
412
+ return
413
+ if isinstance(value, datetime.date):
414
+ return value
415
+ return super(DateTimeProperty, self).validate(value)
416
+
417
+ def get_value_for_datastore(self, model_instance):
418
+ if self.auto_now:
419
+ setattr(model_instance, self.name, self.now())
420
+ return Property.get_value_for_datastore(self, model_instance)
421
+
422
+ def now(self):
423
+ return datetime.datetime.utcnow()
424
+
425
+
426
+ class DateProperty(Property):
427
+
428
+ data_type = datetime.date
429
+ type_name = 'Date'
430
+
431
+ def __init__(self, verbose_name=None, auto_now=False, auto_now_add=False, name=None,
432
+ default=None, required=False, validator=None, choices=None, unique=False):
433
+ Property.__init__(self, verbose_name, name, default, required, validator, choices, unique)
434
+ self.auto_now = auto_now
435
+ self.auto_now_add = auto_now_add
436
+
437
+ def default_value(self):
438
+ if self.auto_now or self.auto_now_add:
439
+ return self.now()
440
+ return Property.default_value(self)
441
+
442
+ def validate(self, value):
443
+ value = super(DateProperty, self).validate(value)
444
+ if value == None:
445
+ return
446
+ if not isinstance(value, self.data_type):
447
+ raise TypeError('Validation Error, expecting %s, got %s' % (self.data_type, type(value)))
448
+
449
+ def get_value_for_datastore(self, model_instance):
450
+ if self.auto_now:
451
+ setattr(model_instance, self.name, self.now())
452
+ val = Property.get_value_for_datastore(self, model_instance)
453
+ if isinstance(val, datetime.datetime):
454
+ val = val.date()
455
+ return val
456
+
457
+ def now(self):
458
+ return datetime.date.today()
459
+
460
+
461
+ class TimeProperty(Property):
462
+ data_type = datetime.time
463
+ type_name = 'Time'
464
+
465
+ def __init__(self, verbose_name=None, name=None,
466
+ default=None, required=False, validator=None, choices=None, unique=False):
467
+ Property.__init__(self, verbose_name, name, default, required, validator, choices, unique)
468
+
469
+ def validate(self, value):
470
+ value = super(TimeProperty, self).validate(value)
471
+ if value is None:
472
+ return
473
+ if not isinstance(value, self.data_type):
474
+ raise TypeError('Validation Error, expecting %s, got %s' % (self.data_type, type(value)))
475
+
476
+
477
+ class ReferenceProperty(Property):
478
+
479
+ data_type = Key
480
+ type_name = 'Reference'
481
+
482
+ def __init__(self, reference_class=None, collection_name=None,
483
+ verbose_name=None, name=None, default=None, required=False, validator=None, choices=None, unique=False):
484
+ Property.__init__(self, verbose_name, name, default, required, validator, choices, unique)
485
+ self.reference_class = reference_class
486
+ self.collection_name = collection_name
487
+
488
+ def __get__(self, obj, objtype):
489
+ if obj:
490
+ value = getattr(obj, self.slot_name)
491
+ if value == self.default_value():
492
+ return value
493
+ # If the value is still the UUID for the referenced object, we need to create
494
+ # the object now that is the attribute has actually been accessed. This lazy
495
+ # instantiation saves unnecessary roundtrips to SimpleDB
496
+ if isinstance(value, str) or isinstance(value, unicode):
497
+ value = self.reference_class(value)
498
+ setattr(obj, self.name, value)
499
+ return value
500
+
501
+ def __set__(self, obj, value):
502
+ """Don't allow this object to be associated to itself
503
+ This causes bad things to happen"""
504
+ if value != None and (obj.id == value or (hasattr(value, "id") and obj.id == value.id)):
505
+ raise ValueError("Can not associate an object with itself!")
506
+ return super(ReferenceProperty, self).__set__(obj, value)
507
+
508
+ def __property_config__(self, model_class, property_name):
509
+ Property.__property_config__(self, model_class, property_name)
510
+ if self.collection_name is None:
511
+ self.collection_name = '%s_%s_set' % (model_class.__name__.lower(), self.name)
512
+ if hasattr(self.reference_class, self.collection_name):
513
+ raise ValueError('duplicate property: %s' % self.collection_name)
514
+ setattr(self.reference_class, self.collection_name,
515
+ _ReverseReferenceProperty(model_class, property_name, self.collection_name))
516
+
517
+ def check_uuid(self, value):
518
+ # This does a bit of hand waving to "type check" the string
519
+ t = value.split('-')
520
+ if len(t) != 5:
521
+ raise ValueError
522
+
523
+ def check_instance(self, value):
524
+ try:
525
+ obj_lineage = value.get_lineage()
526
+ cls_lineage = self.reference_class.get_lineage()
527
+ if obj_lineage.startswith(cls_lineage):
528
+ return
529
+ raise TypeError('%s not instance of %s' % (obj_lineage, cls_lineage))
530
+ except:
531
+ raise ValueError('%s is not a Model' % value)
532
+
533
+ def validate(self, value):
534
+ if self.validator:
535
+ self.validator(value)
536
+ if self.required and value == None:
537
+ raise ValueError('%s is a required property' % self.name)
538
+ if value == self.default_value():
539
+ return
540
+ if not isinstance(value, str) and not isinstance(value, unicode):
541
+ self.check_instance(value)
542
+
543
+
544
+ class _ReverseReferenceProperty(Property):
545
+ data_type = Query
546
+ type_name = 'query'
547
+
548
+ def __init__(self, model, prop, name):
549
+ self.__model = model
550
+ self.__property = prop
551
+ self.collection_name = prop
552
+ self.name = name
553
+ self.item_type = model
554
+
555
+ def __get__(self, model_instance, model_class):
556
+ """Fetches collection of model instances of this collection property."""
557
+ if model_instance is not None:
558
+ query = Query(self.__model)
559
+ if isinstance(self.__property, list):
560
+ props = []
561
+ for prop in self.__property:
562
+ props.append("%s =" % prop)
563
+ return query.filter(props, model_instance)
564
+ else:
565
+ return query.filter(self.__property + ' =', model_instance)
566
+ else:
567
+ return self
568
+
569
+ def __set__(self, model_instance, value):
570
+ """Not possible to set a new collection."""
571
+ raise ValueError('Virtual property is read-only')
572
+
573
+
574
+ class CalculatedProperty(Property):
575
+
576
+ def __init__(self, verbose_name=None, name=None, default=None,
577
+ required=False, validator=None, choices=None,
578
+ calculated_type=int, unique=False, use_method=False):
579
+ Property.__init__(self, verbose_name, name, default, required,
580
+ validator, choices, unique)
581
+ self.calculated_type = calculated_type
582
+ self.use_method = use_method
583
+
584
+ def __get__(self, obj, objtype):
585
+ value = self.default_value()
586
+ if obj:
587
+ try:
588
+ value = getattr(obj, self.slot_name)
589
+ if self.use_method:
590
+ value = value()
591
+ except AttributeError:
592
+ pass
593
+ return value
594
+
595
+ def __set__(self, obj, value):
596
+ """Not possible to set a new AutoID."""
597
+ pass
598
+
599
+ def _set_direct(self, obj, value):
600
+ if not self.use_method:
601
+ setattr(obj, self.slot_name, value)
602
+
603
+ def get_value_for_datastore(self, model_instance):
604
+ if self.calculated_type in [str, int, bool]:
605
+ value = self.__get__(model_instance, model_instance.__class__)
606
+ return value
607
+ else:
608
+ return None
609
+
610
+
611
+ class ListProperty(Property):
612
+
613
+ data_type = list
614
+ type_name = 'List'
615
+
616
+ def __init__(self, item_type, verbose_name=None, name=None, default=None, **kwds):
617
+ if default is None:
618
+ default = []
619
+ self.item_type = item_type
620
+ Property.__init__(self, verbose_name, name, default=default, required=True, **kwds)
621
+
622
+ def validate(self, value):
623
+ if self.validator:
624
+ self.validator(value)
625
+ if value is not None:
626
+ if not isinstance(value, list):
627
+ value = [value]
628
+
629
+ if self.item_type in (int, long):
630
+ item_type = (int, long)
631
+ elif self.item_type in (str, unicode):
632
+ item_type = (str, unicode)
633
+ else:
634
+ item_type = self.item_type
635
+
636
+ for item in value:
637
+ if not isinstance(item, item_type):
638
+ if item_type == (int, long):
639
+ raise ValueError('Items in the %s list must all be integers.' % self.name)
640
+ else:
641
+ raise ValueError('Items in the %s list must all be %s instances' %
642
+ (self.name, self.item_type.__name__))
643
+ return value
644
+
645
+ def empty(self, value):
646
+ return value is None
647
+
648
+ def default_value(self):
649
+ return list(super(ListProperty, self).default_value())
650
+
651
+ def __set__(self, obj, value):
652
+ """Override the set method to allow them to set the property to an instance of the item_type instead of requiring a list to be passed in"""
653
+ if self.item_type in (int, long):
654
+ item_type = (int, long)
655
+ elif self.item_type in (str, unicode):
656
+ item_type = (str, unicode)
657
+ else:
658
+ item_type = self.item_type
659
+ if isinstance(value, item_type):
660
+ value = [value]
661
+ elif value == None: # Override to allow them to set this to "None" to remove everything
662
+ value = []
663
+ return super(ListProperty, self).__set__(obj, value)
664
+
665
+
666
+ class MapProperty(Property):
667
+
668
+ data_type = dict
669
+ type_name = 'Map'
670
+
671
+ def __init__(self, item_type=str, verbose_name=None, name=None, default=None, **kwds):
672
+ if default is None:
673
+ default = {}
674
+ self.item_type = item_type
675
+ Property.__init__(self, verbose_name, name, default=default, required=True, **kwds)
676
+
677
+ def validate(self, value):
678
+ value = super(MapProperty, self).validate(value)
679
+ if value is not None:
680
+ if not isinstance(value, dict):
681
+ raise ValueError('Value must of type dict')
682
+
683
+ if self.item_type in (int, long):
684
+ item_type = (int, long)
685
+ elif self.item_type in (str, unicode):
686
+ item_type = (str, unicode)
687
+ else:
688
+ item_type = self.item_type
689
+
690
+ for key in value:
691
+ if not isinstance(value[key], item_type):
692
+ if item_type == (int, long):
693
+ raise ValueError('Values in the %s Map must all be integers.' % self.name)
694
+ else:
695
+ raise ValueError('Values in the %s Map must all be %s instances' %
696
+ (self.name, self.item_type.__name__))
697
+ return value
698
+
699
+ def empty(self, value):
700
+ return value is None
701
+
702
+ def default_value(self):
703
+ return {}