text: from __future__ import absolute_import
  
  import datetime
  
  from django.utils import timezone
  from parsimonious.exceptions import IncompleteParseError
  
  from sentry.api.event_search import (
      convert_endpoint_params, get_snuba_query_args, parse_search_query,
      InvalidSearchQuery, SearchFilter, SearchKey, SearchValue
  )
  from sentry.testutils import TestCase
  
  
  class EventSearchTest(TestCase):
      def test_parse_search_query(self):
          # test with raw search query at the end
          assert parse_search_query('user.email:foo@example.com release:1.2.1 hello') == [
              SearchFilter(
                  key=SearchKey(name='user.email'),
                  operator="=",
                  value=SearchValue(raw_value='foo@example.com', type='string'),
              ),
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator="=",
                  value=SearchValue(raw_value='1.2.1', type='string'),
              ),
              SearchFilter(
                  key=SearchKey(name='message'),
                  operator='=',
                  value=SearchValue(raw_value='hello', type='string'),
              )
          ]
  
          # if the search query starts with the raw query, assume the whole thing is a raw string
          assert parse_search_query('hello user.email:foo@example.com release:1.2.1') == [
              SearchFilter(
                  key=SearchKey(name='message'),
                  operator='=',
                  value=SearchValue(
                      raw_value='hello user.email:foo@example.com release:1.2.1',
                      type='string'),
              ),
          ]
  
      def test_parse_search_query_timestamp(self):
          # test date format
          assert parse_search_query('timestamp>2015-05-18') == [
              SearchFilter(
                  key=SearchKey(name='timestamp'),
                  operator=">",
                  value=SearchValue(
                      raw_value=datetime.datetime(
                          2015,
                          5,
                          18,
                          0,
                          0,
                          tzinfo=timezone.utc),
                      type='timestamp'),
              ),
          ]
          # test date time format
          assert parse_search_query('timestamp>2015-05-18T10:15:01') == [
              SearchFilter(
                  key=SearchKey(name='timestamp'),
                  operator=">",
                  value=SearchValue(
                      raw_value=datetime.datetime(
                          2015,
                          5,
                          18,
                          10,
                          15,
                          1,
                          tzinfo=timezone.utc),
                      type='timestamp'),
              ),
          ]
  
          # test date time format w microseconds
          assert parse_search_query('timestamp>2015-05-18T10:15:01.103') == [
              SearchFilter(
                  key=SearchKey(name='timestamp'),
                  operator=">",
                  value=SearchValue(
                      raw_value=datetime.datetime(
                          2015,
                          5,
                          18,
                          10,
                          15,
                          1,
                          103000,
                          tzinfo=timezone.utc),
                      type='timestamp'),
              ),
          ]
  
      def test_parse_search_query_quoted_val(self):
          assert parse_search_query('release:"a release"') == [
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator='=',
                  value=SearchValue(raw_value='a release', type='string'),
              ),
          ]
  
      def test_parse_search_query_weird_values(self):
          # quotes within quotes
          assert parse_search_query('release:"a"thing""') == [
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator='=',
                  value=SearchValue(raw_value='a"thing"', type='string'),
              ),
          ]
  
          # newline within quote
          assert parse_search_query('release:"a\nrelease"') == [
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator='=',
                  value=SearchValue(raw_value='a\nrelease', type='string')
              ),
          ]
          # newline outside quote
          with self.assertRaises(IncompleteParseError):
              parse_search_query('release:a\nrelease')
  
          # tab within quote
          assert parse_search_query('release:"a\trelease"') == [
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator='=',
                  value=SearchValue(raw_value='a\trelease', type='string')
              ),
          ]
          # tab outside quote
          assert parse_search_query('release:a\trelease') == [
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator='=',
                  value=SearchValue(raw_value='a', type='string'),
              ),
              SearchFilter(
                  key=SearchKey(name='message'),
                  operator='=',
                  value=SearchValue(raw_value='\trelease', type='string')
              ),
          ]
  
          # escaped quotes
          assert parse_search_query('release:"a\"thing\""') == [
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator='=',
                  value=SearchValue(raw_value='a"thing"', type='string')
              ),
          ]
          assert parse_search_query('release:"a\"\"release"') == [
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator='=',
                  value=SearchValue(raw_value='a""release', type='string')
              ),
          ]
  
          # poorly escaped quotes
          assert parse_search_query('release:"a release\"') == [
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator='=',
                  value=SearchValue(raw_value='a release', type='string')
              ),
          ]
          assert parse_search_query('release:\"a release "') == [
              SearchFilter(
                  key=SearchKey(name='release'),
                  operator='=',
                  value=SearchValue(raw_value='a release ', type='string')
              ),
          ]
  
      def test_parse_search_query_invalid(self):
          with self.assertRaises(InvalidSearchQuery):
              parse_search_query('fruit:apple release:1.2.1')
  
      def test_get_snuba_query_args(self):
          assert get_snuba_query_args('user.email:foo@example.com release:1.2.1 hello', {
              'project_id': [1, 2, 3],
              'start': datetime.datetime(2015, 5, 18, 10, 15, 1, tzinfo=timezone.utc),
              'end': datetime.datetime(2015, 5, 19, 10, 15, 1, tzinfo=timezone.utc),
          }) == {
              'conditions': [
                  ['email', '=', 'foo@example.com'],
                  ['sentry:release', '=', '1.2.1'],
                  [['positionCaseInsensitive', ['message', "'hello'"]], '!=', 0],
              ],
              'filter_keys': {'project_id': [1, 2, 3]},
              'start': datetime.datetime(2015, 5, 18, 10, 15, 1, tzinfo=timezone.utc),
              'end': datetime.datetime(2015, 5, 19, 10, 15, 1, tzinfo=timezone.utc),
          }
  
      def test_get_snuba_query_args_no_search(self):
          assert get_snuba_query_args(params={
              'project_id': [1, 2, 3],
              'start': datetime.datetime(2015, 5, 18, 10, 15, 1, tzinfo=timezone.utc),
              'end': datetime.datetime(2015, 5, 19, 10, 15, 1, tzinfo=timezone.utc),
          }) == {
              'conditions': [],
              'filter_keys': {'project_id': [1, 2, 3]},
              'start': datetime.datetime(2015, 5, 18, 10, 15, 1, tzinfo=timezone.utc),
              'end': datetime.datetime(2015, 5, 19, 10, 15, 1, tzinfo=timezone.utc),
          }
  
      def test_convert_endpoint_params(self):
          assert convert_endpoint_params({
              'project_id': [1, 2, 3],
              'start': datetime.datetime(2015, 5, 18, 10, 15, 1, tzinfo=timezone.utc),
              'end': datetime.datetime(2015, 5, 19, 10, 15, 1, tzinfo=timezone.utc),
          }) == [
              SearchFilter(
                  key=SearchKey(name='start'),
                  operator='=',
                  value=SearchValue(
                      raw_value=datetime.datetime(
                          2015,
                          5,
                          18,
                          10,
                          15,
                          1,
                          tzinfo=timezone.utc),
                      type='timestamp')
              ),
              SearchFilter(
                  key=SearchKey(name='project_id'),
                  operator='=',
                  value=SearchValue(raw_value=[1, 2, 3], type='list')
              ),
              SearchFilter(
                  key=SearchKey(name='end'),
                  operator='=',
                  value=SearchValue(
                      raw_value=datetime.datetime(
                          2015,
                          5,
                          19,
                          10,
                          15,
                          1,
                          tzinfo=timezone.utc),
                      type='timestamp')
              ),
          ]
  