)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e4daddb9f0714cdd295cf969cf1bb822fbfe9c9e","unresolved":false,"context_lines":[{"line_number":11,"context_line":"Once we started tinkering with the sharder, it all snowballed to"},{"line_number":12,"context_line":"include the rest of the container services."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Beware, this does affect some of Python 2 code."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"About killing the stray \"from __future__ import unicode_literals\":"},{"line_number":17,"context_line":"we do not do it in general. The specific problem it caused was"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":17,"id":"9fdfeff1_a6e4ad0f","line":14,"updated":"2019-02-20 18:22:21.000000000","message":"Is this still true? FWIW, I can (on py2) run the previous revision\u0027s test/ with this revisions swift/ and vice-versa. Seems like a really good sign!","commit_id":"0cd331428780fadef53101ed770a6d6f37889cb6"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"88f54a1bab007cf1bc903121e35864b67adba109","unresolved":false,"context_lines":[{"line_number":11,"context_line":"Once we started tinkering with the sharder, it all snowballed to"},{"line_number":12,"context_line":"include the rest of the container services."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Beware, this does affect some of Python 2 code."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"About killing the stray \"from __future__ import unicode_literals\":"},{"line_number":17,"context_line":"we do not do it in general. The specific problem it caused was"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":17,"id":"9fdfeff1_6933f6f7","line":14,"in_reply_to":"9fdfeff1_a6e4ad0f","updated":"2019-02-20 19:03:37.000000000","message":"Common code is even more affected with the squash of your follow-up, even if it\u0027s mostly trivial. Here\u0027s a list of changes visible in py2:\n- defaults manage_shard_ranges.py (trivial)\n- async_check in recon.py (trivial)\n- not checking types anymore in db.py\n- except StopIteration in class Spliterator in utils.py\n- ShardRange changes such as letting empty u\u0027\u0027 in, rocket surgery of _encode() (I have a feeling that one can be proven to affect py3 only, but textually it rehashes py2 code)\n- Making explicit identities where py2 hashed implicitly before is the same - should be fine, but needs a review\n- Non-comparable measures, such as setting sync id to -1\n- adding conn.rollback()\n- keys for sort() and sorted()\nBaiscally like that. They should be safe on py2, but it\u0027s not like most changes where everything is protected by six.PY3.","commit_id":"0cd331428780fadef53101ed770a6d6f37889cb6"}],"swift/cli/info.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":308,"context_line":"        for srange in info[\u0027shard_ranges\u0027]:"},{"line_number":309,"context_line":"            srange \u003d dict(srange, state_text\u003dsrange.state_text)"},{"line_number":310,"context_line":"            print(\u0027  Name: %(name)s\u0027 % srange)"},{"line_number":311,"context_line":"            print(\u0027    lower: %(lower)s, upper: %(upper)s\u0027 % srange)"},{"line_number":312,"context_line":"            print(\u0027    Object Count: %(object_count)d, Bytes Used: \u0027"},{"line_number":313,"context_line":"                  \u0027%(bytes_used)d, State: %(state_text)s (%(state)d)\u0027"},{"line_number":314,"context_line":"                  % srange)"}],"source_content_type":"text/x-python","patch_set":11,"id":"bfdaf3ff_68176b53","line":311,"updated":"2019-01-30 21:15:57.000000000","message":"FWIW, I think the %r was because shard range boundaries come from object names, which may include things like trailing spaces, newlines, control characters, and other things that could lead to surprises.","commit_id":"047aeb7797b0e24dbe33338295731c2250feae7d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":308,"context_line":"        for srange in info[\u0027shard_ranges\u0027]:"},{"line_number":309,"context_line":"            srange \u003d dict(srange, state_text\u003dsrange.state_text)"},{"line_number":310,"context_line":"            print(\u0027  Name: %(name)s\u0027 % srange)"},{"line_number":311,"context_line":"            print(\u0027    lower: %(lower)s, upper: %(upper)s\u0027 % srange)"},{"line_number":312,"context_line":"            print(\u0027    Object Count: %(object_count)d, Bytes Used: \u0027"},{"line_number":313,"context_line":"                  \u0027%(bytes_used)d, State: %(state_text)s (%(state)d)\u0027"},{"line_number":314,"context_line":"                  % srange)"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_9da5aba4","line":311,"updated":"2019-01-30 21:15:57.000000000","message":"I\u0027m a little worried about losing some clarity when upper or lower include some whitespace at the start or end... or include a newline *anywhere*...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":308,"context_line":"        for srange in info[\u0027shard_ranges\u0027]:"},{"line_number":309,"context_line":"            srange \u003d dict(srange, state_text\u003dsrange.state_text)"},{"line_number":310,"context_line":"            print(\u0027  Name: %(name)s\u0027 % srange)"},{"line_number":311,"context_line":"            print(\u0027    lower: %(lower)s, upper: %(upper)s\u0027 % srange)"},{"line_number":312,"context_line":"            print(\u0027    Object Count: %(object_count)d, Bytes Used: \u0027"},{"line_number":313,"context_line":"                  \u0027%(bytes_used)d, State: %(state_text)s (%(state)d)\u0027"},{"line_number":314,"context_line":"                  % srange)"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_a67980c8","line":311,"in_reply_to":"9fdfeff1_9da5aba4","updated":"2019-01-31 03:02:13.000000000","message":"Done","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"}],"swift/cli/manage_shard_ranges.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":171,"context_line":""},{"line_number":172,"context_line":"def _load_and_validate_shard_data(args):"},{"line_number":173,"context_line":"    try:"},{"line_number":174,"context_line":"        with open(args.input, \u0027r\u0027) as fd:"},{"line_number":175,"context_line":"            try:"},{"line_number":176,"context_line":"                data \u003d json.load(fd)"},{"line_number":177,"context_line":"                if not isinstance(data, list):"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_1dbbfbc4","line":174,"updated":"2019-01-30 21:15:57.000000000","message":"This isn\u0027t strictly necessary since https://github.com/openstack/swift/commit/c112203 landed, right?\n\n*shrug* Either way.","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":171,"context_line":""},{"line_number":172,"context_line":"def _load_and_validate_shard_data(args):"},{"line_number":173,"context_line":"    try:"},{"line_number":174,"context_line":"        with open(args.input, \u0027r\u0027) as fd:"},{"line_number":175,"context_line":"            try:"},{"line_number":176,"context_line":"                data \u003d json.load(fd)"},{"line_number":177,"context_line":"                if not isinstance(data, list):"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_313aa898","line":174,"in_reply_to":"9fdfeff1_1dbbfbc4","updated":"2019-01-31 03:02:13.000000000","message":"Although it is now unnecessary, don\u0027t you think it\u0027s \"more correct\" this way?","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":335,"context_line":"        broker, shard_data, args.shards_account_prefix)"},{"line_number":336,"context_line":"    _check_shard_ranges(own_shard_range, shard_ranges)"},{"line_number":337,"context_line":""},{"line_number":338,"context_line":"    if args.verbose:"},{"line_number":339,"context_line":"        print(\u0027New shard ranges to be injected:\u0027)"},{"line_number":340,"context_line":"        print(json.dumps([dict(sr) for sr in shard_ranges],"},{"line_number":341,"context_line":"                         sort_keys\u003dTrue, indent\u003d2))"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_bdce6f57","line":338,"updated":"2019-01-30 21:15:57.000000000","message":"?\n\nDid action\u003d\u0027count\u0027 change behaviors in py3?\n\nOTOH, I guess we never actually make a distinction between -v and -vv...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":335,"context_line":"        broker, shard_data, args.shards_account_prefix)"},{"line_number":336,"context_line":"    _check_shard_ranges(own_shard_range, shard_ranges)"},{"line_number":337,"context_line":""},{"line_number":338,"context_line":"    if args.verbose:"},{"line_number":339,"context_line":"        print(\u0027New shard ranges to be injected:\u0027)"},{"line_number":340,"context_line":"        print(json.dumps([dict(sr) for sr in shard_ranges],"},{"line_number":341,"context_line":"                         sort_keys\u003dTrue, indent\u003d2))"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_51664cc3","line":338,"in_reply_to":"9fdfeff1_bdce6f57","updated":"2019-01-31 03:02:13.000000000","message":"You cannot compare None and 0 in py3. This is what parser gives us if -v is not set. I don\u0027t think it\u0027s a change in the parser, but in py2 None was almost like integer \"minus infinity\" value.","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"}],"swift/common/utils.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":4745,"context_line":""},{"line_number":4746,"context_line":"    @name.setter"},{"line_number":4747,"context_line":"    def name(self, path):"},{"line_number":4748,"context_line":"        path \u003d self._encode(path)"},{"line_number":4749,"context_line":"        if not path or len(path.split(\u0027/\u0027)) !\u003d 2 or not all(path.split(\u0027/\u0027)):"},{"line_number":4750,"context_line":"            raise ValueError("},{"line_number":4751,"context_line":"                \"Name must be of the form \u0027\u003caccount\u003e/\u003ccontainer\u003e\u0027, got %r\" %"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_7d1b27c9","side":"PARENT","line":4748,"updated":"2019-01-30 21:15:57.000000000","message":"So previously on py2, when setting\n\n shard_range.name \u003d u\u0027account/container\u0027\n\nwe\u0027d ensure self.account and self.container were native strings... but now they\u0027ll still be unicode? Hmm...","commit_id":"700fcc735336a904d19554da053fb77209f7073e"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":4745,"context_line":""},{"line_number":4746,"context_line":"    @name.setter"},{"line_number":4747,"context_line":"    def name(self, path):"},{"line_number":4748,"context_line":"        path \u003d self._encode(path)"},{"line_number":4749,"context_line":"        if not path or len(path.split(\u0027/\u0027)) !\u003d 2 or not all(path.split(\u0027/\u0027)):"},{"line_number":4750,"context_line":"            raise ValueError("},{"line_number":4751,"context_line":"                \"Name must be of the form \u0027\u003caccount\u003e/\u003ccontainer\u003e\u0027, got %r\" %"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_acc87fa5","side":"PARENT","line":4748,"in_reply_to":"9fdfeff1_7d1b27c9","updated":"2019-01-31 03:02:13.000000000","message":"Okay, fine. But the existing code had a .name property that returned something other than was set. Look at the getter - it does not de-convert. I thought it was much too difficult to reason about. The name is still a native string, but there\u0027s no enforcement anymore.\n\nHow about we add a couple of isinstance() that rejects non-native strings with TypeError?","commit_id":"700fcc735336a904d19554da053fb77209f7073e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":4693,"context_line":"    def _encode_bound(self, bound):"},{"line_number":4694,"context_line":"        if isinstance(bound, ShardRange.OuterBound):"},{"line_number":4695,"context_line":"            return bound"},{"line_number":4696,"context_line":"        if not (isinstance(bound, six.string_types) or"},{"line_number":4697,"context_line":"                isinstance(bound, six.binary_type)):"},{"line_number":4698,"context_line":"            raise TypeError(\u0027must be a string type\u0027)"},{"line_number":4699,"context_line":"        return self._encode(bound)"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_3d311f5b","line":4696,"range":{"start_line":4696,"start_character":38,"end_line":4696,"end_character":50},"updated":"2019-01-30 21:15:57.000000000","message":"I wonder if this should get tightened to six.text_type... it just seems kinda weird that depending on Python version, this check implies the next one...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":4693,"context_line":"    def _encode_bound(self, bound):"},{"line_number":4694,"context_line":"        if isinstance(bound, ShardRange.OuterBound):"},{"line_number":4695,"context_line":"            return bound"},{"line_number":4696,"context_line":"        if not (isinstance(bound, six.string_types) or"},{"line_number":4697,"context_line":"                isinstance(bound, six.binary_type)):"},{"line_number":4698,"context_line":"            raise TypeError(\u0027must be a string type\u0027)"},{"line_number":4699,"context_line":"        return self._encode(bound)"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_31caa81a","line":4696,"range":{"start_line":4696,"start_character":38,"end_line":4696,"end_character":50},"in_reply_to":"9fdfeff1_3d311f5b","updated":"2019-01-31 03:02:13.000000000","message":"Done","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":4819,"context_line":"        if value in (None, u\u0027\u0027, b\u0027\u0027):"},{"line_number":4820,"context_line":"            value \u003d ShardRange.MAX"},{"line_number":4821,"context_line":"        try:"},{"line_number":4822,"context_line":"            value \u003d self._encode_bound(value)"},{"line_number":4823,"context_line":"        except TypeError as err:"},{"line_number":4824,"context_line":"            raise TypeError(\u0027upper %s\u0027 % err)"},{"line_number":4825,"context_line":"        if value \u003c self._lower:"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_80dea4d7","line":4822,"updated":"2019-01-30 21:15:57.000000000","message":"I kinda wonder if we should ensure upper/lower are always *decoded* instead... the container namespace is always limited to unicode strings after all... hmm...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":5005,"context_line":"        elif other is None:"},{"line_number":5006,"context_line":"            return True"},{"line_number":5007,"context_line":"        else:"},{"line_number":5008,"context_line":"            return self.upper \u003c self._encode(other)"},{"line_number":5009,"context_line":""},{"line_number":5010,"context_line":"    def __gt__(self, other):"},{"line_number":5011,"context_line":"        # a ShardRange is greater than other if its entire namespace is greater"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_3d683f1b","line":5008,"range":{"start_line":5008,"start_character":37,"end_line":5008,"end_character":44},"updated":"2019-01-30 21:15:57.000000000","message":"These should be equivalent... but I wonder if\n\n self._encode_bound(other)\n\nwould be more obviously-correct...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":5005,"context_line":"        elif other is None:"},{"line_number":5006,"context_line":"            return True"},{"line_number":5007,"context_line":"        else:"},{"line_number":5008,"context_line":"            return self.upper \u003c self._encode(other)"},{"line_number":5009,"context_line":""},{"line_number":5010,"context_line":"    def __gt__(self, other):"},{"line_number":5011,"context_line":"        # a ShardRange is greater than other if its entire namespace is greater"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_8c4edb35","line":5008,"range":{"start_line":5008,"start_character":37,"end_line":5008,"end_character":44},"in_reply_to":"9fdfeff1_3d683f1b","updated":"2019-01-31 03:02:13.000000000","message":"I don\u0027t follow. The _encode_bound() is like this:  if isinstance(x, Bound): compare as bounds, else: _encode(). But we don\u0027t compare ShardRange with a Bound. Do you want to add an additional branch of the if, in case? The original code didn\u0027t do that and py3 didn\u0027t change anything, but I can do it.","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0fa3ffb71451845876bca3e396cf47ac41ecfb64","unresolved":false,"context_lines":[{"line_number":3976,"context_line":"                try:"},{"line_number":3977,"context_line":"                    chunk \u003d next(self.input_iterator)"},{"line_number":3978,"context_line":"                except StopIteration:"},{"line_number":3979,"context_line":"                    return"},{"line_number":3980,"context_line":"                cl \u003d len(chunk)"},{"line_number":3981,"context_line":"                if cl \u003c\u003d n:"},{"line_number":3982,"context_line":"                    n -\u003d cl"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_1a5e26e9","line":3979,"updated":"2019-02-20 22:12:33.000000000","message":"This was me -- needed for py37, see https://www.python.org/dev/peps/pep-0479/ and https://docs.python.org/3/whatsnew/3.7.html#changes-in-python-behavior","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"}],"swift/container/backend.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":1735,"context_line":"                start \u003d marker \u003c sr.upper"},{"line_number":1736,"context_line":"            return start and end"},{"line_number":1737,"context_line":""},{"line_number":1738,"context_line":"        (marker, end_marker) \u003d utf8encode(marker, end_marker)"},{"line_number":1739,"context_line":""},{"line_number":1740,"context_line":"        if reverse:"},{"line_number":1741,"context_line":"            marker, end_marker \u003d end_marker, marker"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_9d8b6bc1","line":1738,"updated":"2019-01-30 21:15:57.000000000","message":"So no\n\n if six.PY2:\n\nguard here?","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":1735,"context_line":"                start \u003d marker \u003c sr.upper"},{"line_number":1736,"context_line":"            return start and end"},{"line_number":1737,"context_line":""},{"line_number":1738,"context_line":"        (marker, end_marker) \u003d utf8encode(marker, end_marker)"},{"line_number":1739,"context_line":""},{"line_number":1740,"context_line":"        if reverse:"},{"line_number":1741,"context_line":"            marker, end_marker \u003d end_marker, marker"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_acd2bf26","line":1738,"in_reply_to":"9fdfeff1_9d8b6bc1","updated":"2019-01-31 03:02:13.000000000","message":"Done\n\nI thought py2 was wrong specifically here. But let\u0027s not touch it. Maybe fix separately.","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":2168,"context_line":"                        \"Problem finding shard upper in %r: \" % self.db_file)"},{"line_number":2169,"context_line":"                    break"},{"line_number":2170,"context_line":"                if six.PY3:"},{"line_number":2171,"context_line":"                    next_shard_upper \u003d next_shard_upper.encode(\u0027utf-8\u0027)"},{"line_number":2172,"context_line":""},{"line_number":2173,"context_line":"            if (next_shard_upper is None or"},{"line_number":2174,"context_line":"                    next_shard_upper \u003e own_shard_range.upper):"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_a0fba8be","line":2171,"updated":"2019-01-30 21:15:57.000000000","message":"Should we just do this in _get_next_shard_range_upper()?","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":2168,"context_line":"                        \"Problem finding shard upper in %r: \" % self.db_file)"},{"line_number":2169,"context_line":"                    break"},{"line_number":2170,"context_line":"                if six.PY3:"},{"line_number":2171,"context_line":"                    next_shard_upper \u003d next_shard_upper.encode(\u0027utf-8\u0027)"},{"line_number":2172,"context_line":""},{"line_number":2173,"context_line":"            if (next_shard_upper is None or"},{"line_number":2174,"context_line":"                    next_shard_upper \u003e own_shard_range.upper):"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_acdddfe0","line":2171,"in_reply_to":"9fdfeff1_a0fba8be","updated":"2019-01-31 03:02:13.000000000","message":"Done","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"4122647a4c09b4598824c91e3f496dc9bd1837d8","unresolved":false,"context_lines":[{"line_number":469,"context_line":"        return self._storage_policy_index"},{"line_number":470,"context_line":""},{"line_number":471,"context_line":"    @property"},{"line_number":472,"context_line":"    def _path(self):"},{"line_number":473,"context_line":"        self._populate_instance_cache()"},{"line_number":474,"context_line":"        # Seems very silly for the type of a field in our own structure"},{"line_number":475,"context_line":"        # to change between py2 and py3, but apparently this is how WSGI"}],"source_content_type":"text/x-python","patch_set":13,"id":"9fdfeff1_f9aaab6e","line":472,"updated":"2019-02-01 05:59:35.000000000","message":"This path change definitely added to the size of this change. Was this going to go back to path?","commit_id":"89faf13c56afcb9f48c270d12c185ce0e29f068a"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"52440372b22c67eec28aaeb01d1675affaabcbae","unresolved":false,"context_lines":[{"line_number":469,"context_line":"        return self._storage_policy_index"},{"line_number":470,"context_line":""},{"line_number":471,"context_line":"    @property"},{"line_number":472,"context_line":"    def _path(self):"},{"line_number":473,"context_line":"        self._populate_instance_cache()"},{"line_number":474,"context_line":"        # Seems very silly for the type of a field in our own structure"},{"line_number":475,"context_line":"        # to change between py2 and py3, but apparently this is how WSGI"}],"source_content_type":"text/x-python","patch_set":13,"id":"9fdfeff1_95ce57b2","line":472,"in_reply_to":"9fdfeff1_f9aaab6e","updated":"2019-02-07 21:14:58.000000000","message":"Done, I broke it out into a separate patch.","commit_id":"89faf13c56afcb9f48c270d12c185ce0e29f068a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"4122647a4c09b4598824c91e3f496dc9bd1837d8","unresolved":false,"context_lines":[{"line_number":1375,"context_line":"                item \u003d dict(item)"},{"line_number":1376,"context_line":"            # Seems silly to do the isinstance() dance, because ShardRange"},{"line_number":1377,"context_line":"            # has a defined type for each of the 3: \u0027name\u0027 is always text,"},{"line_number":1378,"context_line":"            # bounds are bytes. But, bounds can also be the min/max type."},{"line_number":1379,"context_line":"            for col in (\u0027name\u0027, \u0027lower\u0027, \u0027upper\u0027):"},{"line_number":1380,"context_line":"                if six.PY2 and isinstance(item[col], six.text_type):"},{"line_number":1381,"context_line":"                    item[col] \u003d item[col].encode(\u0027utf-8\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"9fdfeff1_d9bd67b7","line":1378,"updated":"2019-02-01 05:59:35.000000000","message":"Yeah, to be honest, up until having to deal with bytes and unicode craziness thanks to py3 I never really thought about this much.\n\nthe min/max bounds all started out being an \"\" string, but but Al rightly tuned them into the Min and Max bound objects as it greatly simplified the code and edge cases. But they still get sent over the wire as \"\". Which is why the bounds __str__ alwasys returns \"\".","commit_id":"89faf13c56afcb9f48c270d12c185ce0e29f068a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e7bbd9b8a7a2ea25cdc318a2555bc76bbb85c45e","unresolved":false,"context_lines":[{"line_number":1368,"context_line":"                if six.PY2 and isinstance(item[col], six.text_type):"},{"line_number":1369,"context_line":"                    item[col] \u003d item[col].encode(\u0027utf-8\u0027)"},{"line_number":1370,"context_line":"                elif not six.PY2 and isinstance(item[col], six.binary_type):"},{"line_number":1371,"context_line":"                    item[col] \u003d item[col].decode(\u0027utf-8\u0027)"},{"line_number":1372,"context_line":"            item_list.append(item)"},{"line_number":1373,"context_line":""},{"line_number":1374,"context_line":"        def _really_merge_items(conn):"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_eb435612","line":1371,"updated":"2019-02-21 00:50:11.000000000","message":"We see this pattern twice now. Anymore and we should start to think about refactoring it. Or hold on until py2 isn\u0027t supported anymore ;P","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e7bbd9b8a7a2ea25cdc318a2555bc76bbb85c45e","unresolved":false,"context_lines":[{"line_number":1427,"context_line":"                # will panic:"},{"line_number":1428,"context_line":"                #   sqlite3.OperationalError: cannot start a transaction"},{"line_number":1429,"context_line":"                #   within a transaction"},{"line_number":1430,"context_line":"                conn.rollback()"},{"line_number":1431,"context_line":"                if (\u0027no such table: %s\u0027 % SHARD_RANGE_TABLE) not in str(err):"},{"line_number":1432,"context_line":"                    raise"},{"line_number":1433,"context_line":"                self.create_shard_range_table(conn)"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_8b488a2e","line":1430,"updated":"2019-02-21 00:50:11.000000000","message":"Wow OK. Is this something that we may need to add all over the place then?","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"}],"swift/container/reconciler.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e7bbd9b8a7a2ea25cdc318a2555bc76bbb85c45e","unresolved":false,"context_lines":[{"line_number":121,"context_line":"def best_policy_index(headers):"},{"line_number":122,"context_line":"    container_info \u003d [translate_container_headers_to_info(header_set)"},{"line_number":123,"context_line":"                      for header_set in headers]"},{"line_number":124,"context_line":"    container_info.sort(key\u003dfunctools.cmp_to_key(cmp_policy_info))"},{"line_number":125,"context_line":"    return container_info[0][\u0027storage_policy_index\u0027]"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_ab454e17","line":124,"updated":"2019-02-21 00:50:11.000000000","message":"huh, removing a pythonism like map, is this not supported in py37 or something?","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"}],"swift/container/server.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e7bbd9b8a7a2ea25cdc318a2555bc76bbb85c45e","unresolved":false,"context_lines":[{"line_number":464,"context_line":"                return response"},{"line_number":465,"context_line":""},{"line_number":466,"context_line":"            broker.put_object(obj, req_timestamp.internal,"},{"line_number":467,"context_line":"                              int(req.headers[\u0027x-size\u0027]),"},{"line_number":468,"context_line":"                              req.headers[\u0027x-content-type\u0027],"},{"line_number":469,"context_line":"                              req.headers[\u0027x-etag\u0027], 0,"},{"line_number":470,"context_line":"                              obj_policy_index,"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_4b52a2e0","side":"PARENT","line":467,"updated":"2019-02-21 00:50:11.000000000","message":"Well I\u0027d hope no unicode sneaks into x-size, and seeing that we\u0027re using int, if it did we\u0027d expoct it to fail right? I think this is fine.","commit_id":"6381da009e2efcea987d89340e64cc65850c313a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0fa3ffb71451845876bca3e396cf47ac41ecfb64","unresolved":false,"context_lines":[{"line_number":464,"context_line":"            if response:"},{"line_number":465,"context_line":"                return response"},{"line_number":466,"context_line":""},{"line_number":467,"context_line":"            broker.put_object(obj, req_timestamp.internal,"},{"line_number":468,"context_line":"                              int(req.headers[\u0027x-size\u0027]),"},{"line_number":469,"context_line":"                              wsgi_to_str(req.headers[\u0027x-content-type\u0027]),"},{"line_number":470,"context_line":"                              wsgi_to_str(req.headers[\u0027x-etag\u0027]), 0,"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_7a72d24b","line":467,"range":{"start_line":467,"start_character":30,"end_line":467,"end_character":33},"updated":"2019-02-20 22:12:33.000000000","message":"Still debating about whether this should get a wsgi_to_str... but we could always do it later if needed -- it won\u0027t affect the py2 path.","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e7bbd9b8a7a2ea25cdc318a2555bc76bbb85c45e","unresolved":false,"context_lines":[{"line_number":532,"context_line":"        if is_deleted:"},{"line_number":533,"context_line":"            return HTTPNotFound(request\u003dreq, headers\u003dheaders)"},{"line_number":534,"context_line":"        headers.update("},{"line_number":535,"context_line":"            (str_to_wsgi(key), str_to_wsgi(value))"},{"line_number":536,"context_line":"            for key, (value, timestamp) in broker.metadata.items()"},{"line_number":537,"context_line":"            if value !\u003d \u0027\u0027 and (key.lower() in self.save_headers or"},{"line_number":538,"context_line":"                                is_sys_or_user_meta(\u0027container\u0027, key)))"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_6b4f6634","line":535,"updated":"2019-02-21 00:50:11.000000000","message":"It would be cool if we could make swob and request_helpers were smart enough to str_to_wsgi or wsgi_to_str automatically so we don\u0027t have to worry about it anywhere else. What\u0027s the point in reimplementing webob locally if we can\u0027t make it work for us ;) \nJust a thought.. not something we need now.","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"07ed79267a3a36d495f530dd470cfd14b24aae3c","unresolved":false,"context_lines":[{"line_number":532,"context_line":"        if is_deleted:"},{"line_number":533,"context_line":"            return HTTPNotFound(request\u003dreq, headers\u003dheaders)"},{"line_number":534,"context_line":"        headers.update("},{"line_number":535,"context_line":"            (str_to_wsgi(key), str_to_wsgi(value))"},{"line_number":536,"context_line":"            for key, (value, timestamp) in broker.metadata.items()"},{"line_number":537,"context_line":"            if value !\u003d \u0027\u0027 and (key.lower() in self.save_headers or"},{"line_number":538,"context_line":"                                is_sys_or_user_meta(\u0027container\u0027, key)))"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_27d67255","line":535,"in_reply_to":"9fdfeff1_6b4f6634","updated":"2019-02-21 02:10:44.000000000","message":"This is one reason why I was very much against letting WSGI leak all over: there\u0027s no type difference. You cannot distinguish unicode strings that are in WSGI from regular ones. At least if UTF-8 bytes are used somewhere it should not be, you get some sort of type mismatch. But in this case, there\u0027s no typing information to go on. It\u0027s impossible to distinguish wsgi and str, and therefore it\u0027s impossible to make automatic polymorphy or coersions.","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"}],"swift/container/sharder.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":675,"context_line":""},{"line_number":676,"context_line":"        shard_range \u003d None"},{"line_number":677,"context_line":"        if own_shard_range:"},{"line_number":678,"context_line":"            # stuffing lower and upper sraight into params works in this case,"},{"line_number":679,"context_line":"            # because our own range can never have bounds in upper and lower,"},{"line_number":680,"context_line":"            # only encoded strings... right?"},{"line_number":681,"context_line":"            shard_ranges \u003d self._fetch_shard_ranges("}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_002ab42a","line":678,"range":{"start_line":678,"start_character":39,"end_line":678,"end_character":46},"updated":"2019-01-30 21:15:57.000000000","message":"nit: straight","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":675,"context_line":""},{"line_number":676,"context_line":"        shard_range \u003d None"},{"line_number":677,"context_line":"        if own_shard_range:"},{"line_number":678,"context_line":"            # stuffing lower and upper sraight into params works in this case,"},{"line_number":679,"context_line":"            # because our own range can never have bounds in upper and lower,"},{"line_number":680,"context_line":"            # only encoded strings... right?"},{"line_number":681,"context_line":"            shard_ranges \u003d self._fetch_shard_ranges("}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_0ca18b46","line":678,"range":{"start_line":678,"start_character":39,"end_line":678,"end_character":46},"in_reply_to":"9fdfeff1_002ab42a","updated":"2019-01-31 03:02:13.000000000","message":"Done","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":676,"context_line":"        shard_range \u003d None"},{"line_number":677,"context_line":"        if own_shard_range:"},{"line_number":678,"context_line":"            # stuffing lower and upper sraight into params works in this case,"},{"line_number":679,"context_line":"            # because our own range can never have bounds in upper and lower,"},{"line_number":680,"context_line":"            # only encoded strings... right?"},{"line_number":681,"context_line":"            shard_ranges \u003d self._fetch_shard_ranges("},{"line_number":682,"context_line":"                broker, newest\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_40c2fc5a","line":679,"range":{"start_line":679,"start_character":22,"end_line":679,"end_character":76},"updated":"2019-01-30 21:15:57.000000000","message":"What about first and last shards? Pretty sure they can have MIN/MAX for lower/upper... I think we were relying on a str() that happens somewhere in stdlib...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":676,"context_line":"        shard_range \u003d None"},{"line_number":677,"context_line":"        if own_shard_range:"},{"line_number":678,"context_line":"            # stuffing lower and upper sraight into params works in this case,"},{"line_number":679,"context_line":"            # because our own range can never have bounds in upper and lower,"},{"line_number":680,"context_line":"            # only encoded strings... right?"},{"line_number":681,"context_line":"            shard_ranges \u003d self._fetch_shard_ranges("},{"line_number":682,"context_line":"                broker, newest\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_8ca57b49","line":679,"range":{"start_line":679,"start_character":22,"end_line":679,"end_character":76},"in_reply_to":"9fdfeff1_40c2fc5a","updated":"2019-01-31 03:02:13.000000000","message":"Indeed, now that I think about it, maybe I was wrong.\n\nBut if I change the code like this, I have to write a test that captures the problem, and that\u0027s haaaard without knowing how sharder works. Maybe Matt can do it :-)","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":1149,"context_line":"        source_max_row \u003d source_broker.get_max_row()"},{"line_number":1150,"context_line":"        sync_point \u003d shard_broker.get_sync(source_db_id)"},{"line_number":1151,"context_line":"        if sync_point \u003c source_max_row:"},{"line_number":1152,"context_line":"            sync_from_row \u003d max(cleaving_context.last_cleave_to_row or 0,"},{"line_number":1153,"context_line":"                                sync_point)"},{"line_number":1154,"context_line":"            for objects, info in self.yield_objects("},{"line_number":1155,"context_line":"                    source_broker, shard_range,"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_8098e474","line":1152,"range":{"start_line":1152,"start_character":71,"end_line":1152,"end_character":72},"updated":"2019-01-30 21:15:57.000000000","message":"I wonder if we should default to -1, like get_sync() will if no sync point is found...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":1149,"context_line":"        source_max_row \u003d source_broker.get_max_row()"},{"line_number":1150,"context_line":"        sync_point \u003d shard_broker.get_sync(source_db_id)"},{"line_number":1151,"context_line":"        if sync_point \u003c source_max_row:"},{"line_number":1152,"context_line":"            sync_from_row \u003d max(cleaving_context.last_cleave_to_row or 0,"},{"line_number":1153,"context_line":"                                sync_point)"},{"line_number":1154,"context_line":"            for objects, info in self.yield_objects("},{"line_number":1155,"context_line":"                    source_broker, shard_range,"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_00086f25","line":1152,"range":{"start_line":1152,"start_character":71,"end_line":1152,"end_character":72},"in_reply_to":"9fdfeff1_8098e474","updated":"2019-01-31 03:02:13.000000000","message":"I didn\u0027t think far enough. I looked how None compares to integers, and concluded that 0 will produce the same result. Tested on command line, moved on. I\u0027m going to change this now.","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"4122647a4c09b4598824c91e3f496dc9bd1837d8","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        if own_shard_range:"},{"line_number":678,"context_line":"            # stuffing lower and upper straight into params works in this case,"},{"line_number":679,"context_line":"            # because our own range can never have bounds in upper and lower,"},{"line_number":680,"context_line":"            # only encoded strings... right?"},{"line_number":681,"context_line":"            shard_ranges \u003d self._fetch_shard_ranges("},{"line_number":682,"context_line":"                broker, newest\u003dTrue,"},{"line_number":683,"context_line":"                params\u003d{\u0027marker\u0027: own_shard_range.lower,"}],"source_content_type":"text/x-python","patch_set":13,"id":"9fdfeff1_39cef362","line":680,"updated":"2019-02-01 05:59:35.000000000","message":"Actually when we shard a root container, we split it up into ranges and each shard container is in charge of a ShardRange. But this means there will always be a shard container that has a lower \u003d\u003d \"\" (or Min) and another with an upper \u003d\u003d \"\" (or Max). The str of both these objects become \"\" so stuffing them and encoding them into params, hopefully, should turn them to \"\".. will it works in py2. I hope it would in py3.","commit_id":"89faf13c56afcb9f48c270d12c185ce0e29f068a"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"52440372b22c67eec28aaeb01d1675affaabcbae","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        if own_shard_range:"},{"line_number":678,"context_line":"            # stuffing lower and upper straight into params works in this case,"},{"line_number":679,"context_line":"            # because our own range can never have bounds in upper and lower,"},{"line_number":680,"context_line":"            # only encoded strings... right?"},{"line_number":681,"context_line":"            shard_ranges \u003d self._fetch_shard_ranges("},{"line_number":682,"context_line":"                broker, newest\u003dTrue,"},{"line_number":683,"context_line":"                params\u003d{\u0027marker\u0027: own_shard_range.lower,"}],"source_content_type":"text/x-python","patch_set":13,"id":"9fdfeff1_154fc734","line":680,"in_reply_to":"9fdfeff1_39cef362","updated":"2019-02-07 21:14:58.000000000","message":"Well the problem is, we\u0027re trying to avoid __str__, because all the marker comparisons are in bytes. The like 948 below is what I\u0027m trying to avoid. But if one finds himself writing these comments it\u0027s probably a sign that it was easier to add the encoding instead.","commit_id":"89faf13c56afcb9f48c270d12c185ce0e29f068a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"4122647a4c09b4598824c91e3f496dc9bd1837d8","unresolved":false,"context_lines":[{"line_number":812,"context_line":"                    yield objs[last_index:], None, info"},{"line_number":813,"context_line":"                    return"},{"line_number":814,"context_line":"                # This is a little awkward. We want to make the comparison"},{"line_number":815,"context_line":"                # with OuterBound happen, so we cannot use upper_str/lower_str."},{"line_number":816,"context_line":"                obj_name \u003d obj[\u0027name\u0027]"},{"line_number":817,"context_line":"                if six.PY3:"},{"line_number":818,"context_line":"                    obj_name \u003d obj_name.encode(\u0027utf-8\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"9fdfeff1_79febb6b","line":815,"updated":"2019-02-01 05:59:35.000000000","message":"I thought we made it so the comparisons between strings and OuterBound would work together. So you could mix and match.. though maybe I\u0027m miss remembering. \n\nOH.. I get it, it\u0027s because in we need to encode to \u0027utf-8\u0027 in PY3. Right.. yay, have I said how much I \"love\" this PY2/PY3 string/bytes craziness?","commit_id":"89faf13c56afcb9f48c270d12c185ce0e29f068a"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"52440372b22c67eec28aaeb01d1675affaabcbae","unresolved":false,"context_lines":[{"line_number":812,"context_line":"                    yield objs[last_index:], None, info"},{"line_number":813,"context_line":"                    return"},{"line_number":814,"context_line":"                # This is a little awkward. We want to make the comparison"},{"line_number":815,"context_line":"                # with OuterBound happen, so we cannot use upper_str/lower_str."},{"line_number":816,"context_line":"                obj_name \u003d obj[\u0027name\u0027]"},{"line_number":817,"context_line":"                if six.PY3:"},{"line_number":818,"context_line":"                    obj_name \u003d obj_name.encode(\u0027utf-8\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"9fdfeff1_952ad729","line":815,"in_reply_to":"9fdfeff1_79febb6b","updated":"2019-02-07 21:14:58.000000000","message":"Well, we \"need\" then encode in this verson. The alternative would be to complare obj[\u0027name\u0027] \u003c\u003d r.lower_str, but that does not work when r.lower is a bound, because r.lower_str is a \"\" then, as you explained above.","commit_id":"89faf13c56afcb9f48c270d12c185ce0e29f068a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"511204cd2423a99a6e3e0e46fc1801c9eea59911","unresolved":false,"context_lines":[{"line_number":571,"context_line":""},{"line_number":572,"context_line":"    def _send_shard_ranges(self, account, container, shard_ranges,"},{"line_number":573,"context_line":"                           headers\u003dNone):"},{"line_number":574,"context_line":"        body \u003d json.dumps([dict(sr) for sr in shard_ranges]).encode(\u0027ascii\u0027)"},{"line_number":575,"context_line":"        part, nodes \u003d self.ring.get_nodes(account, container)"},{"line_number":576,"context_line":"        headers \u003d headers or {}"},{"line_number":577,"context_line":"        headers.update({\u0027X-Backend-Record-Type\u0027: RECORD_TYPE_SHARD,"}],"source_content_type":"text/x-python","patch_set":14,"id":"9fdfeff1_83d9bc83","line":574,"updated":"2019-02-15 08:37:24.000000000","message":"I know I always seem to get confused with string encoeing but would encoding to ascii cause issues if a marker used international characters? As markers will usually end up being an object name?","commit_id":"4f2f65567fc8ad875370e998cd19235731f7e791"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"02097e76c281a1f43c83ef9845147ba2823b9339","unresolved":false,"context_lines":[{"line_number":571,"context_line":""},{"line_number":572,"context_line":"    def _send_shard_ranges(self, account, container, shard_ranges,"},{"line_number":573,"context_line":"                           headers\u003dNone):"},{"line_number":574,"context_line":"        body \u003d json.dumps([dict(sr) for sr in shard_ranges]).encode(\u0027ascii\u0027)"},{"line_number":575,"context_line":"        part, nodes \u003d self.ring.get_nodes(account, container)"},{"line_number":576,"context_line":"        headers \u003d headers or {}"},{"line_number":577,"context_line":"        headers.update({\u0027X-Backend-Record-Type\u0027: RECORD_TYPE_SHARD,"}],"source_content_type":"text/x-python","patch_set":14,"id":"9fdfeff1_5714e5e8","line":574,"in_reply_to":"9fdfeff1_83d9bc83","updated":"2019-02-16 03:09:43.000000000","message":"This encode() applies to the output of json.dumps(), which only contains ASCII. Example (works on both py2 and py3):\n\n\u003e\u003e\u003e json.dumps([u\u0027\\u3042\u0027])\n\u0027[\"\\\\u3042\"]\u0027\n\nBTW, JSON on py3 no longer serializes UTF-8 encoded bytes. The following works on py2, but not py3:\n\njson.dumps([b\u0027\\xe3\\x81\\x82\u0027])","commit_id":"4f2f65567fc8ad875370e998cd19235731f7e791"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"511204cd2423a99a6e3e0e46fc1801c9eea59911","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        if own_shard_range:"},{"line_number":678,"context_line":"            # stuffing lower and upper straight into params works in this case,"},{"line_number":679,"context_line":"            # because our own range can never have bounds in upper and lower,"},{"line_number":680,"context_line":"            # only encoded strings... right?"},{"line_number":681,"context_line":"            shard_ranges \u003d self._fetch_shard_ranges("},{"line_number":682,"context_line":"                broker, newest\u003dTrue,"},{"line_number":683,"context_line":"                params\u003d{\u0027marker\u0027: own_shard_range.lower,"}],"source_content_type":"text/x-python","patch_set":14,"id":"9fdfeff1_23e4903b","line":680,"updated":"2019-02-15 08:37:24.000000000","message":"Well if the current container happens to be a shard container at the start or end of the ranges then it\u0027ll have either a Min or Max as lower or upper respectively. So i can happen. These will be turned into a \u0027\u0027 (NOTE: not a b\u0027\u0027) will that be a problem?","commit_id":"4f2f65567fc8ad875370e998cd19235731f7e791"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"02097e76c281a1f43c83ef9845147ba2823b9339","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        if own_shard_range:"},{"line_number":678,"context_line":"            # stuffing lower and upper straight into params works in this case,"},{"line_number":679,"context_line":"            # because our own range can never have bounds in upper and lower,"},{"line_number":680,"context_line":"            # only encoded strings... right?"},{"line_number":681,"context_line":"            shard_ranges \u003d self._fetch_shard_ranges("},{"line_number":682,"context_line":"                broker, newest\u003dTrue,"},{"line_number":683,"context_line":"                params\u003d{\u0027marker\u0027: own_shard_range.lower,"}],"source_content_type":"text/x-python","patch_set":14,"id":"9fdfeff1_bf7abe84","line":680,"in_reply_to":"9fdfeff1_23e4903b","updated":"2019-02-16 03:09:43.000000000","message":"Okay. I see that it\u0027s easier to do the right thing than explain why I didn\u0027t. Since the params parameter ultimately gets into Request.params, I went with WSGI instead. Hopefully the fix is to your liking.","commit_id":"4f2f65567fc8ad875370e998cd19235731f7e791"}],"swift/proxy/controllers/container.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":196,"context_line":"            elif reverse:"},{"line_number":197,"context_line":"                em \u003d shard_range.lower_str"},{"line_number":198,"context_line":"                if isinstance(em, six.text_type):"},{"line_number":199,"context_line":"                    em \u003d em.encode(\u0027utf-8\u0027)"},{"line_number":200,"context_line":"                params[\u0027end_marker\u0027] \u003d em"},{"line_number":201,"context_line":"            else:"},{"line_number":202,"context_line":"                em \u003d shard_range.end_marker"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_40e3dcd9","line":199,"updated":"2019-01-30 21:15:57.000000000","message":"Can/should we use something like str_to_wsgi() instead?","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":196,"context_line":"            elif reverse:"},{"line_number":197,"context_line":"                em \u003d shard_range.lower_str"},{"line_number":198,"context_line":"                if isinstance(em, six.text_type):"},{"line_number":199,"context_line":"                    em \u003d em.encode(\u0027utf-8\u0027)"},{"line_number":200,"context_line":"                params[\u0027end_marker\u0027] \u003d em"},{"line_number":201,"context_line":"            else:"},{"line_number":202,"context_line":"                em \u003d shard_range.end_marker"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_e03e8bb6","line":199,"in_reply_to":"9fdfeff1_40e3dcd9","updated":"2019-01-31 03:02:13.000000000","message":"IIRC, _make_request isn\u0027t going to do the right thing if WSGI strings are used. I suppose I can throw utf8encode there.","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"}],"test/unit/cli/test_info.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":193,"context_line":"        self.assertEqual(sorted(out.getvalue().strip().split(\u0027\\n\u0027)),"},{"line_number":194,"context_line":"                         sorted(exp_out.split(\u0027\\n\u0027)))"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"    # XXX We need a test like this but with international characters, too."},{"line_number":197,"context_line":"    def test_print_db_info_metadata_with_shard_ranges(self):"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        shard_ranges \u003d [utils.ShardRange("}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_e0fe9069","line":196,"updated":"2019-01-30 21:15:57.000000000","message":"...and leading/trailing spaces... and embedded newlines...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"511204cd2423a99a6e3e0e46fc1801c9eea59911","unresolved":false,"context_lines":[{"line_number":193,"context_line":"        self.assertEqual(sorted(out.getvalue().strip().split(\u0027\\n\u0027)),"},{"line_number":194,"context_line":"                         sorted(exp_out.split(\u0027\\n\u0027)))"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"    # XXX We need a test like this but with international characters, too."},{"line_number":197,"context_line":"    def test_print_db_info_metadata_with_shard_ranges(self):"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        shard_ranges \u003d [utils.ShardRange("}],"source_content_type":"text/x-python","patch_set":14,"id":"9fdfeff1_43df5465","line":196,"updated":"2019-02-15 08:37:24.000000000","message":"Should we address this before this lands?","commit_id":"4f2f65567fc8ad875370e998cd19235731f7e791"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"02097e76c281a1f43c83ef9845147ba2823b9339","unresolved":false,"context_lines":[{"line_number":193,"context_line":"        self.assertEqual(sorted(out.getvalue().strip().split(\u0027\\n\u0027)),"},{"line_number":194,"context_line":"                         sorted(exp_out.split(\u0027\\n\u0027)))"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"    # XXX We need a test like this but with international characters, too."},{"line_number":197,"context_line":"    def test_print_db_info_metadata_with_shard_ranges(self):"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        shard_ranges \u003d [utils.ShardRange("}],"source_content_type":"text/x-python","patch_set":14,"id":"9fdfeff1_323da5ba","line":196,"in_reply_to":"9fdfeff1_43df5465","updated":"2019-02-16 03:09:43.000000000","message":"Done","commit_id":"4f2f65567fc8ad875370e998cd19235731f7e791"}],"test/unit/cli/test_manage_shard_ranges.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":209,"context_line":"                    \u0027}\u0027,"},{"line_number":210,"context_line":"                    \u0027Metadata:\u0027,"},{"line_number":211,"context_line":"                    \u0027  X-Container-Sysmeta-Sharding \u003d True\u0027]"},{"line_number":212,"context_line":"        # The json.dumps() in py2 produces trailing space, not in py3."},{"line_number":213,"context_line":"        result \u003d [x.rstrip() for x in out.getvalue().splitlines()]"},{"line_number":214,"context_line":"        self.assertEqual(expected, result)"},{"line_number":215,"context_line":"        self.assertEqual([\u0027Loaded db broker for a/c.\u0027],"}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_c0f7cc8a","line":212,"updated":"2019-01-30 21:15:57.000000000","message":"*sigh*\n\nI like the new behavior better, but still...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0fa3ffb71451845876bca3e396cf47ac41ecfb64","unresolved":false,"context_lines":[{"line_number":7305,"context_line":"        sr \u003d utils.ShardRange(\u0027a/c\u0027, utils.Timestamp.now(), \u0027b\u0027, \u0027y\u0027)"},{"line_number":7306,"context_line":"        with self.assertRaises(ValueError) as cm:"},{"line_number":7307,"context_line":"            sr.lower \u003d \u0027z\u0027"},{"line_number":7308,"context_line":"        self.assertIn(\"must be less than or equal to upper\", str(cm.exception))"},{"line_number":7309,"context_line":"        self.assertEqual(\u0027b\u0027, sr.lower_str)"},{"line_number":7310,"context_line":"        self.assertEqual(\u0027y\u0027, sr.upper_str)"},{"line_number":7311,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_9af7768d","line":7308,"updated":"2019-02-20 22:12:33.000000000","message":"Oh yeah, we could probably tighten this up again... *shrug*","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0fa3ffb71451845876bca3e396cf47ac41ecfb64","unresolved":false,"context_lines":[{"line_number":7621,"context_line":"        self.assertEqual("},{"line_number":7622,"context_line":"            \"ShardRange\u003c%r to %r as of %s, (100, 1000) as of %s, \""},{"line_number":7623,"context_line":"            \"active as of %s\u003e\""},{"line_number":7624,"context_line":"            % (\u0027l\u0027, \u0027u\u0027,"},{"line_number":7625,"context_line":"               ts.internal, meta_ts.internal, state_ts.internal), str(sr))"},{"line_number":7626,"context_line":""},{"line_number":7627,"context_line":"        ts.offset \u003d 0"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_5af10e95","line":7624,"updated":"2019-02-20 22:12:33.000000000","message":"Oh yeah, unneeded delta -- w/e","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"}],"test/unit/container/test_auditor.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0fa3ffb71451845876bca3e396cf47ac41ecfb64","unresolved":false,"context_lines":[{"line_number":151,"context_line":""},{"line_number":152,"context_line":"    @with_tempdir"},{"line_number":153,"context_line":"    @mock.patch(\u0027swift.container.auditor.dump_recon_cache\u0027)"},{"line_number":154,"context_line":"    def test_db_migration(self, tempdir, mock_recon):"},{"line_number":155,"context_line":"        db_path \u003d os.path.join(tempdir, \u0027sda\u0027, \u0027containers\u0027, \u00270\u0027, \u00270\u0027, \u00270\u0027,"},{"line_number":156,"context_line":"                               \u0027test.db\u0027)"},{"line_number":157,"context_line":"        with test_backend.TestContainerBrokerBeforeSPI.old_broker() as \\"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_3a2e8afa","line":154,"updated":"2019-02-20 22:12:33.000000000","message":"Sorry, I probably should have done these as a separate patch...","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"}],"test/unit/container/test_backend.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0fa3ffb71451845876bca3e396cf47ac41ecfb64","unresolved":false,"context_lines":[{"line_number":3739,"context_line":"            broker \u003d ContainerBroker(db_path, account\u003da, container\u003dc)"},{"line_number":3740,"context_line":"            broker.initialize(next(ts_iter).internal, 0)"},{"line_number":3741,"context_line":"            broker.set_sharding_sysmeta(\u0027Root\u0027, \u0027a/c\u0027)"},{"line_number":3742,"context_line":"            broker.merge_shard_ranges(list(shard_range_by_state.values()))"},{"line_number":3743,"context_line":"            return broker"},{"line_number":3744,"context_line":""},{"line_number":3745,"context_line":"        # make broker appear to be a root container"}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_3a7c4aea","line":3742,"updated":"2019-02-20 22:12:33.000000000","message":"Hmm... I wonder if we should move this into merge_shard_ranges(), so you could pass a generator expression and the like...","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"}],"test/unit/container/test_sharder.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":839,"context_line":"            params\u003dparams)"},{"line_number":840,"context_line":""},{"line_number":841,"context_line":"        params \u003d {\u0027format\u0027: \u0027json\u0027,"},{"line_number":842,"context_line":"                  \u0027end_marker\u0027: b\u0027there\u0027, \u0027marker\u0027: b\u0027here\u0027}"},{"line_number":843,"context_line":"        actual, mock_call \u003d do_test(json.dumps([]), params\u003dparams)"},{"line_number":844,"context_line":"        self._assert_shard_ranges_equal([], actual)"},{"line_number":845,"context_line":"        mock_call.assert_called_once_with("}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_801b04c8","line":842,"updated":"2019-01-30 21:15:57.000000000","message":"Mixing native strings and bytes seems kinda weird...","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"72c358d2ab3e146e6bfb6428a6dc6b829e7813a2","unresolved":false,"context_lines":[{"line_number":839,"context_line":"            params\u003dparams)"},{"line_number":840,"context_line":""},{"line_number":841,"context_line":"        params \u003d {\u0027format\u0027: \u0027json\u0027,"},{"line_number":842,"context_line":"                  \u0027end_marker\u0027: b\u0027there\u0027, \u0027marker\u0027: b\u0027here\u0027}"},{"line_number":843,"context_line":"        actual, mock_call \u003d do_test(json.dumps([]), params\u003dparams)"},{"line_number":844,"context_line":"        self._assert_shard_ranges_equal([], actual)"},{"line_number":845,"context_line":"        mock_call.assert_called_once_with("}],"source_content_type":"text/x-python","patch_set":12,"id":"9fdfeff1_80c8df73","line":842,"in_reply_to":"9fdfeff1_801b04c8","updated":"2019-01-31 03:02:13.000000000","message":"This is uniform with code like the line 2970 below.","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e7bbd9b8a7a2ea25cdc318a2555bc76bbb85c45e","unresolved":false,"context_lines":[{"line_number":839,"context_line":"            params\u003dparams)"},{"line_number":840,"context_line":""},{"line_number":841,"context_line":"        params \u003d {\u0027format\u0027: \u0027json\u0027,"},{"line_number":842,"context_line":"                  \u0027end_marker\u0027: \u0027there\u0027, \u0027marker\u0027: \u0027here\u0027}"},{"line_number":843,"context_line":"        actual, mock_call \u003d do_test(json.dumps([]), params\u003dparams)"},{"line_number":844,"context_line":"        self._assert_shard_ranges_equal([], actual)"},{"line_number":845,"context_line":"        mock_call.assert_called_once_with("}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_0b5edae8","line":842,"updated":"2019-02-21 00:50:11.000000000","message":"But this gives us and extra line in our line count :P (not a blocker)","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0fa3ffb71451845876bca3e396cf47ac41ecfb64","unresolved":false,"context_lines":[{"line_number":839,"context_line":"            params\u003dparams)"},{"line_number":840,"context_line":""},{"line_number":841,"context_line":"        params \u003d {\u0027format\u0027: \u0027json\u0027,"},{"line_number":842,"context_line":"                  \u0027end_marker\u0027: \u0027there\u0027, \u0027marker\u0027: \u0027here\u0027}"},{"line_number":843,"context_line":"        actual, mock_call \u003d do_test(json.dumps([]), params\u003dparams)"},{"line_number":844,"context_line":"        self._assert_shard_ranges_equal([], actual)"},{"line_number":845,"context_line":"        mock_call.assert_called_once_with("}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_da9c1e10","line":842,"updated":"2019-02-20 22:12:33.000000000","message":"Could all be one line again.","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0fa3ffb71451845876bca3e396cf47ac41ecfb64","unresolved":false,"context_lines":[{"line_number":1251,"context_line":"        context \u003d CleavingContext.load(broker)"},{"line_number":1252,"context_line":"        self.assertTrue(context.misplaced_done)"},{"line_number":1253,"context_line":"        self.assertFalse(context.cleaving_done)"},{"line_number":1254,"context_line":"        self.assertEqual(shard_ranges[1].upper_str, context.cursor)"},{"line_number":1255,"context_line":"        self.assertEqual(8, context.cleave_to_row)"},{"line_number":1256,"context_line":"        self.assertEqual(8, context.max_row)"},{"line_number":1257,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"9fdfeff1_9a8696ba","line":1254,"updated":"2019-02-20 22:12:33.000000000","message":"*shrug*\n\nEither way.","commit_id":"9881705a14ca2b68d908338ed3ff9a3b8b369d5b"}],"tox.ini":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5213bd90413bef97b0be243c1ba4d95e4b584e59","unresolved":false,"context_lines":[{"line_number":35,"context_line":"commands \u003d"},{"line_number":36,"context_line":"  nosetests {posargs:\\"},{"line_number":37,"context_line":"      test/unit/account \\"},{"line_number":38,"context_line":"      test/unit/cli \\"},{"line_number":39,"context_line":"      test/unit/common/middleware/crypto \\"},{"line_number":40,"context_line":"      test/unit/common/middleware/test_account_quotas.py \\"},{"line_number":41,"context_line":"      test/unit/common/middleware/test_acl.py \\"}],"source_content_type":"text/x-properties","patch_set":12,"id":"9fdfeff1_e05a1081","line":38,"updated":"2019-01-30 21:15:57.000000000","message":"Whooo!","commit_id":"ac8a213367bb274f4f03cc829f5aa6a295071cb7"}]}
