)]}'
{"requirements.txt":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1d6b569da79800b833c6ca5abaff5666bd8d2f22","unresolved":false,"context_lines":[{"line_number":1,"context_line":"futures\u003e\u003d2.1.3"},{"line_number":2,"context_line":"requests\u003e\u003d1.1"},{"line_number":3,"context_line":"simplejson\u003e\u003d2.0.9"},{"line_number":4,"context_line":"six\u003e\u003d1.5.2"}],"source_content_type":"text/plain","patch_set":27,"id":"1abeadc6_bb44941b","line":1,"updated":"2014-08-21 19:32:39.000000000","message":"something about this requirement was throwing off my development installation on precise.  I was able to \"import futures\" but and pip freeze showed 2.1.6 installed - but if I tried to \"pkg_resources.get_distribution(\u0027futures\u0027)\" it would raise DistributionNotFound.\n\nI\u0027d get a similar error if I tried to run \u0027swift\" from the command line.","commit_id":"ad758c078a101f7f07fe33d2fc1bcb7bf0ed4168"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"73925813cca28d222a8707d66d3ee28fca4f9582","unresolved":false,"context_lines":[{"line_number":1,"context_line":"futures\u003e\u003d2.1.3"},{"line_number":2,"context_line":"requests\u003e\u003d1.1"},{"line_number":3,"context_line":"simplejson\u003e\u003d2.0.9"},{"line_number":4,"context_line":"six\u003e\u003d1.5.2"}],"source_content_type":"text/plain","patch_set":27,"id":"1abeadc6_3b4964b7","line":1,"in_reply_to":"1abeadc6_bb44941b","updated":"2014-08-21 19:56:25.000000000","message":"That\u0027s really odd, I\u0027ve installed futures (and this version of swift) across a lot of platforms and never had an issue. \n\n\"pkg_resources.get_distribution(\u0027futures\u0027)\" returns the following on my system:\n\nfutures 2.1.6 (/\u003c\u003cpath_to_venv\u003e\u003e/lib/python2.7/site-packages)","commit_id":"ad758c078a101f7f07fe33d2fc1bcb7bf0ed4168"}],"swiftclient/command_helpers.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"060289a9449bdb3da54c6e8867c9dc2a13871fc2","unresolved":false,"context_lines":[{"line_number":176,"context_line":"            meta_items.append((meta_key, value))"},{"line_number":177,"context_line":"        elif key not in exclude_headers:"},{"line_number":178,"context_line":"            other_items.append((key.title(), value))"},{"line_number":179,"context_line":"    return meta_items + other_items"}],"source_content_type":"text/x-python","patch_set":26,"id":"1abeadc6_c5c8d824","line":179,"updated":"2014-08-20 07:12:40.000000000","message":"This is a nitpic, so wont -1 for this, but if someone decides to use this helper method and wants to exclude certain meta items, then they can\u0027t as headers starting with the meta_prefix are never checked against the exclude_headers. \n\nMaybe that situation will never arise as the meta_headers are suppose to be user defined.. but bugs me a little :)","commit_id":"536da4771f443d31bfd6ff6742e4de22980f2a41"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"31177073c6d03dc0d042a944f9fdb64d15e5e2b7","unresolved":false,"context_lines":[{"line_number":176,"context_line":"            meta_items.append((meta_key, value))"},{"line_number":177,"context_line":"        elif key not in exclude_headers:"},{"line_number":178,"context_line":"            other_items.append((key.title(), value))"},{"line_number":179,"context_line":"    return meta_items + other_items"}],"source_content_type":"text/x-python","patch_set":26,"id":"1abeadc6_a01caac2","line":179,"in_reply_to":"1abeadc6_c5c8d824","updated":"2014-08-20 07:38:58.000000000","message":"That\u0027s a fair comment. I actually moved this code into a helper method after it was added as a recent patch to the old threadManager. There seems no good reason not to allow filtering of headers starting with the meta prefix.","commit_id":"536da4771f443d31bfd6ff6742e4de22980f2a41"}],"swiftclient/multithreading.py":[{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"20dba0b05c17070cb647d9c96acc62ddff0f65e8","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        self.error_print_pool \u003d ThreadPoolExecutor(max_workers\u003d1)"},{"line_number":61,"context_line":"        self.error_count \u003d 0"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def __enter__(self):"},{"line_number":64,"context_line":"        return self"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    def __exit__(self, exc_type, exc_value, traceback):"}],"source_content_type":"text/x-python","patch_set":24,"id":"7ac7a964_3412d3b1","line":63,"updated":"2014-08-16 04:23:11.000000000","message":"Please pardon my ignorance, but is this okay to drop the forwarding of __enter__? I looked at the cpython source and the _base.Executor has an empty __enter__ method, so this certainly works, but is it correct theoretically?\n\nSame question about MultiThreadingManager.","commit_id":"77770c1e0b6a3cb22b218dade302869b8f5b44ce"}],"swiftclient/service.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"9aef950b856f846e78ac09112e237bd7812553a2","unresolved":false,"context_lines":[{"line_number":1028,"context_line":"        \"\"\""},{"line_number":1029,"context_line":"        Upload a list of objects to a given container."},{"line_number":1030,"context_line":""},{"line_number":1031,"context_line":"        :param container: The container to make the uploads into."},{"line_number":1032,"context_line":"        :param objects: A list of tuples containing a source for the created"},{"line_number":1033,"context_line":"                        object, an object name, and an options dict (can be"},{"line_number":1034,"context_line":"                        None) to override the options for that individual"}],"source_content_type":"text/x-python","patch_set":24,"id":"baada198_720443c5","line":1031,"updated":"2014-08-07 11:57:29.000000000","message":"s/make/put/ or \u0027The container that will hold the uploads\u0027","commit_id":"77770c1e0b6a3cb22b218dade302869b8f5b44ce"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"9aef950b856f846e78ac09112e237bd7812553a2","unresolved":false,"context_lines":[{"line_number":1151,"context_line":"                        object_options, path\u003ds"},{"line_number":1152,"context_line":"                    )"},{"line_number":1153,"context_line":"                    file_jobs[dir_future] \u003d details"},{"line_number":1154,"context_line":"                else:"},{"line_number":1155,"context_line":"                    file_future \u003d self.thread_manager.object_uu_pool.submit("},{"line_number":1156,"context_line":"                        self._upload_object_job, container, s, o,"},{"line_number":1157,"context_line":"                        object_options, results_queue\u003drq"}],"source_content_type":"text/x-python","patch_set":24,"id":"baada198_d23a6f34","line":1154,"updated":"2014-08-07 11:57:29.000000000","message":"isdir will only return True if its a directory (obviously) if the path doesn\u0027t exist it will still return False. So do we want to add  a check to make sure the file exists? or just let swift handle the lack of file?\n\nI\u0027m OK either way really, just pointing it out as we might want to quick fail rather then wait for the thread to fail later.\n\nOR if the file doesn\u0027t exist should it be treated as a None? i.e the else below.","commit_id":"77770c1e0b6a3cb22b218dade302869b8f5b44ce"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a0643ed048534e727bfaa110bb92e2afc8b231a5","unresolved":false,"context_lines":[{"line_number":1151,"context_line":"                        object_options, path\u003ds"},{"line_number":1152,"context_line":"                    )"},{"line_number":1153,"context_line":"                    file_jobs[dir_future] \u003d details"},{"line_number":1154,"context_line":"                else:"},{"line_number":1155,"context_line":"                    file_future \u003d self.thread_manager.object_uu_pool.submit("},{"line_number":1156,"context_line":"                        self._upload_object_job, container, s, o,"},{"line_number":1157,"context_line":"                        object_options, results_queue\u003drq"}],"source_content_type":"text/x-python","patch_set":24,"id":"baada198_fa11e85c","line":1154,"in_reply_to":"baada198_5f9ba672","updated":"2014-08-11 13:47:08.000000000","message":"Sorry, got the wrong end of the stick about \"check to make sure the file exists\". I do prefer the idea of failing sooner, rather than tying up a thread (however briefly) with a detectable failure. Because we already have access to the queue that will be used for the results of the uploads there seems no reason not to just try to stat the path, catch potential errors, and put a failed result on there in the case of an error.\n\nI\u0027ll make this change too :)","commit_id":"77770c1e0b6a3cb22b218dade302869b8f5b44ce"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"eb5ae69a361fbfc93be5a00658380e09de694309","unresolved":false,"context_lines":[{"line_number":1151,"context_line":"                        object_options, path\u003ds"},{"line_number":1152,"context_line":"                    )"},{"line_number":1153,"context_line":"                    file_jobs[dir_future] \u003d details"},{"line_number":1154,"context_line":"                else:"},{"line_number":1155,"context_line":"                    file_future \u003d self.thread_manager.object_uu_pool.submit("},{"line_number":1156,"context_line":"                        self._upload_object_job, container, s, o,"},{"line_number":1157,"context_line":"                        object_options, results_queue\u003drq"}],"source_content_type":"text/x-python","patch_set":24,"id":"baada198_5f9ba672","line":1154,"in_reply_to":"baada198_d019807b","updated":"2014-08-08 07:56:43.000000000","message":"Yeah arguably it is correct and if we want later code to detect and error that is fine. Just pointing it out cause I noticed :)\n\nAnd yeah I agree we don\u0027t want to be counter-intuitive.\n \nIf the file doesn\u0027t exist I didn\u0027t want to ignore it, still error/add to results, I just wondered if we wanted to error earlier.","commit_id":"77770c1e0b6a3cb22b218dade302869b8f5b44ce"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"1cac943ed2c9a6136e8cebd730cf094898e97c57","unresolved":false,"context_lines":[{"line_number":1151,"context_line":"                        object_options, path\u003ds"},{"line_number":1152,"context_line":"                    )"},{"line_number":1153,"context_line":"                    file_jobs[dir_future] \u003d details"},{"line_number":1154,"context_line":"                else:"},{"line_number":1155,"context_line":"                    file_future \u003d self.thread_manager.object_uu_pool.submit("},{"line_number":1156,"context_line":"                        self._upload_object_job, container, s, o,"},{"line_number":1157,"context_line":"                        object_options, results_queue\u003drq"}],"source_content_type":"text/x-python","patch_set":24,"id":"baada198_d019807b","line":1154,"in_reply_to":"baada198_d23a6f34","updated":"2014-08-07 15:15:13.000000000","message":"I see your point, but I think the current behaviour is (arguably) correct.\n\nIf a string is passed as an argument to upload, then I believe the intention is that the string should be interpreted as a path to an object to upload (or a dir_marker to create if desired). Checking if a file exists and either ignoring that source or defaulting to a different action could have the following unexpected behaviours in the case that the user generates a bad input list:\n\n - If the file doesn\u0027t exist and we ignore it there will be no feedback about that source. I would prefer that a result was returned for every element of the input list.\n\n - If the file doesn\u0027t exist and we default to making an empty object we\u0027ll get success results without uploading anything which seems counter-intuitive.\n\nDoes this seem reasonable?","commit_id":"77770c1e0b6a3cb22b218dade302869b8f5b44ce"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"9aef950b856f846e78ac09112e237bd7812553a2","unresolved":false,"context_lines":[{"line_number":1268,"context_line":"                mt \u003d headers.get(\u0027x-object-meta-mtime\u0027)"},{"line_number":1269,"context_line":"                if ct.split(\u0027;\u0027, 1)[0] \u003d\u003d \u0027text/directory\u0027 and \\"},{"line_number":1270,"context_line":"                        cl \u003d\u003d 0 and \\"},{"line_number":1271,"context_line":"                        et \u003d\u003d \u0027d41d8cd98f00b204e9800998ecf8427e\u0027 and \\"},{"line_number":1272,"context_line":"                        mt \u003d\u003d put_headers[\u0027x-object-meta-mtime\u0027]:"},{"line_number":1273,"context_line":"                    res[\u0027success\u0027] \u003d True"},{"line_number":1274,"context_line":"                    return res"}],"source_content_type":"text/x-python","patch_set":24,"id":"baada198_ed5eb813","line":1271,"updated":"2014-08-07 11:57:29.000000000","message":"I now know \u0027d41d8cd98f00b204e9800998ecf8427e\u0027 is the md5 of an emply string, I assumed it was but had to double check, but to make it easier to read can we put it in a constant or even as a variable in the method? Just to make the code easier to read for new devs. \n\nMaybe something like:\n\n  _empty_string_etag \u003d \u0027d41d8cd98f00b204e9800998ecf8427e\u0027","commit_id":"77770c1e0b6a3cb22b218dade302869b8f5b44ce"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"9aef950b856f846e78ac09112e237bd7812553a2","unresolved":false,"context_lines":[{"line_number":1619,"context_line":"        Delete operations on an account, optional container and optional list"},{"line_number":1620,"context_line":"        of objects."},{"line_number":1621,"context_line":""},{"line_number":1622,"context_line":"        :param container: The container to delete from."},{"line_number":1623,"context_line":"        :param objects: The list of objects to delete."},{"line_number":1624,"context_line":"        :param options: A dictionary containing options to override the global"},{"line_number":1625,"context_line":"                        options specified during the service object creation."}],"source_content_type":"text/x-python","patch_set":24,"id":"baada198_c83c82c3","line":1622,"updated":"2014-08-07 11:57:29.000000000","message":"The container to delete or delete from","commit_id":"77770c1e0b6a3cb22b218dade302869b8f5b44ce"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"dc2063a061935e4e11025423a258641418d78e7a","unresolved":false,"context_lines":[{"line_number":18,"context_line":"from hashlib import md5"},{"line_number":19,"context_line":"from os import environ, makedirs, stat, utime"},{"line_number":20,"context_line":"from os.path import basename, dirname, getmtime, getsize, isdir, join, \\"},{"line_number":21,"context_line":"    sep as os_path_sep"},{"line_number":22,"context_line":"from random import shuffle"},{"line_number":23,"context_line":"from time import time"},{"line_number":24,"context_line":"from threading import Thread"}],"source_content_type":"text/x-python","patch_set":25,"id":"1abeadc6_c6e4993d","line":21,"updated":"2014-08-19 06:10:08.000000000","message":"Below (line 38) you use the \"from module import (\" syntax which allows you to wrap nicely. Whereas on this line you are using the older \u0027\"\\\" syntax. \n\nIf the line is going wrap, lets be consistent with a common usage in a file. I personally prefer line 38 :)","commit_id":"8c4104ae8f4626d82330c7a638123e389551263f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b07e1fa7e4145da4e21ec16457ce6c723a66de48","unresolved":false,"context_lines":[{"line_number":781,"context_line":"            \u0027error\u0027: error,"},{"line_number":782,"context_line":"        }"},{"line_number":783,"context_line":"        result_queue.put(res)"},{"line_number":784,"context_line":"        result_queue.put(None)"},{"line_number":785,"context_line":""},{"line_number":786,"context_line":"    # Download related methods"},{"line_number":787,"context_line":"    #"}],"source_content_type":"text/x-python","patch_set":27,"id":"1abeadc6_6bcf8956","line":784,"updated":"2014-08-21 23:04:58.000000000","message":"this is only for the error case right?  the happy path always exits from if not items?","commit_id":"ad758c078a101f7f07fe33d2fc1bcb7bf0ed4168"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"079de5264bf62d2c332ac181ecef563e5cdd0742","unresolved":false,"context_lines":[{"line_number":781,"context_line":"            \u0027error\u0027: error,"},{"line_number":782,"context_line":"        }"},{"line_number":783,"context_line":"        result_queue.put(res)"},{"line_number":784,"context_line":"        result_queue.put(None)"},{"line_number":785,"context_line":""},{"line_number":786,"context_line":"    # Download related methods"},{"line_number":787,"context_line":"    #"}],"source_content_type":"text/x-python","patch_set":27,"id":"1abeadc6_dabccabd","line":784,"in_reply_to":"1abeadc6_6bcf8956","updated":"2014-08-22 15:42:57.000000000","message":"Yes that\u0027s correct, this is only used for the error case.","commit_id":"ad758c078a101f7f07fe33d2fc1bcb7bf0ed4168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b07e1fa7e4145da4e21ec16457ce6c723a66de48","unresolved":false,"context_lines":[{"line_number":791,"context_line":"        of objects."},{"line_number":792,"context_line":""},{"line_number":793,"context_line":"        :param container: The container to download from."},{"line_number":794,"context_line":"        :param options: A dictionary containing options to override the global"},{"line_number":795,"context_line":"                        options specified during the service object creation."},{"line_number":796,"context_line":""},{"line_number":797,"context_line":"                            {"}],"source_content_type":"text/x-python","patch_set":27,"id":"1abeadc6_4bfbad78","line":794,"updated":"2014-08-21 23:04:58.000000000","message":"param objects: is a list of strings; yes?","commit_id":"ad758c078a101f7f07fe33d2fc1bcb7bf0ed4168"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"079de5264bf62d2c332ac181ecef563e5cdd0742","unresolved":false,"context_lines":[{"line_number":791,"context_line":"        of objects."},{"line_number":792,"context_line":""},{"line_number":793,"context_line":"        :param container: The container to download from."},{"line_number":794,"context_line":"        :param options: A dictionary containing options to override the global"},{"line_number":795,"context_line":"                        options specified during the service object creation."},{"line_number":796,"context_line":""},{"line_number":797,"context_line":"                            {"}],"source_content_type":"text/x-python","patch_set":27,"id":"1abeadc6_1ab3a2e9","line":794,"in_reply_to":"1abeadc6_4bfbad78","updated":"2014-08-22 15:42:57.000000000","message":"Good point, I\u0027ll add that in :)","commit_id":"ad758c078a101f7f07fe33d2fc1bcb7bf0ed4168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b07e1fa7e4145da4e21ec16457ce6c723a66de48","unresolved":false,"context_lines":[{"line_number":1044,"context_line":"                        None) to override the options for that individual"},{"line_number":1045,"context_line":"                        upload operation."},{"line_number":1046,"context_line":""},{"line_number":1047,"context_line":"                            [(source, object, options), ...]"},{"line_number":1048,"context_line":""},{"line_number":1049,"context_line":"                        The options dict is as described below."},{"line_number":1050,"context_line":""}],"source_content_type":"text/x-python","patch_set":27,"id":"1abeadc6_0b8375cc","line":1047,"updated":"2014-08-21 23:04:58.000000000","message":"don\u0027t love it.\n\nThese fixed length tuples are hell on evolving the API of the class. Very difficult/clunky to expand later; although maybe we can cram most everything we might need into options - I really do wonder if in the end we\u0027d be happier with a list of dicts, or even a list of \"SwiftObject\" instances or some other struct like thing.\n\nI also got really strange results when I passed in [(\u0027/some/file/on/disk\u0027, \u0027\u0027, {})] to the tune of a container PUT :\\","commit_id":"ad758c078a101f7f07fe33d2fc1bcb7bf0ed4168"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"079de5264bf62d2c332ac181ecef563e5cdd0742","unresolved":false,"context_lines":[{"line_number":1044,"context_line":"                        None) to override the options for that individual"},{"line_number":1045,"context_line":"                        upload operation."},{"line_number":1046,"context_line":""},{"line_number":1047,"context_line":"                            [(source, object, options), ...]"},{"line_number":1048,"context_line":""},{"line_number":1049,"context_line":"                        The options dict is as described below."},{"line_number":1050,"context_line":""}],"source_content_type":"text/x-python","patch_set":27,"id":"1abeadc6_d57add86","line":1047,"in_reply_to":"1abeadc6_0b8375cc","updated":"2014-08-22 15:42:57.000000000","message":"I\u0027m working on a class based solution so that we supply just a list of strings for the basic case. I think I see how the container PUT happened (the name parameter in the low level client library resolved to False, but it\u0027s quite happy to allow that, it just expects the given url to contain details of the expected object name).\n\nThe new SwiftUploadObject/SwiftPostObject code will make this case impossible.","commit_id":"ad758c078a101f7f07fe33d2fc1bcb7bf0ed4168"}]}
