diff --git a/tests/cassettes/test_entries_group_by/test_group_by_tags.yaml b/tests/cassettes/test_entries_group_by/test_group_by_tags.yaml index d66d88d..588ffb6 100644 --- a/tests/cassettes/test_entries_group_by/test_group_by_tags.yaml +++ b/tests/cassettes/test_entries_group_by/test_group_by_tags.yaml @@ -15,31 +15,31 @@ interactions: response: body: string: !!binary | - H4sIAAAAAAAEA82Z3YrjNhTHX0X4thnQh+UP3W1nurDQ0sIUCl2WQRNrEm8c27XlTWdL36CFXpdC - r/oCfbI+Qo+deGxFqSeT2mYhN5FNIp3f+Z8vvf3JiSNH0ICEhHIc+gtnlxWbMpdLdVc/IQHhmAQL - Jy+y92qp94t+4DLuU1jWstw0a2mVJAvnPk4SeZ8oRzzIpFQLp9Sy0I5wKKbsCpMr6n1LqaBcMP4Z - xgJjp34ny61XuCsY+x6eRlUhdZylsBefwT9GqlwWcb5fcq6z7bZKY/0o0KskyXYol0UZpyuUPaA3 - 33zwkIyiQpWlKlGcwmelSo3yOFdJnCr4dS1XpSPeOvoxV6Ks8jyD7b5r1uFY9SNCsR9gD8MibCVL - k0dH6KKCs0n7YM2uu4Op4oMq7iKVKK2iu/r9vZmqEpYbw3uUMMYWTmV825mmb761Nv950THDAaUe - nYMZES4XhHRHO8WswWoyoy51B5i9jn98IqaKIivQMolVCoiAA4pLdJ/IdINkGgHI9xWwe4B3dLxV - t1pu8/EBHnnmHADdWUS3B4iHAB4YmwDJHPQMwZ0hNMsb5+BE5uOEg+c5YZMTRIH/jIyjqewyTj2n - m5wTZoSDy06fxLBgoXD9Zznh0OTEQjqE6tXHqlDoNl6lkK6+yqIqUUhWeg0xMV42efAOMvESMhrk - MsgsWsZJid6UZTV6NmtEhsPuhBPDCwIf8tl5IqMBdknI8EUFCAkEDwXvuaWdzA54TXY8rAskU2b/ - /Pnr3+gmTlNVdNnopTqxnGlEU7em6tUNgU9ciqHqmFwmxBeEQbnXOZFl6ppGIOhRrefRcLDW+2Rk - 0m6/O+GI7MiJoi/wvICfWfS17C+TiSdcADMkkxavKRPoGLgtk99/QbfrSmsovFdoA7U1uld6p1SK - 1tkWghyUeLu11Aoq5ouF1O5nEhitMftC4p6H+Xkh64nlZTC44NA09aKxLaQ9L2rCYMQDoZsxq980 - fTpCOmx/EnZPxjfguSF3wVOnj4IcKgVB3O5oNrwDXxPeCSHdFFmO1kpGqkBJtkJ1H1u3ttdJVkWv - oT/VCCSU6rIT0SjNLbEccOo453oEE8jwc+DBTLhDzS2cviFo4qEesbT1RSJLKNW+TptKTqAfKpg4 - wPiiRA9FtkU3Ko0/ouus3FTp+ISOvGxqQtQnvj+LgJjAZHhkRGBeBGWUZxLizLUb2FopUFvD1Cgr - 6mR0hb5TagNznWbs042DtkppeG6Og8KQeZDgnm9S2w11op8aB8zHuO+dJZg2l12WiyigEGyo94Gi - D6Z7xzSIG4bHuQjq5z/Ql1W6XHfmf2H5DH8G6HkvvI5o6dZS/cRBaMDrsdb0kYkKDGlxsATbwyCm - 34MrWH5fPqbLzsaHpFCvGeY+jDvJGQ5++Of5HBz73PNnyQgQbODzjN0bNKbdKakzllltrSS07zC0 - zHZWxP+fEcbyjhH9/mTFhGHcPMsdAQE9Q8ExNAYje0ZHjl+P048ByLrGpQJGx80NQWWNjVeZTE6q - gJ2hgsM2ZlOB7weM1jcyk0cfDN2fK8hgz3HgZKogxHacHz36WB4ysfP7Pob8CvnrDLuHHNPQq5v0 - C+7HsA/3ccLtpTOrWwAy8CHHI2DmQfY3g4/OVqvkShdyuRHQK8AFSn15gqBBKGLV6xGMHPC817cb - mMTrW+v1Uq4PQw8cgj0nN37ThfIhnwc+MGfARwMr4gXWRddUxj9sYD7jM7gdPi/vtuXSZZ7v1eXO - YNqtc249vjUDDuXuicLyr9/Q54WSmwfoyLrC56WebjnEiHGmtZbh6QRD4zuDp9f3ucM9FRi74WEa - m9HQGu9N5emWQ4xo/Kcw8+5fyIRd7gYhAAA= + H4sIAAAAAAAEA9WZ3Y7jNBTHX8XKLR3JH7GT+G6ZYaWVQCDNSkisViNP47bZpklInC2ziDdgJa4R + Ele8AE/GI3CSJpO6KZluacIg9aZO1Nrndz7+5/jNj04UOpL6JCCU48CbOds0XxeZmuu76gnxCcfE + nzlZnr7Tc7Nb9HyXcY/CslHFul5LyjieOfdRHKv7WDtyoeJCz5zCqNw40qGYsitMrqh4TamkXDL+ + GcYSY6d6J816r3BXMvYdPA3LXJkoTWAvHoN/DHUxz6Nst+Rcp5tNmUTmQaIXcZxuUabyIkqWKF2g + V9+8F0iFYa6LQhcoSuCz1IVBWZTpOEo0/LpRy8KRbxzzkGlZlFmWwnbf1utwrOoRodjzscCwCFtJ + k/jBkSYv4Wyqf7B6193BdP5e53ehjrXR4V31/s5MZQHLteEFJYyxmVNa37a26etvrc1/mnXMsE+p + oFMwI9LlkpDuaMeY1VhtZtSl7gCzl9EPj8R0nqc5mseRTgARcEBRge5jlayRSkIA+a4Edgt4x0Qb + fWvUJrs8wAPPnAKgO0nQ7QDiIYANYxsg+T/Qo1eYvcaedIVkQXfEKeiR6ehhvztaP/wawDY9yA3/ + mC+fTez9V/QwIxzce/yCh8Erpes9SQ8HNj0W0CGALz6UuUa30TKB0vZVGpaxRqo0K8if0byumXdQ + tedQ/aDuQRUyKooL9KooyotXvtr58HSh5/se1L7TQo/62CUBw2eJFeJLHkg+mDcbvDY7HlRiyg6+ + v37/+Ce6iZJE513lssTGCSKj50wXzHKtqfY0hu8Rl2JQKKOHCfEkYSANB8KkouFLeqALBQ0GdeGz + CZN2+90JL8iOHBGIvhA+P1EgtuzPCxMhXQAzFCYtXjtMoLvg/TD59Wd0uyqNAZG+RGvQ4ehem63W + CVqlG0hyIAe3K2U0qOuzA6ndzygwWmPuBxIXAvPTUtYjy/NgcMmhwdrLxj21QHa8qA2DEQGBbues + /Qbr+QRSs/1R2D0a34LnBtwFTx0/C3JQCpK43dH68Bq+NrwjgXSTpxlaaRXqHMXpElU9b9UGX8dp + Gb6EXtYgCKHEFF0QXaQRJj0HHDvPuYJgAhV+CjyYSXeoEYbT1wRtPFSQXmx9EasCpNrXSa3kJPq+ + hOkEjDoKtMjTDbrRSfQBXafFukwuT+jAy8YmRD3ieZMEEJOYDI+XCMyWQEYJmxBnbr/ZrSIFtDVM + mNK8KkZX6Fut1zADqkdE3ehoo7WB5/boKAiYgAL3tKhrN9QF/dg4YJbGPXFSwLS17LxaRAGFZEO9 + D4g+mAQe0iBuEBzWItDPv6Evy2S+6sz/ifIZ/gzQ8730ekFLt5baLxyE+rwagY2fmajEUBYHJdgO + BrH9Hlyh5/fFQzLvbNwUhWrNMnczGiUnOHjzz9M5OPa48CapCJBs4POE3Ws0tt0pqSqWrbaWCtp3 + GHCm217G/5cZpucdF/T7o4oJw2h6kvsEAvEMgmNoOEZ2jA4cvxq9HwJQlcalEsbM9W1C2RsxL1MV + H40CdkIUNNuYLAo8z2e0ur0ZPftg6P5cSQZ7joaTHQUB7uf5i2efnoeM7Pyeh6G+Qv06we4BxzQQ + VZN+xl0azLypL929ctbrFoAMfAi2zU6ZgOpvJx+TLpfxlcnVfC2hV4DLluqiBUGDkEd6r0ewasDT + Xt9uYBSvb623V3I9GHrgAOw5uvHrLpQP+TzwgTkDPhhYEeH3LsXGMn6zgemMz+Am+bS628ql8zxf + VHJnsOxWNbca3x54PnePCMs/fkGf51qtF9CRdcLnUz295xAXzDOttSxPJxga3wk8vbr7He6pwNg1 + D9vYjAa98d5Ynt5ziAsa/zHNvP0bd0fgfDIhAAA= headers: Alt-Svc: - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 @@ -50,7 +50,7 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Fri, 03 Feb 2023 07:02:08 GMT + - Fri, 03 Feb 2023 07:48:05 GMT Instance: - time-public-api2 Referrer-Policy: @@ -68,11 +68,11 @@ interactions: X-Content-Type-Options: - nosniff X-Request-ID: - - fcc935dc52862c5105bcd3754c37f105 + - 1012c9aa6eee4f312cfe0bf58f2b58cf X-Service-Level: - GREEN X-Toggl-Request-Id: - - fcc935dc52862c5105bcd3754c37f105 + - 1012c9aa6eee4f312cfe0bf58f2b58cf X-We-are-hiring: - https://toggl.com/jobs/ status: diff --git a/tests/cassettes/test_entries_group_by/test_group_by_tags_and_filter.yaml b/tests/cassettes/test_entries_group_by/test_group_by_tags_and_filter.yaml new file mode 100644 index 0000000..2cd9081 --- /dev/null +++ b/tests/cassettes/test_entries_group_by/test_group_by_tags_and_filter.yaml @@ -0,0 +1,81 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.28.2 + method: GET + uri: https://api.track.toggl.com/api/v9/me/time_entries?start_date=2023-01-26T00%3A00%3A00Z&end_date=2023-01-27T00%3A00%3A00Z + response: + body: + string: !!binary | + H4sIAAAAAAAEA9WZ3Y7jNBTHX8XKLR3JH7GT+G6ZYaWVQCDNSkisViNP47bZpklInC2ziDdgJa4R + Ele8AE/GI3CSJpO6KZluacIg9aZO1Nrndz7+5/jNj04UOpL6JCCU48CbOds0XxeZmuu76gnxCcfE + nzlZnr7Tc7Nb9HyXcY/CslHFul5LyjieOfdRHKv7WDtyoeJCz5zCqNw40qGYsitMrqh4TamkXDL+ + GcYSY6d6J816r3BXMvYdPA3LXJkoTWAvHoN/DHUxz6Nst+Rcp5tNmUTmQaIXcZxuUabyIkqWKF2g + V9+8F0iFYa6LQhcoSuCz1IVBWZTpOEo0/LpRy8KRbxzzkGlZlFmWwnbf1utwrOoRodjzscCwCFtJ + k/jBkSYv4Wyqf7B6193BdP5e53ehjrXR4V31/s5MZQHLteEFJYyxmVNa37a26etvrc1/mnXMsE+p + oFMwI9LlkpDuaMeY1VhtZtSl7gCzl9EPj8R0nqc5mseRTgARcEBRge5jlayRSkIA+a4Edgt4x0Qb + fWvUJrs8wAPPnAKgO0nQ7QDiIYANYxsg+T/Qo1eYvcaedIVkQXfEKeiR6ehhvztaP/wawDY9yA3/ + mC+fTez9V/QwIxzce/yCh8Erpes9SQ8HNj0W0CGALz6UuUa30TKB0vZVGpaxRqo0K8if0byumXdQ + tedQ/aDuQRUyKooL9KooyotXvtr58HSh5/se1L7TQo/62CUBw2eJFeJLHkg+mDcbvDY7HlRiyg6+ + v37/+Ce6iZJE513lssTGCSKj50wXzHKtqfY0hu8Rl2JQKKOHCfEkYSANB8KkouFLeqALBQ0GdeGz + CZN2+90JL8iOHBGIvhA+P1EgtuzPCxMhXQAzFCYtXjtMoLvg/TD59Wd0uyqNAZG+RGvQ4ehem63W + CVqlG0hyIAe3K2U0qOuzA6ndzygwWmPuBxIXAvPTUtYjy/NgcMmhwdrLxj21QHa8qA2DEQGBbues + /Qbr+QRSs/1R2D0a34LnBtwFTx0/C3JQCpK43dH68Bq+NrwjgXSTpxlaaRXqHMXpElU9b9UGX8dp + Gb6EXtYgCKHEFF0QXaQRJj0HHDvPuYJgAhV+CjyYSXeoEYbT1wRtPFSQXmx9EasCpNrXSa3kJPq+ + hOkEjDoKtMjTDbrRSfQBXafFukwuT+jAy8YmRD3ieZMEEJOYDI+XCMyWQEYJmxBnbr/ZrSIFtDVM + mNK8KkZX6Fut1zADqkdE3ehoo7WB5/boKAiYgAL3tKhrN9QF/dg4YJbGPXFSwLS17LxaRAGFZEO9 + D4g+mAQe0iBuEBzWItDPv6Evy2S+6sz/ifIZ/gzQ8730ekFLt5baLxyE+rwagY2fmajEUBYHJdgO + BrH9Hlyh5/fFQzLvbNwUhWrNMnczGiUnOHjzz9M5OPa48CapCJBs4POE3Ws0tt0pqSqWrbaWCtp3 + GHCm217G/5cZpucdF/T7o4oJw2h6kvsEAvEMgmNoOEZ2jA4cvxq9HwJQlcalEsbM9W1C2RsxL1MV + H40CdkIUNNuYLAo8z2e0ur0ZPftg6P5cSQZ7joaTHQUB7uf5i2efnoeM7Pyeh6G+Qv06we4BxzQQ + VZN+xl0azLypL929ctbrFoAMfAi2zU6ZgOpvJx+TLpfxlcnVfC2hV4DLluqiBUGDkEd6r0ewasDT + Xt9uYBSvb623V3I9GHrgAOw5uvHrLpQP+TzwgTkDPhhYEeH3LsXGMn6zgemMz+Am+bS628ql8zxf + VHJnsOxWNbca3x54PnePCMs/fkGf51qtF9CRdcLnUz295xAXzDOttSxPJxga3wk8vbr7He6pwNg1 + D9vYjAa98d5Ynt5ziAsa/zHNvP0bd0fgfDIhAAA= + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0 + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 03 Feb 2023 07:48:05 GMT + Instance: + - time-public-api2 + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - nginx + Strict-Transport-Security: + - max-age=15552000; includeSubDomains + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: + - 1.1 google + X-Content-Type-Options: + - nosniff + X-Request-ID: + - 3461241a983f5db01e7ae9f26b929aeb + X-Service-Level: + - GREEN + X-Toggl-Request-Id: + - 3461241a983f5db01e7ae9f26b929aeb + X-We-are-hiring: + - https://toggl.com/jobs/ + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/test_entries_list/test_list.yaml b/tests/cassettes/test_entries_list/test_list.yaml index 78fb3db..6a01cd5 100644 --- a/tests/cassettes/test_entries_list/test_list.yaml +++ b/tests/cassettes/test_entries_list/test_list.yaml @@ -15,31 +15,31 @@ interactions: response: body: string: !!binary | - H4sIAAAAAAAEA82Z3YrjNhTHX0X4thnQh+UP3W1nurDQ0sIUCl2WQRNrEm8c27XlTWdL36CFXpdC - r/oCfbI+Qo+deGxFqSeT2mYhN5FNIp3f+Z8vvf3JiSNH0ICEhHIc+gtnlxWbMpdLdVc/IQHhmAQL - Jy+y92qp94t+4DLuU1jWstw0a2mVJAvnPk4SeZ8oRzzIpFQLp9Sy0I5wKKbsCpMr6n1LqaBcMP4Z - xgJjp34ny61XuCsY+x6eRlUhdZylsBefwT9GqlwWcb5fcq6z7bZKY/0o0KskyXYol0UZpyuUPaA3 - 33zwkIyiQpWlKlGcwmelSo3yOFdJnCr4dS1XpSPeOvoxV6Ks8jyD7b5r1uFY9SNCsR9gD8MibCVL - k0dH6KKCs0n7YM2uu4Op4oMq7iKVKK2iu/r9vZmqEpYbw3uUMMYWTmV825mmb761Nv950THDAaUe - nYMZES4XhHRHO8WswWoyoy51B5i9jn98IqaKIivQMolVCoiAA4pLdJ/IdINkGgHI9xWwe4B3dLxV - t1pu8/EBHnnmHADdWUS3B4iHAB4YmwDJHPQMwZ0hNMsb5+BE5uOEg+c5YZMTRIH/jIyjqewyTj2n - m5wTZoSDy06fxLBgoXD9Zznh0OTEQjqE6tXHqlDoNl6lkK6+yqIqUUhWeg0xMV42efAOMvESMhrk - MsgsWsZJid6UZTV6NmtEhsPuhBPDCwIf8tl5IqMBdknI8EUFCAkEDwXvuaWdzA54TXY8rAskU2b/ - /Pnr3+gmTlNVdNnopTqxnGlEU7em6tUNgU9ciqHqmFwmxBeEQbnXOZFl6ppGIOhRrefRcLDW+2Rk - 0m6/O+GI7MiJoi/wvICfWfS17C+TiSdcADMkkxavKRPoGLgtk99/QbfrSmsovFdoA7U1uld6p1SK - 1tkWghyUeLu11Aoq5ouF1O5nEhitMftC4p6H+Xkh64nlZTC44NA09aKxLaQ9L2rCYMQDoZsxq980 - fTpCOmx/EnZPxjfguSF3wVOnj4IcKgVB3O5oNrwDXxPeCSHdFFmO1kpGqkBJtkJ1H1u3ttdJVkWv - oT/VCCSU6rIT0SjNLbEccOo453oEE8jwc+DBTLhDzS2cviFo4qEesbT1RSJLKNW+TptKTqAfKpg4 - wPiiRA9FtkU3Ko0/ouus3FTp+ISOvGxqQtQnvj+LgJjAZHhkRGBeBGWUZxLizLUb2FopUFvD1Cgr - 6mR0hb5TagNznWbs042DtkppeG6Og8KQeZDgnm9S2w11op8aB8zHuO+dJZg2l12WiyigEGyo94Gi - D6Z7xzSIG4bHuQjq5z/Ql1W6XHfmf2H5DH8G6HkvvI5o6dZS/cRBaMDrsdb0kYkKDGlxsATbwyCm - 34MrWH5fPqbLzsaHpFCvGeY+jDvJGQ5++Of5HBz73PNnyQgQbODzjN0bNKbdKakzllltrSS07zC0 - zHZWxP+fEcbyjhH9/mTFhGHcPMsdAQE9Q8ExNAYje0ZHjl+P048ByLrGpQJGx80NQWWNjVeZTE6q - gJ2hgsM2ZlOB7weM1jcyk0cfDN2fK8hgz3HgZKogxHacHz36WB4ysfP7Pob8CvnrDLuHHNPQq5v0 - C+7HsA/3ccLtpTOrWwAy8CHHI2DmQfY3g4/OVqvkShdyuRHQK8AFSn15gqBBKGLV6xGMHPC817cb - mMTrW+v1Uq4PQw8cgj0nN37ThfIhnwc+MGfARwMr4gXWRddUxj9sYD7jM7gdPi/vtuXSZZ7v1eXO - YNqtc249vjUDDuXuicLyr9/Q54WSmwfoyLrC56WebjnEiHGmtZbh6QRD4zuDp9f3ucM9FRi74WEa - m9HQGu9N5emWQ4xo/Kcw8+5fyIRd7gYhAAA= + H4sIAAAAAAAEA9WZ3Y7jNBTHX8XKLR3JH7GT+G6ZYaWVQCDNSkisViNP47bZpklInC2ziDdgJa4R + Ele8AE/GI3CSJpO6KZluacIg9aZO1Nrndz7+5/jNj04UOpL6JCCU48CbOds0XxeZmuu76gnxCcfE + nzlZnr7Tc7Nb9HyXcY/CslHFul5LyjieOfdRHKv7WDtyoeJCz5zCqNw40qGYsitMrqh4TamkXDL+ + GcYSY6d6J816r3BXMvYdPA3LXJkoTWAvHoN/DHUxz6Nst+Rcp5tNmUTmQaIXcZxuUabyIkqWKF2g + V9+8F0iFYa6LQhcoSuCz1IVBWZTpOEo0/LpRy8KRbxzzkGlZlFmWwnbf1utwrOoRodjzscCwCFtJ + k/jBkSYv4Wyqf7B6193BdP5e53ehjrXR4V31/s5MZQHLteEFJYyxmVNa37a26etvrc1/mnXMsE+p + oFMwI9LlkpDuaMeY1VhtZtSl7gCzl9EPj8R0nqc5mseRTgARcEBRge5jlayRSkIA+a4Edgt4x0Qb + fWvUJrs8wAPPnAKgO0nQ7QDiIYANYxsg+T/Qo1eYvcaedIVkQXfEKeiR6ehhvztaP/wawDY9yA3/ + mC+fTez9V/QwIxzce/yCh8Erpes9SQ8HNj0W0CGALz6UuUa30TKB0vZVGpaxRqo0K8if0byumXdQ + tedQ/aDuQRUyKooL9KooyotXvtr58HSh5/se1L7TQo/62CUBw2eJFeJLHkg+mDcbvDY7HlRiyg6+ + v37/+Ce6iZJE513lssTGCSKj50wXzHKtqfY0hu8Rl2JQKKOHCfEkYSANB8KkouFLeqALBQ0GdeGz + CZN2+90JL8iOHBGIvhA+P1EgtuzPCxMhXQAzFCYtXjtMoLvg/TD59Wd0uyqNAZG+RGvQ4ehem63W + CVqlG0hyIAe3K2U0qOuzA6ndzygwWmPuBxIXAvPTUtYjy/NgcMmhwdrLxj21QHa8qA2DEQGBbues + /Qbr+QRSs/1R2D0a34LnBtwFTx0/C3JQCpK43dH68Bq+NrwjgXSTpxlaaRXqHMXpElU9b9UGX8dp + Gb6EXtYgCKHEFF0QXaQRJj0HHDvPuYJgAhV+CjyYSXeoEYbT1wRtPFSQXmx9EasCpNrXSa3kJPq+ + hOkEjDoKtMjTDbrRSfQBXafFukwuT+jAy8YmRD3ieZMEEJOYDI+XCMyWQEYJmxBnbr/ZrSIFtDVM + mNK8KkZX6Fut1zADqkdE3ehoo7WB5/boKAiYgAL3tKhrN9QF/dg4YJbGPXFSwLS17LxaRAGFZEO9 + D4g+mAQe0iBuEBzWItDPv6Evy2S+6sz/ifIZ/gzQ8730ekFLt5baLxyE+rwagY2fmajEUBYHJdgO + BrH9Hlyh5/fFQzLvbNwUhWrNMnczGiUnOHjzz9M5OPa48CapCJBs4POE3Ws0tt0pqSqWrbaWCtp3 + GHCm217G/5cZpucdF/T7o4oJw2h6kvsEAvEMgmNoOEZ2jA4cvxq9HwJQlcalEsbM9W1C2RsxL1MV + H40CdkIUNNuYLAo8z2e0ur0ZPftg6P5cSQZ7joaTHQUB7uf5i2efnoeM7Pyeh6G+Qv06we4BxzQQ + VZN+xl0azLypL929ctbrFoAMfAi2zU6ZgOpvJx+TLpfxlcnVfC2hV4DLluqiBUGDkEd6r0ewasDT + Xt9uYBSvb623V3I9GHrgAOw5uvHrLpQP+TzwgTkDPhhYEeH3LsXGMn6zgemMz+Am+bS628ql8zxf + VHJnsOxWNbca3x54PnePCMs/fkGf51qtF9CRdcLnUz295xAXzDOttSxPJxga3wk8vbr7He6pwNg1 + D9vYjAa98d5Ynt5ziAsa/zHNvP0bd0fgfDIhAAA= headers: Alt-Svc: - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 @@ -50,7 +50,7 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Fri, 03 Feb 2023 07:02:09 GMT + - Fri, 03 Feb 2023 07:48:05 GMT Instance: - time-public-api2 Referrer-Policy: @@ -68,11 +68,11 @@ interactions: X-Content-Type-Options: - nosniff X-Request-ID: - - a62a2f942c009e485790366413698216 + - d37a26641b2eb9d772d2e2ad8364d785 X-Service-Level: - GREEN X-Toggl-Request-Id: - - a62a2f942c009e485790366413698216 + - d37a26641b2eb9d772d2e2ad8364d785 X-We-are-hiring: - https://toggl.com/jobs/ status: diff --git a/tests/test_entries_group_by.py b/tests/test_entries_group_by.py index 20b99fb..94d5e6a 100644 --- a/tests/test_entries_group_by.py +++ b/tests/test_entries_group_by.py @@ -36,3 +36,29 @@ def test_group_by_tags(): """ ) + +@pytest.mark.vcr +@pytest.mark.block_network +def test_group_by_tags_and_filter(): + runner = CliRunner() + with runner.isolated_filesystem(): + result = runner.invoke( + cli, + ["entries", "--project-id", "178435728", "group-by", "--field", "tags", "--start-date", "2023-01-26", "--end-date", "2023-01-27"], + env=env, + ) + assert result.exit_code == 0 + assert ( + result.output + == """ Time Entries + + tags Duration + ───────────────────────── + type:support 5:44 + type:sync 3:00 + type:meeting 2:04 + type:goal 0:35 + + +""" + ) diff --git a/tests/test_entries_list.py b/tests/test_entries_list.py index 46e8dac..1f1cf93 100644 --- a/tests/test_entries_list.py +++ b/tests/test_entries_list.py @@ -38,13 +38,13 @@ def test_list(): blank and adjust for timeStamp - 2023-01-26 Community: Fix 09:45 PM 09:45 PM 0:00 + 2023-02-03 Community: Fix 09:45 PM 09:45 PM 0:00 type:support parsing error client port is blank and adjust for timeStamp - 2023-01-26 Community: Fix 09:45 PM 09:45 PM 0:00 + 2023-02-03 Community: Fix 09:45 PM 09:45 PM 0:00 type:support parsing error client port is blank and diff --git a/toggl_track/cli.py b/toggl_track/cli.py index d7e7fe1..0ac4712 100644 --- a/toggl_track/cli.py +++ b/toggl_track/cli.py @@ -1,5 +1,5 @@ -import datetime -from datetime import timedelta +import datetime as dt +from typing import List import click @@ -8,9 +8,9 @@ # default reference date for all date options -now = datetime.datetime.now() +now = dt.datetime.now() -def as_str(reference_date: datetime = now) -> str: +def as_str(reference_date: dt.datetime = now) -> str: """Formats a `reference_date` into a string. Helper function to be used as a default value for click options. @@ -26,16 +26,23 @@ def cli(): @cli.group() -def entries(): +@click.option( + '--project-id', + '-p', + type=click.INT, + multiple=True) +@click.pass_context +def entries(ctx: click.Context, project_id: List[int]): "Time entries commands" - pass + ctx.ensure_object(dict) + ctx.obj['project_id'] = project_id @entries.command(name="list") @click.option( "--start-date", type=click.DateTime(), - default=as_str(now - timedelta(hours=24)), + default=as_str(now - dt.timedelta(hours=24)), help="Start date (default: 24 hours ago)" ) @click.option( @@ -43,14 +50,15 @@ def entries(): type=click.DateTime(), default=as_str(now) ) -def list_entries(start_date: datetime, end_date: datetime): +@click.pass_context +def list_entries(ctx: click.Context, start_date: dt.datetime, end_date: dt.datetime): """Returns a list of the latest time entries (default: last 24 hours)""" client = TimeEntries.from_environment() click.echo( TimeEntriesListResult( - client.list(start_date, end_date) + client.list(start_date, end_date, project_ids=ctx.obj['project_id']) ) ) @@ -63,7 +71,7 @@ def list_entries(start_date: datetime, end_date: datetime): @click.option( "--start-date", type=click.DateTime(), - default=as_str(now - timedelta(hours=24)), + default=as_str(now - dt.timedelta(hours=24)), help="Start date (default: 24 hours ago)" ) @click.option( @@ -71,14 +79,15 @@ def list_entries(start_date: datetime, end_date: datetime): type=click.DateTime(), default=as_str(now) ) -def group_by_entries(start_date: datetime, end_date: datetime, field: str = "tags"): +@click.pass_context +def group_by_entries(ctx: click.Context, start_date: dt.datetime, end_date: dt.datetime, field: str = "tags"): """Returns a list of time entries grouped by a field""" client = TimeEntries.from_environment() click.echo( TimeEntriesGroupByResult( - client.list(start_date, end_date), + client.list(start_date, end_date, project_ids=ctx.obj['project_id']), key_func=GroupByCriterion(field) ) ) diff --git a/toggl_track/result.py b/toggl_track/result.py index 410813b..cac1fe7 100644 --- a/toggl_track/result.py +++ b/toggl_track/result.py @@ -24,6 +24,7 @@ def __str__(self) -> str: table = Table(title="Time Entries", box=box.SIMPLE) table.add_column("At") + # table.add_column("Project") table.add_column("Description") table.add_column("Start") table.add_column("Stop") @@ -33,6 +34,7 @@ def __str__(self) -> str: for e in self.entries: table.add_row( e.at.strftime("%Y-%m-%d"), + # str(e.project_id), e.description, e.start.strftime("%I:%M %p"), "" if not e.stop else e.stop.strftime("%I:%M %p"), diff --git a/toggl_track/toggl.py b/toggl_track/toggl.py index 7ad7bfa..3eff6ef 100644 --- a/toggl_track/toggl.py +++ b/toggl_track/toggl.py @@ -39,7 +39,7 @@ def from_environment(cls) -> "TimeEntries": ) return cls(api_token=os.environ["TOGGL_API_TOKEN"]) - def list(self, start_date: datetime, end_date: datetime) -> List[TimeEntry]: + def list(self, start_date: datetime, end_date: datetime, project_ids: List[int] = ()) -> List[TimeEntry]: """Fetches the time entries between `start_date` and `end_date` dates. Time Entries API v9 @@ -59,4 +59,11 @@ def list(self, start_date: datetime, end_date: datetime) -> List[TimeEntry]: if resp.status_code != 200: raise Exception(resp.text) - return parse_raw_as(List[TimeEntry], resp.text) + # it looks like the API doesn't support filtering, so I suppose + # we have to do it ourselves + entries = parse_raw_as(List[TimeEntry], resp.text) + + if project_ids: + return filter(lambda entry: entry.project_id in project_ids, entries) + + return entries