)]}'
{"subunit2sql/db/api.py":[{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6b12ecde6c3bb82779df7a3d811534d56bd18d79","unresolved":false,"context_lines":[{"line_number":466,"context_line":""},{"line_number":467,"context_line":"def _get_test_prefixes_mysql(session):"},{"line_number":468,"context_line":"    query \u003d session.query("},{"line_number":469,"context_line":"        sqlalchemy.func.substring_index(models.Test.test_id, \u0027.\u0027, 1))"},{"line_number":470,"context_line":""},{"line_number":471,"context_line":"    prefixes \u003d set()"},{"line_number":472,"context_line":"    for prefix in query.distinct().all():"}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_52ca4b6f","line":469,"updated":"2016-02-26 21:15:36.000000000","message":"So my issue with this is it assumes period separated test_ids, which there is no guarantee of. Nothing in the spec says this will always be the case. This is a thing with the default python running stack, but not actually a guaranteed pattern. That being said I think we can cheat here, if it causes a problem in the edge case of non-python users we can fix it in the future.","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":17001,"name":"Tim Buckley","email":"timothy.jas.buckley@hpe.com","username":"timothy.jas.buckley"},"change_message_id":"fde5ded7385b4475ca69c53eb8a2dd1c0cfd4b3b","unresolved":false,"context_lines":[{"line_number":466,"context_line":""},{"line_number":467,"context_line":"def _get_test_prefixes_mysql(session):"},{"line_number":468,"context_line":"    query \u003d session.query("},{"line_number":469,"context_line":"        sqlalchemy.func.substring_index(models.Test.test_id, \u0027.\u0027, 1))"},{"line_number":470,"context_line":""},{"line_number":471,"context_line":"    prefixes \u003d set()"},{"line_number":472,"context_line":"    for prefix in query.distinct().all():"}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_069d2559","line":469,"in_reply_to":"9aed3d3a_52ca4b6f","updated":"2016-02-26 23:55:17.000000000","message":"Doing some testing, both the mysql function (substring_index) and the pure-python implementation handle this case \u0027safely\u0027 and will just return the entire string if it can\u0027t find the separator (\u0027.\u0027), so at worst you\u0027ll just get a list of all test_id values if you never use periods.\n\nI\u0027ve made a note in the docs about what we\u0027re defining a prefix to be and added extra assertions in the unit tests, but I think it should be safe, functionality-wise, with this implementation?","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6b12ecde6c3bb82779df7a3d811534d56bd18d79","unresolved":false,"context_lines":[{"line_number":472,"context_line":"    for prefix in query.distinct().all():"},{"line_number":473,"context_line":"        prefix \u003d prefix[0]"},{"line_number":474,"context_line":"        if \u0027(\u0027 in prefix:"},{"line_number":475,"context_line":"            prefix \u003d prefix.split(\u0027(\u0027, 1)[1]"},{"line_number":476,"context_line":""},{"line_number":477,"context_line":"        prefixes.add(prefix)"},{"line_number":478,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_b2c9177b","line":475,"updated":"2016-02-26 21:15:36.000000000","message":"I think we need comments here and on it\u0027s dual function below. I know what you\u0027re trying to do here, but keeping the model in your head is tricky. I think explaining in words (or with examples) will make this much clearer","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":17001,"name":"Tim Buckley","email":"timothy.jas.buckley@hpe.com","username":"timothy.jas.buckley"},"change_message_id":"fde5ded7385b4475ca69c53eb8a2dd1c0cfd4b3b","unresolved":false,"context_lines":[{"line_number":472,"context_line":"    for prefix in query.distinct().all():"},{"line_number":473,"context_line":"        prefix \u003d prefix[0]"},{"line_number":474,"context_line":"        if \u0027(\u0027 in prefix:"},{"line_number":475,"context_line":"            prefix \u003d prefix.split(\u0027(\u0027, 1)[1]"},{"line_number":476,"context_line":""},{"line_number":477,"context_line":"        prefixes.add(prefix)"},{"line_number":478,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_fc5b6ef4","line":475,"in_reply_to":"9aed3d3a_b2c9177b","updated":"2016-02-26 23:55:17.000000000","message":"Done","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6b12ecde6c3bb82779df7a3d811534d56bd18d79","unresolved":false,"context_lines":[{"line_number":515,"context_line":"def _get_tests_by_prefix_mysql(prefix, session, limit, offset):"},{"line_number":516,"context_line":"    func_filter \u003d sqlalchemy.func.substring_index(models.Test.test_id, \u0027.\u0027, 1)"},{"line_number":517,"context_line":"    query \u003d db_utils.model_query(models.Test, session).filter("},{"line_number":518,"context_line":"        func_filter.like(\u0027%\u0027 + prefix)).order_by(models.Test.test_id.asc())"},{"line_number":519,"context_line":""},{"line_number":520,"context_line":"    return query.limit(limit).offset(offset).all()"},{"line_number":521,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_92c4d35f","line":518,"updated":"2016-02-26 21:15:36.000000000","message":"SpamapS always says to try to avoid using like in a query like this. I\u0027m not sure of the alternative, it might be useful to ping him.","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":17001,"name":"Tim Buckley","email":"timothy.jas.buckley@hpe.com","username":"timothy.jas.buckley"},"change_message_id":"fde5ded7385b4475ca69c53eb8a2dd1c0cfd4b3b","unresolved":false,"context_lines":[{"line_number":515,"context_line":"def _get_tests_by_prefix_mysql(prefix, session, limit, offset):"},{"line_number":516,"context_line":"    func_filter \u003d sqlalchemy.func.substring_index(models.Test.test_id, \u0027.\u0027, 1)"},{"line_number":517,"context_line":"    query \u003d db_utils.model_query(models.Test, session).filter("},{"line_number":518,"context_line":"        func_filter.like(\u0027%\u0027 + prefix)).order_by(models.Test.test_id.asc())"},{"line_number":519,"context_line":""},{"line_number":520,"context_line":"    return query.limit(limit).offset(offset).all()"},{"line_number":521,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_260ae921","line":518,"in_reply_to":"9aed3d3a_92c4d35f","updated":"2016-02-26 23:55:17.000000000","message":"That\u0027s almost always good advice, since it prevents the backend from using any indexes. I don\u0027t think it makes a difference here, though, since we\u0027re operating on function output anyway (that is, the substr_index result).","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6b12ecde6c3bb82779df7a3d811534d56bd18d79","unresolved":false,"context_lines":[{"line_number":527,"context_line":"    skipped \u003d 0"},{"line_number":528,"context_line":""},{"line_number":529,"context_line":"    ret \u003d []"},{"line_number":530,"context_line":"    for test in query.all():"},{"line_number":531,"context_line":"        test_prefix \u003d test.test_id.split(\u0027.\u0027, 1)[0]"},{"line_number":532,"context_line":"        if test_prefix.endswith(prefix):"},{"line_number":533,"context_line":"            if offset \u003e 0 and skipped \u003c offset:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_f2a1dfaa","line":530,"updated":"2016-02-26 21:15:36.000000000","message":"I wonder if we should use:\n\n for test in query:\n\nhere (if we can) that\u0027ll be looping over an iter instead of a list. Not a big deal either way.","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":17001,"name":"Tim Buckley","email":"timothy.jas.buckley@hpe.com","username":"timothy.jas.buckley"},"change_message_id":"fde5ded7385b4475ca69c53eb8a2dd1c0cfd4b3b","unresolved":false,"context_lines":[{"line_number":527,"context_line":"    skipped \u003d 0"},{"line_number":528,"context_line":""},{"line_number":529,"context_line":"    ret \u003d []"},{"line_number":530,"context_line":"    for test in query.all():"},{"line_number":531,"context_line":"        test_prefix \u003d test.test_id.split(\u0027.\u0027, 1)[0]"},{"line_number":532,"context_line":"        if test_prefix.endswith(prefix):"},{"line_number":533,"context_line":"            if offset \u003e 0 and skipped \u003c offset:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_8619357c","line":530,"in_reply_to":"9aed3d3a_f2a1dfaa","updated":"2016-02-26 23:55:17.000000000","message":"Done","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"6b12ecde6c3bb82779df7a3d811534d56bd18d79","unresolved":false,"context_lines":[{"line_number":553,"context_line":"    \"\"\""},{"line_number":554,"context_line":"    session \u003d session or get_session()"},{"line_number":555,"context_line":""},{"line_number":556,"context_line":"    backend \u003d session.bind.url.get_backend_name()"},{"line_number":557,"context_line":"    if backend \u003d\u003d \u0027mysql\u0027:"},{"line_number":558,"context_line":"        return _get_tests_by_prefix_mysql(prefix, session, limit, offset)"},{"line_number":559,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_d2a49bba","line":556,"updated":"2016-02-26 21:15:36.000000000","message":"I think you can probably just use session.bind.dialect for this.","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":17001,"name":"Tim Buckley","email":"timothy.jas.buckley@hpe.com","username":"timothy.jas.buckley"},"change_message_id":"fde5ded7385b4475ca69c53eb8a2dd1c0cfd4b3b","unresolved":false,"context_lines":[{"line_number":553,"context_line":"    \"\"\""},{"line_number":554,"context_line":"    session \u003d session or get_session()"},{"line_number":555,"context_line":""},{"line_number":556,"context_line":"    backend \u003d session.bind.url.get_backend_name()"},{"line_number":557,"context_line":"    if backend \u003d\u003d \u0027mysql\u0027:"},{"line_number":558,"context_line":"        return _get_tests_by_prefix_mysql(prefix, session, limit, offset)"},{"line_number":559,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9aed3d3a_26130968","line":556,"in_reply_to":"9aed3d3a_d2a49bba","updated":"2016-02-26 23:55:17.000000000","message":"Done","commit_id":"08260c039980fc178ad4a3ebb993fde24d1dc887"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"2b4cadf356d744d9dee5956e2ac93b469fa2a538","unresolved":false,"context_lines":[{"line_number":569,"context_line":""},{"line_number":570,"context_line":"            ret.append(test)"},{"line_number":571,"context_line":""},{"line_number":572,"context_line":"            if len(ret) \u003e\u003d limit:"},{"line_number":573,"context_line":"                break"},{"line_number":574,"context_line":""},{"line_number":575,"context_line":"    return ret"}],"source_content_type":"text/x-python","patch_set":6,"id":"9aed3d3a_29ec0cf2","line":572,"updated":"2016-03-01 06:22:44.000000000","message":"This is just a note. It seems the LIMIT and OFFSET in SQL is supported by not only mysql but also sqlite and postgresql. But I\u0027m OK here because we can\u0027t guarantee the other DBs.\n\nhttp://www.postgresql.org/docs/9.3/static/queries-limit.html\nhttps://www.sqlite.org/lang_select.html#limitoffset","commit_id":"8cee1f36ea1d382e5980f3cacbc232c7b711fee0"},{"author":{"_account_id":17001,"name":"Tim Buckley","email":"timothy.jas.buckley@hpe.com","username":"timothy.jas.buckley"},"change_message_id":"e3543b05e845bae01b1829a2286dc9f7f61f21ed","unresolved":false,"context_lines":[{"line_number":569,"context_line":""},{"line_number":570,"context_line":"            ret.append(test)"},{"line_number":571,"context_line":""},{"line_number":572,"context_line":"            if len(ret) \u003e\u003d limit:"},{"line_number":573,"context_line":"                break"},{"line_number":574,"context_line":""},{"line_number":575,"context_line":"    return ret"}],"source_content_type":"text/x-python","patch_set":6,"id":"7af24918_bff90ccb","line":572,"in_reply_to":"9aed3d3a_29ec0cf2","updated":"2016-03-01 20:29:16.000000000","message":"We can\u0027t actually use DBMS-side limiting and offsets here since we had to move all the filtering logic to the client. If the caller asks for 100 tests and we pass that limit along to the DBMS, we\u0027d (probably) have to return \u003c 100 results even if more exist.\n\nOn the other hand, for the mysql version, if you ask for a limit of 100, it will always give you the first 100 matches (as expected). In other words, if we don\u0027t do our own limiting and offsets for the fallback code path, we\u0027d have inconsistent output depending on backend :)","commit_id":"8cee1f36ea1d382e5980f3cacbc232c7b711fee0"},{"author":{"_account_id":5689,"name":"Masayuki Igawa","email":"masayuki@igawa.io","username":"igawa"},"change_message_id":"2b4cadf356d744d9dee5956e2ac93b469fa2a538","unresolved":false,"context_lines":[{"line_number":590,"context_line":"    unexpected results."},{"line_number":591,"context_line":""},{"line_number":592,"context_line":"    :param str prefix: the test prefix to search for"},{"line_number":593,"context_line":"    :param int limit: the maximum number of results to return"},{"line_number":594,"context_line":"    :param int offset: the starting index, for pagination purposes"},{"line_number":595,"context_line":"    :return list: the list of matching test objects, ordered by their test id"},{"line_number":596,"context_line":"    :rtype: subunit2sql.models.Test"}],"source_content_type":"text/x-python","patch_set":6,"id":"9aed3d3a_e9ad04ea","line":593,"updated":"2016-03-01 06:22:44.000000000","message":"nit: I feel like it\u0027s good to add a doc of the session parameter for the consistency.","commit_id":"8cee1f36ea1d382e5980f3cacbc232c7b711fee0"},{"author":{"_account_id":17001,"name":"Tim Buckley","email":"timothy.jas.buckley@hpe.com","username":"timothy.jas.buckley"},"change_message_id":"e3543b05e845bae01b1829a2286dc9f7f61f21ed","unresolved":false,"context_lines":[{"line_number":590,"context_line":"    unexpected results."},{"line_number":591,"context_line":""},{"line_number":592,"context_line":"    :param str prefix: the test prefix to search for"},{"line_number":593,"context_line":"    :param int limit: the maximum number of results to return"},{"line_number":594,"context_line":"    :param int offset: the starting index, for pagination purposes"},{"line_number":595,"context_line":"    :return list: the list of matching test objects, ordered by their test id"},{"line_number":596,"context_line":"    :rtype: subunit2sql.models.Test"}],"source_content_type":"text/x-python","patch_set":6,"id":"7af24918_ff76f43c","line":593,"in_reply_to":"9aed3d3a_e9ad04ea","updated":"2016-03-01 20:29:16.000000000","message":"Done","commit_id":"8cee1f36ea1d382e5980f3cacbc232c7b711fee0"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"e680bb53fb2aa7b441e857c4b290fd990c7f0c1b","unresolved":false,"context_lines":[{"line_number":584,"context_line":"    given an input \u0027a\u0027, this will return tests with prefixes \u0027a\u0027, but also"},{"line_number":585,"context_line":"    prefixes wrapped in function syntax, such as \u0027setUpClass (a\u0027."},{"line_number":586,"context_line":""},{"line_number":587,"context_line":"    Note that this implementation assumes that tests ids are semantically"},{"line_number":588,"context_line":"    separated by a period. If no period character exists in a test id, its"},{"line_number":589,"context_line":"    prefix will be considered the full test id, and this method may return"},{"line_number":590,"context_line":"    unexpected results."},{"line_number":591,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"7af24918_fa6ecd94","line":588,"range":{"start_line":587,"start_character":62,"end_line":588,"end_character":25},"updated":"2016-03-02 14:42:44.000000000","message":"Would could have a kwarg based deliminator. But that can also be a follow up patch.","commit_id":"4fc05aa11acd1f9ce3c79984d3d71ee3c4a5294b"}]}
