<commit_before>#!/usr/bin/python2.7
"""Tests for csharp generator."""

from google.apputils import basetest
from googleapis.codegen import csharp_generator

class NestedClassNameTest(basetest.TestCase):

  NESTED_API = {
      'name': 'nestor',
      'version': 'v1',
      'resources': {},
      'schemas': {
          'A': {
              'id': 'A',
              'type': 'object',
              'properties': {
                  'B': {
                      'id': 'B',
                      'type': 'object',
                      'properties': {
                          'count': {
                              'type': 'integer',
                              'format': 'int32'
                              }
                          }
                      }
                  }
              },
          'C': {
              'id': 'C',
              'type': 'array',
              'items': {
                  '$ref': 'A'
                  }
              },
          'D': {
              'id': 'D',
              'type': 'array',
              'items': {
                  'type': 'object',
                  'properties': {
                      'foo': {
                          'type': 'string'
                          }
                      }
                  }
              },
          'E': {
              'id': 'E',
              'type': 'object',
              'properties': {
                  'F': {
                      'type': 'array',
                      'items': {
                          'type': 'object',
                          'properties': {
                              'aproperty': {
                                  'type': 'string'
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }

  COMPUTE_EXTRACT = {
      'name': 'computeextract',
      'version': 'v1',
      'resources': {},
      'schemas': {
          'MachineType': {
              'id': 'MachineType',
              'type': 'object',
              'properties': {
                  'ephemeralDisks': {
                      'type': 'array',
                      'items': {
                          'type': 'object',
                          'properties': {
                              'diskGb': {
                                  'type': 'integer',
                                  'format': 'int32'
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }

  FREEBASE_EXTRACT = {
      'name': 'freebase',
      'version': 'v1',
      'resources': {},
      'schemas': {
          'TopicStatslinkcount': {
              'id': 'TopicStatslinkcount',
              'type': 'object',
              'properties': {
                  'type': {
                      'type': 'string',
                      'default': 'custom'
                      },
                  'values': {
                      'type': 'array',
                      'items': {
                          'type': 'object',
                          'properties': {
                              'count': {
                                  'type': 'integer',
                                  'format': 'int32'
                                  },
                              'id': {
                                  'type': 'string'
                                  },
                              'values': {
                                  'type': 'array',
                                  'items': {
                                      'type': 'object',
                                      'properties': {
                                          'count': {
                                              'type': 'integer',
                                              'format': 'int32'
                                              },
                                          'id': {
                                              'type': 'string'
                                              },
                                          'values': {
                                              'type': 'array',
                                              'items': {
                                                  'type': 'object',
                                                  'properties': {
                                                      'count': {
                                                          'type': 'integer',
                                                          'format': 'int32'
                                                          },
                                                      'id': {
                                                          'type': 'string'
                                                          }
                                                      }
                                                  }
                                              }
                                          }
                                      }
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }

  def testNestedClassName(self):
    gen = csharp_generator.CSharpGenerator(discovery=self.NESTED_API)
    gen.AnnotateApiForLanguage(gen.api)
    self.assertEquals({'A', 'A.B', 'C', 'D', 'DItems', 'E', 'E.F'},
                      set(gen.api._schemas))
    b_schema = gen.api._schemas['A.B']
    c_schema = gen.api._schemas['C']
    self.assertEquals('A.B', b_schema.packageRelativeClassName)
    # TODO(user): This is the current behavior.  We could change it for
    # csharp by annotating schemas and setting codeType to
    # packageRelativeClassName, but that will uncover other bugs -- due to the
    # many ways of getting at a class name (codeType, code_type, safeCodeType,
    # safe_code_type, class_name, className, safe...) there is inconsistency in
    # the code base, and we'll end up prepending parent names in some cases more
    # than once.
    self.assertEquals('B', b_schema.code_type)
    self.assertEquals('System.Collections.Generic.IList<A>', c_schema.code_type)
    d_schema = gen.api._schemas['D']
    self.assertEquals('System.Collections.Generic.IList<DItems>',
                      d_schema.code_type)

  def testAbsurdlyNestedButRealClassNames(self):
    gen = csharp_generator.CSharpGenerator(discovery=self.FREEBASE_EXTRACT)
    gen.AnnotateApiForLanguage(gen.api)
    schema_names = sorted(s.class_name.split('.')[-1]
                          for s in gen.api._schemas.itervalues())
    expected = sorted(['TopicStatslinkcount',
                       'ValuesData',  # nested 1
                       'ValuesDataSchema',  # nested 2
                       'ValuesData',  # nested 3
                      ])
    self.assertEquals(expected, schema_names)

  def testNestedArray(self):
    gen = csharp_generator.CSharpGenerator(discovery=self.COMPUTE_EXTRACT)
    gen.AnnotateApiForLanguage(gen.api)
    self.assertEquals({'MachineType', 'MachineType.ephemeralDisks'},
                      set(gen.api._schemas))
    # The array type in this case is not available in the schema list; we have
    # to spelunk into the properties to get at it.
    machine_type_schema = gen.api._schemas['MachineType']
    # While properties in discovery are dictionaries, for some reason
    # the dictionary is overridden and replaced by a dict in the object model.
    disk_array = [p for p in machine_type_schema['properties']
                  if p['wireName'] == 'ephemeralDisks'][0]
    self.assertEquals(
        'System.Collections.Generic.IList<MachineType.EphemeralDisksData>',
        disk_array.code_type)
    ephemeral_disk_schema = gen.api._schemas['MachineType.ephemeralDisks']
    self.assertEquals('EphemeralDisksData', ephemeral_disk_schema.safeClassName)

class PackagePathTest(basetest.TestCase):

  def testPackagePath(self):
    discovery = {
        'name': 'foo',
        'version': 'v1',
        'packagePath': 'nougat',
        'schemas': {},
        'resources': {},
        }
    gen = csharp_generator.CSharpGenerator(discovery)
    gen.AnnotateApiForLanguage(gen.api)
    api = gen.api
    self.assertEquals('Google.Apis.Nougat.Foo.v1', api.module.name)
    self.assertEquals('Google.Apis.Nougat.Foo.v1.Data', api.model_module.name)

class VersionWithDashTest(basetest.TestCase):

  def testVersionWithDash(self):
    discovery = {
        'name': 'foo',
        'version': 'v1-dash',
        'schemas': {},
        'resources': {},
        }
    gen = csharp_generator.CSharpGenerator(discovery)
    gen.AnnotateApiForLanguage(gen.api)
    api = gen.api
    self.assertEquals('Google.Apis.Foo.v1dash', api.module.name)
    self.assertEquals('Google.Apis.Foo.v1dash.Data', api.model_module.name)

class MemberNameTest(basetest.TestCase):

  def testMemberNameConflictWithParentClass(self):
    api = {
        'name': 'groups',
        'version': 'v1',
        'schemas': {
            'Groups': {
                'id': 'Groups',
                'type': 'object',
                'properties': {
                    'groups': {
                        'type': 'string'
                        }
                    }
                }
            }
        }
    gen = csharp_generator.CSharpGenerator(discovery=api)
    gen.AnnotateApiForLanguage(gen.api)
    groups_schema = gen.api._schemas['Groups']
    groups_prop = groups_schema['properties'][0]
    self.assertEquals('GroupsValue', groups_prop.memberName)

  def testMemberNameConflictWithParentClassWithUnderscores(self):
    api = {
        'name': 'groups',
        'version': 'v1',
        'schemas': {
            'GroupsThing': {
                'id': 'groups_thing',
                'type': 'object',
                'properties': {
                    'groups_thing': {
                        'type': 'string'
                        }
                    }
                }
            }
        }
    gen = csharp_generator.CSharpGenerator(discovery=api)
    gen.AnnotateApiForLanguage(gen.api)
    groups_schema = gen.api._schemas['GroupsThing']
    groups_prop = groups_schema['properties'][0]
    self.assertEquals('GroupsThingValue', groups_prop.memberName)

class MapTest(basetest.TestCase):

  def testMapNameIsConsistent(self):
    api = {
        'name': 'discovery',
        'version': 'v1',
        'schemas': {
            'RestDescription': {
                'id': 'RestDescription',
                'type': 'object',
                'properties': {
                    'auth': {
                        'type': 'object',
                        'properties': {
                            'oauth2': {
                                'type': 'object',
                                'properties': {
                                    'scopes': {
                                        'type': 'object',
                                        'additionalProperties': {
                                            'type': 'object',
                                            'properties': {
                                                'description': {
                                                    'type': 'string',
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    gen = csharp_generator.CSharpGenerator(discovery=api)
    gen.AnnotateApiForLanguage(gen.api)
    schemas = gen.api._schemas
    oauth2_schema = schemas['RestDescription.auth.oauth2']
    scopes_schema = schemas['RestDescription.auth.oauth2.scopesElement']
    child_schema = oauth2_schema.children[0]
    self.assertEquals(scopes_schema, child_schema)
    self.assertEquals('ScopesDataElement', scopes_schema.safeClassName)

if __name__ == '__main__':
  basetest.main()
<commit_msg>Fix C# generator tests<commit_after>#!/usr/bin/python2.7
"""Tests for csharp generator."""

from google.apputils import basetest
from googleapis.codegen import csharp_generator

class NestedClassNameTest(basetest.TestCase):

  NESTED_API = {
      'name': 'nestor',
      'version': 'v1',
      'revision': '20190804',
      'resources': {},
      'schemas': {
          'A': {
              'id': 'A',
              'type': 'object',
              'properties': {
                  'B': {
                      'id': 'B',
                      'type': 'object',
                      'properties': {
                          'count': {
                              'type': 'integer',
                              'format': 'int32'
                              }
                          }
                      }
                  }
              },
          'C': {
              'id': 'C',
              'type': 'array',
              'items': {
                  '$ref': 'A'
                  }
              },
          'D': {
              'id': 'D',
              'type': 'array',
              'items': {
                  'type': 'object',
                  'properties': {
                      'foo': {
                          'type': 'string'
                          }
                      }
                  }
              },
          'E': {
              'id': 'E',
              'type': 'object',
              'properties': {
                  'F': {
                      'type': 'array',
                      'items': {
                          'type': 'object',
                          'properties': {
                              'aproperty': {
                                  'type': 'string'
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }

  COMPUTE_EXTRACT = {
      'name': 'computeextract',
      'version': 'v1',
      'revision': '20190804',
      'resources': {},
      'schemas': {
          'MachineType': {
              'id': 'MachineType',
              'type': 'object',
              'properties': {
                  'ephemeralDisks': {
                      'type': 'array',
                      'items': {
                          'type': 'object',
                          'properties': {
                              'diskGb': {
                                  'type': 'integer',
                                  'format': 'int32'
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }

  FREEBASE_EXTRACT = {
      'name': 'freebase',
      'version': 'v1',
      'revision': '20190804',
      'resources': {},
      'schemas': {
          'TopicStatslinkcount': {
              'id': 'TopicStatslinkcount',
              'type': 'object',
              'properties': {
                  'type': {
                      'type': 'string',
                      'default': 'custom'
                      },
                  'values': {
                      'type': 'array',
                      'items': {
                          'type': 'object',
                          'properties': {
                              'count': {
                                  'type': 'integer',
                                  'format': 'int32'
                                  },
                              'id': {
                                  'type': 'string'
                                  },
                              'values': {
                                  'type': 'array',
                                  'items': {
                                      'type': 'object',
                                      'properties': {
                                          'count': {
                                              'type': 'integer',
                                              'format': 'int32'
                                              },
                                          'id': {
                                              'type': 'string'
                                              },
                                          'values': {
                                              'type': 'array',
                                              'items': {
                                                  'type': 'object',
                                                  'properties': {
                                                      'count': {
                                                          'type': 'integer',
                                                          'format': 'int32'
                                                          },
                                                      'id': {
                                                          'type': 'string'
                                                          }
                                                      }
                                                  }
                                              }
                                          }
                                      }
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }

  def testNestedClassName(self):
    gen = csharp_generator.CSharpGenerator(discovery=self.NESTED_API)
    gen.AnnotateApiForLanguage(gen.api)
    self.assertEquals({'A', 'A.B', 'C', 'D', 'DItems', 'E', 'E.F'},
                      set(gen.api._schemas))
    b_schema = gen.api._schemas['A.B']
    c_schema = gen.api._schemas['C']
    self.assertEquals('A.B', b_schema.packageRelativeClassName)
    # TODO(user): This is the current behavior.  We could change it for
    # csharp by annotating schemas and setting codeType to
    # packageRelativeClassName, but that will uncover other bugs -- due to the
    # many ways of getting at a class name (codeType, code_type, safeCodeType,
    # safe_code_type, class_name, className, safe...) there is inconsistency in
    # the code base, and we'll end up prepending parent names in some cases more
    # than once.
    self.assertEquals('B', b_schema.code_type)
    self.assertEquals('System.Collections.Generic.IList<A>', c_schema.code_type)
    d_schema = gen.api._schemas['D']
    self.assertEquals('System.Collections.Generic.IList<DItems>',
                      d_schema.code_type)

  def testAbsurdlyNestedButRealClassNames(self):
    gen = csharp_generator.CSharpGenerator(discovery=self.FREEBASE_EXTRACT)
    gen.AnnotateApiForLanguage(gen.api)
    schema_names = sorted(s.class_name.split('.')[-1]
                          for s in gen.api._schemas.itervalues())
    expected = sorted(['TopicStatslinkcount',
                       'ValuesData',  # nested 1
                       'ValuesDataSchema',  # nested 2
                       'ValuesData',  # nested 3
                      ])
    self.assertEquals(expected, schema_names)

  def testNestedArray(self):
    gen = csharp_generator.CSharpGenerator(discovery=self.COMPUTE_EXTRACT)
    gen.AnnotateApiForLanguage(gen.api)
    self.assertEquals({'MachineType', 'MachineType.ephemeralDisks'},
                      set(gen.api._schemas))
    # The array type in this case is not available in the schema list; we have
    # to spelunk into the properties to get at it.
    machine_type_schema = gen.api._schemas['MachineType']
    # While properties in discovery are dictionaries, for some reason
    # the dictionary is overridden and replaced by a dict in the object model.
    disk_array = [p for p in machine_type_schema['properties']
                  if p['wireName'] == 'ephemeralDisks'][0]
    self.assertEquals(
        'System.Collections.Generic.IList<MachineType.EphemeralDisksData>',
        disk_array.code_type)
    ephemeral_disk_schema = gen.api._schemas['MachineType.ephemeralDisks']
    self.assertEquals('EphemeralDisksData', ephemeral_disk_schema.safeClassName)

class PackagePathTest(basetest.TestCase):

  def testPackagePath(self):
    discovery = {
        'name': 'foo',
        'version': 'v1',
        'revision': '20190804',
        'packagePath': 'nougat',
        'schemas': {},
        'resources': {},
        }
    gen = csharp_generator.CSharpGenerator(discovery)
    gen.AnnotateApiForLanguage(gen.api)
    api = gen.api
    self.assertEquals('Google.Apis.Nougat.Foo.v1', api.module.name)
    self.assertEquals('Google.Apis.Nougat.Foo.v1.Data', api.model_module.name)

class VersionWithDashTest(basetest.TestCase):

  def testVersionWithDash(self):
    discovery = {
        'name': 'foo',
        'version': 'v1-dash',
        'revision': '20190804',
        'schemas': {},
        'resources': {},
        }
    gen = csharp_generator.CSharpGenerator(discovery)
    gen.AnnotateApiForLanguage(gen.api)
    api = gen.api
    self.assertEquals('Google.Apis.Foo.v1dash', api.module.name)
    self.assertEquals('Google.Apis.Foo.v1dash.Data', api.model_module.name)

class MemberNameTest(basetest.TestCase):

  def testMemberNameConflictWithParentClass(self):
    api = {
        'name': 'groups',
        'version': 'v1',
        'revision': '20190804',
        'schemas': {
            'Groups': {
                'id': 'Groups',
                'type': 'object',
                'properties': {
                    'groups': {
                        'type': 'string'
                        }
                    }
                }
            }
        }
    gen = csharp_generator.CSharpGenerator(discovery=api)
    gen.AnnotateApiForLanguage(gen.api)
    groups_schema = gen.api._schemas['Groups']
    groups_prop = groups_schema['properties'][0]
    self.assertEquals('GroupsValue', groups_prop.memberName)

  def testMemberNameConflictWithParentClassWithUnderscores(self):
    api = {
        'name': 'groups',
        'version': 'v1',
        'revision': '20190804',
        'schemas': {
            'GroupsThing': {
                'id': 'groups_thing',
                'type': 'object',
                'properties': {
                    'groups_thing': {
                        'type': 'string'
                        }
                    }
                }
            }
        }
    gen = csharp_generator.CSharpGenerator(discovery=api)
    gen.AnnotateApiForLanguage(gen.api)
    groups_schema = gen.api._schemas['GroupsThing']
    groups_prop = groups_schema['properties'][0]
    self.assertEquals('GroupsThingValue', groups_prop.memberName)

class MapTest(basetest.TestCase):

  def testMapNameIsConsistent(self):
    api = {
        'name': 'discovery',
        'version': 'v1',
        'schemas': {
            'RestDescription': {
                'id': 'RestDescription',
                'type': 'object',
                'properties': {
                    'auth': {
                        'type': 'object',
                        'properties': {
                            'oauth2': {
                                'type': 'object',
                                'properties': {
                                    'scopes': {
                                        'type': 'object',
                                        'additionalProperties': {
                                            'type': 'object',
                                            'properties': {
                                                'description': {
                                                    'type': 'string',
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    gen = csharp_generator.CSharpGenerator(discovery=api)
    gen.AnnotateApiForLanguage(gen.api)
    schemas = gen.api._schemas
    oauth2_schema = schemas['RestDescription.auth.oauth2']
    scopes_schema = schemas['RestDescription.auth.oauth2.scopesElement']
    child_schema = oauth2_schema.children[0]
    self.assertEquals(scopes_schema, child_schema)
    self.assertEquals('ScopesDataElement', scopes_schema.safeClassName)

if __name__ == '__main__':
  basetest.main()
<|endoftext|>


<commit_before>import re

class TagsResponse:
   def __init__(self, filename, pattern):
      self.filename = filename
      self.pattern = pattern
   def __str__(self):
      return '[filename=%s pattern=%s]' % (self.filename, self.pattern)

def quote_pattern(pat):
   pat = re.sub('~', '\~', pat)
   pat = re.sub('\*', '\\\*', pat)
   return pat

class CTag:
   def __init__(self, line):
      self.fields = line.split('\t')
   def to_response(self):
      return TagsResponse(self.filename(), self.pattern())
   def tag(self):
      return self.fields[0]
   def filename(self):
      return self.fields[1]
   def pattern(self):
      return quote_pattern(self.fields[2])

class AbstractTagsSearcher:
   '''
   Tags searching, using an unspecified algorithm.
   '''
   def __init__(self, tagsfile):
      self.tagsfile = tagsfile

   def find(self, tag):
      '''
      Searches for a tag. Returns a TagsResponse, or None if not found.
      NOTE: Only returns the first match it finds.
      '''
      raise 'Abstract interface!'

class LinearTagsSearcher(AbstractTagsSearcher):
   ''' Crungey old lsearch. '''
   def find(self,tag):
      f = open(self.tagsfile, 'r')
      needle = tag + '\t'
      for line in f:
         if line.startswith(needle):
            return CTag(line).to_response()
      return None

class BinaryTagsSearcher(AbstractTagsSearcher):
   ''' bsearch is faster, particularly on large files '''
   def find(self,needle):
      f = open(self.tagsfile, 'r')
      f.seek(0,2)
      size = f.tell()

      TOP = 0
      BOTTOM = size
      while True:
         MID = (TOP+BOTTOM)/2
         #print "Top %d Mid %d Bottom %d"%(TOP,MID,BOTTOM)
         f.seek(MID,0)
         f.readline() # throw away the partial line
         MID = f.tell()
         if MID>=BOTTOM:
            # Endgame... naive binary search fails to take account of line lengths, so use TOP as a false pivot
            MID = TOP
            f.seek(TOP,0)
            f.readline()
            MID=f.tell()
         if MID>=BOTTOM:
            return None # No?
         line = f.readline()
         ctag = CTag(line)
         tag = ctag.tag()
         #print "..-> %s"%tag

         if tag == needle:
            return ctag.to_response() # Jackpot!
         elif tag < needle:
            TOP = f.tell()-1 # end of the rejected mid-record
            #print "<<<"
         else: # needle > tag
            BOTTOM = MID # beginning of the rejected mid-record
            #print ">>>"

         if TOP>=BOTTOM:
            return None # Simple termination

class TagsSearcherFactory:
   def get(self, tagsfile):
      return BinaryTagsSearcher(tagsfile)

<commit_msg>add generate() interface to TagsSearch, only implemented lsearch for now<commit_after>import re

class TagsResponse:
   def __init__(self, filename, pattern):
      self.filename = filename
      self.pattern = pattern
   def __str__(self):
      return '[filename=%s pattern=%s]' % (self.filename, self.pattern)

def quote_pattern(pat):
   pat = re.sub('~', '\~', pat)
   pat = re.sub('\*', '\\\*', pat)
   return pat

class CTag:
   def __init__(self, line):
      self.fields = line.split('\t')
   def to_response(self):
      return TagsResponse(self.filename(), self.pattern())
   def tag(self):
      return self.fields[0]
   def filename(self):
      return self.fields[1]
   def pattern(self):
      return quote_pattern(self.fields[2])

class AbstractTagsSearcher:
   '''
   Tags searching, using an unspecified algorithm.
   '''
   def __init__(self, tagsfile):
      self.tagsfile = tagsfile

   def find(self, tag):
      '''
      Searches for a tag. Returns a TagsResponse, or None if not found.
      NOTE: Only returns the first match it finds.
      '''
      raise 'Abstract interface!'
   def generate(self, tag):
      '''
      Tag search generator, i.e. returns an iterator that contains all
      possible completions. Not quite the same as find().
      '''
      raise 'Abstract interface!'

class LinearTagsSearcher(AbstractTagsSearcher):
   ''' Crungey old lsearch. '''
   def find(self,tag):
      f = open(self.tagsfile, 'r')
      needle = tag + '\t'
      for line in f:
         if line.startswith(needle):
            return CTag(line).to_response()
      return None

   def generate(self,tag):
      f = open(self.tagsfile, 'r')
      needle = tag # Different from find() !
      for line in f:
         if line.startswith(needle):
            yield CTag(line)

class BinaryTagsSearcher(AbstractTagsSearcher):
   ''' bsearch is faster, particularly on large files '''
   def find(self,needle):
      f = open(self.tagsfile, 'r')
      f.seek(0,2)
      size = f.tell()

      TOP = 0
      BOTTOM = size
      while True:
         MID = (TOP+BOTTOM)/2
         #print "Top %d Mid %d Bottom %d"%(TOP,MID,BOTTOM)
         f.seek(MID,0)
         f.readline() # throw away the partial line
         MID = f.tell()
         if MID>=BOTTOM:
            # Endgame... naive binary search fails to take account of line lengths, so use TOP as a false pivot
            MID = TOP
            f.seek(TOP,0)
            f.readline()
            MID=f.tell()
         if MID>=BOTTOM:
            return None # No?
         line = f.readline()
         ctag = CTag(line)
         tag = ctag.tag()
         #print "..-> %s"%tag

         if tag == needle:
            return ctag.to_response() # Jackpot!
         elif tag < needle:
            TOP = f.tell()-1 # end of the rejected mid-record
            #print "<<<"
         else: # needle > tag
            BOTTOM = MID # beginning of the rejected mid-record
            #print ">>>"

         if TOP>=BOTTOM:
            return None # Simple termination

class TagsSearcherFactory:
   def get(self, tagsfile):
      return BinaryTagsSearcher(tagsfile)
   def get_generator(self,tagsfile):
      return LinearTagsSearcher(tagsfile)

<|endoftext|>


<commit_before>from __future__ import absolute_import

import itertools

from collections import defaultdict

from sentry.app import env
from sentry.api.serializers import Serializer, register, serialize
from sentry.models import (
    OrganizationAccessRequest, OrganizationMemberTeam, Project, ProjectStatus,
    Team
)

@register(Team)
class TeamSerializer(Serializer):
    def get_attrs(self, item_list, user):
        request = env.request
        if user.is_authenticated():
            memberships = frozenset(
                OrganizationMemberTeam.objects.filter(
                    organizationmember__user=user,
                    team__in=item_list,
                    is_active=True,
                ).values_list('team', flat=True)
            )
        else:
            memberships = frozenset()

        if user.is_authenticated():
            access_requests = frozenset(
                OrganizationAccessRequest.objects.filter(
                    team__in=item_list,
                    member__user=user,
                ).values_list('team', flat=True)
            )
        else:
            access_requests = frozenset()

        is_superuser = request.is_superuser() and request.user == user
        result = {}
        for team in item_list:
            is_member = team.id in memberships
            if is_member:
                has_access = True
            elif is_superuser:
                has_access = True
            elif team.organization.flags.allow_joinleave:
                has_access = True
            else:
                has_access = False
            result[team] = {
                'pending_request': team.id in access_requests,
                'is_member': is_member,
                'has_access': has_access,
            }
        return result

    def serialize(self, obj, attrs, user):
        return {
            'id': str(obj.id),
            'slug': obj.slug,
            'name': obj.name,
            'dateCreated': obj.date_added,
            'isMember': attrs['is_member'],
            'hasAccess': attrs['has_access'],
            'isPending': attrs['pending_request'],
        }

class TeamWithProjectsSerializer(TeamSerializer):
    def get_attrs(self, item_list, user):
        project_qs = list(Project.objects.filter(
            team__in=item_list,
            status=ProjectStatus.VISIBLE,
        ).order_by('name', 'slug'))

        team_map = {i.id: i for i in item_list}

        for project in project_qs:
            project._team_cache = team_map[project.team_id]
            assert getattr(project.team, '_organization_cache', None)
            project._organization_cache = project.team.organization

        project_map = defaultdict(list)
        for project, data in itertools.izip(project_qs, serialize(project_qs, user)):
            project_map[project.team_id].append(data)

        result = super(TeamWithProjectsSerializer, self).get_attrs(item_list, user)
        for team in item_list:
            result[team]['projects'] = project_map[team.id]
        return result

    def serialize(self, obj, attrs, user):
        d = super(TeamWithProjectsSerializer, self).serialize(obj, attrs, user)
        d['projects'] = attrs['projects']
        return d
<commit_msg>Better handle cases where organization isnt present<commit_after>from __future__ import absolute_import

import itertools

from collections import defaultdict

from sentry.app import env
from sentry.api.serializers import Serializer, register, serialize
from sentry.models import (
    OrganizationAccessRequest, OrganizationMemberTeam, Project, ProjectStatus,
    Team
)

@register(Team)
class TeamSerializer(Serializer):
    def get_attrs(self, item_list, user):
        request = env.request
        if user.is_authenticated():
            memberships = frozenset(
                OrganizationMemberTeam.objects.filter(
                    organizationmember__user=user,
                    team__in=item_list,
                    is_active=True,
                ).values_list('team', flat=True)
            )
        else:
            memberships = frozenset()

        if user.is_authenticated():
            access_requests = frozenset(
                OrganizationAccessRequest.objects.filter(
                    team__in=item_list,
                    member__user=user,
                ).values_list('team', flat=True)
            )
        else:
            access_requests = frozenset()

        is_superuser = request.is_superuser() and request.user == user
        result = {}
        for team in item_list:
            is_member = team.id in memberships
            if is_member:
                has_access = True
            elif is_superuser:
                has_access = True
            elif team.organization.flags.allow_joinleave:
                has_access = True
            else:
                has_access = False
            result[team] = {
                'pending_request': team.id in access_requests,
                'is_member': is_member,
                'has_access': has_access,
            }
        return result

    def serialize(self, obj, attrs, user):
        return {
            'id': str(obj.id),
            'slug': obj.slug,
            'name': obj.name,
            'dateCreated': obj.date_added,
            'isMember': attrs['is_member'],
            'hasAccess': attrs['has_access'],
            'isPending': attrs['pending_request'],
        }

class TeamWithProjectsSerializer(TeamSerializer):
    def get_attrs(self, item_list, user):
        project_qs = list(Project.objects.filter(
            team__in=item_list,
            status=ProjectStatus.VISIBLE,
        ).order_by('name', 'slug'))

        team_map = {i.id: i for i in item_list}
        # TODO(dcramer): we should query in bulk for ones we're missing here
        orgs = {i.organization_id: i.organization for i in item_list}

        for project in project_qs:
            project._team_cache = team_map[project.team_id]
            project._organization_cache = orgs[project.organization_id]

        project_map = defaultdict(list)
        for project, data in itertools.izip(project_qs, serialize(project_qs, user)):
            project_map[project.team_id].append(data)

        result = super(TeamWithProjectsSerializer, self).get_attrs(item_list, user)
        for team in item_list:
            result[team]['projects'] = project_map[team.id]
        return result

    def serialize(self, obj, attrs, user):
        d = super(TeamWithProjectsSerializer, self).serialize(obj, attrs, user)
        d['projects'] = attrs['projects']
        return d
<|endoftext|>


<commit_before>from __future__ import absolute_import

from django.conf import settings

from sentry.api.serializers import Serializer, register
from sentry.models import User, UserOption
from sentry.utils.avatar import get_gravatar_url

@register(User)
class UserSerializer(Serializer):
    def serialize(self, obj, attrs, user):
        d = {
            'id': str(obj.id),
            'name': obj.get_display_name(),
            'isSuperuser': obj.is_active_superuser(),
            'email': obj.email,
            'avatarUrl': get_gravatar_url(obj.email, size=32),
        }
        if obj == user:
            options = {
                o.key: o.value
                for o in UserOption.objects.filter(
                    user=user,
                    project__isnull=True,
                )
            }
            stacktrace_order = int(options.get('stacktrace_order', -1) or -1)
            if stacktrace_order == -1:
                stacktrace_order = 'default'
            elif stacktrace_order == 2:
                stacktrace_order = 'newestFirst'
            elif stacktrace_order == 1:
                stacktrace_order = 'newestLast'

            d['options'] = {
                'language': options.get('language') or 'en',
                'stacktraceOrder': stacktrace_order,
                'timezone': options.get('timezone') or settings.SENTRY_DEFAULT_TIME_ZONE,

            }
        return d
<commit_msg>Pass 24 hour clock flag via API<commit_after>from __future__ import absolute_import

from django.conf import settings

from sentry.api.serializers import Serializer, register
from sentry.models import User, UserOption
from sentry.utils.avatar import get_gravatar_url

@register(User)
class UserSerializer(Serializer):
    def serialize(self, obj, attrs, user):
        d = {
            'id': str(obj.id),
            'name': obj.get_display_name(),
            'isSuperuser': obj.is_active_superuser(),
            'email': obj.email,
            'avatarUrl': get_gravatar_url(obj.email, size=32),
        }
        if obj == user:
            options = {
                o.key: o.value
                for o in UserOption.objects.filter(
                    user=user,
                    project__isnull=True,
                )
            }
            stacktrace_order = int(options.get('stacktrace_order', -1) or -1)
            if stacktrace_order == -1:
                stacktrace_order = 'default'
            elif stacktrace_order == 2:
                stacktrace_order = 'newestFirst'
            elif stacktrace_order == 1:
                stacktrace_order = 'newestLast'

            d['options'] = {
                'language': options.get('language') or 'en',
                'stacktraceOrder': stacktrace_order,
                'timezone': options.get('timezone') or settings.SENTRY_DEFAULT_TIME_ZONE,
                'clock24Hours': options.get('clock_24_hours') or False,
            }
        return d
<|endoftext|>


<commit_before>"""
sentry.management.commands.cleanup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:copyright: (c) 2012 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
from __future__ import absolute_import, print_function

from datetime import timedelta
from django.core.management.base import BaseCommand
from django.db import connections
from django.utils import timezone
from nydus.utils import ThreadPool
from optparse import make_option

from sentry.app import nodestore
from sentry.models import (
    Activity, Alert, Event, EventMapping, Group, GroupRuleStatus, GroupTagValue,
    LostPasswordHash, TagValue
)
from sentry.utils import db

def delete_object(item):
    item.delete()

class Command(BaseCommand):
    help = 'Deletes a portion of trailing data based on creation date'

    option_list = BaseCommand.option_list + (
        make_option('--days', default='30', type=int, help='Numbers of days to truncate on.'),
        make_option('--project', type=int, help='Limit truncation to only entries from project.'),
        make_option('--concurrency', type=int, default=1, help='The number of concurrent workers to run.'),
    )

    # these models should be safe to delete without cascades, in order
    BULK_DELETES = (
        (GroupRuleStatus, 'date_added'),
        (GroupTagValue, 'last_seen'),
        (Activity, 'datetime'),
        (TagValue, 'last_seen'),
        (Alert, 'datetime'),
    )

    GENERIC_DELETES = (
        (Event, 'datetime'),
        (Group, 'last_seen'),
    )

    def _postgres_bulk_speed_delete(self, model, dtfield, days=None,
                                    chunk_size=100000):
        """
        Cleanup models which we know dont need expensive (in-app) cascades or
        cache handling.

        This chunks up delete statements but still does them in bulk.
        """
        cursor = connections['default'].cursor()
        quote_name = connections['default'].ops.quote_name

        if days is None:
            days = self.days

        if self.project:
            where_extra = 'and project_id = %d' % (self.project,)
        else:
            where_extra = ''

        keep_it_going = True
        while keep_it_going:
            cursor.execute("""
            delete from %(table)s
            where id = any(array(
                select id
                from %(table)s
                where %(dtfield)s < now() - interval '%(days)d days'
                %(where_extra)s
                limit %(chunk_size)d
            ));
            """ % dict(
                table=model._meta.db_table,
                dtfield=quote_name(dtfield),
                days=days,
                where_extra=where_extra,
                chunk_size=chunk_size,
            ))
            keep_it_going = cursor.rowcount > 0

    def bulk_delete(self, model, dtfield, days=None):
        if db.is_postgres():
            self._postgres_bulk_speed_delete(model, dtfield, days=days)
        else:
            self.generic_delete(model, dtfield, days=days)

    def generic_delete(self, model, dtfield, days=None, chunk_size=1000):
        if days is None:
            days = self.days

        cutoff = timezone.now() - timedelta(days=days)

        qs = model.objects.filter(**{'%s__lte' % (dtfield,): cutoff})
        if self.project:
            qs = qs.filter(project=self.project)

        # XXX: we step through because the deletion collector will pull all
        # relations into memory
        count = 0
        while qs.exists():
            # TODO(dcramer): change this to delete by chunks of IDs and utilize
            # bulk_delete_objects
            self.stdout.write("Removing {model} chunk {count}\n".format(
                model=model.__name__,
                count=count,
            ))
            if self.concurrency > 1:
                worker_pool = ThreadPool(workers=self.concurrency)
                for obj in qs[:chunk_size].iterator():
                    worker_pool.add(obj.id, delete_object, [obj])
                    count += 1
                worker_pool.join()
                del worker_pool
            else:
                for obj in qs[:chunk_size].iterator():
                    delete_object(obj)
                    count += 1

    def handle(self, **options):
        self.days = options['days']
        self.concurrency = options['concurrency']
        self.project = options['project']

        self.stdout.write("Removing expired values for LostPasswordHash\n")
        LostPasswordHash.objects.filter(
            date_added__lte=timezone.now() - timedelta(hours=48)
        ).delete()

        if self.project:
            self.stderr.write("Bulk NodeStore deletion not available for project selection\n")
        else:
            self.stdout.write("Removing old NodeStore values\n")
            cutoff = timezone.now() - timedelta(days=self.days)
            try:
                nodestore.cleanup(cutoff)
            except NotImplementedError:
                self.stderr.write("NodeStore backend does not support cleanup operation\n")

        for model, dtfield in self.BULK_DELETES:
            self.stdout.write("Removing {model} for days={days} project={project}\n".format(
                model=model.__name__,
                days=self.days,
                project=self.project or '*',
            ))
            self.bulk_delete(model, dtfield)

        for model, dtfield in self.GENERIC_DELETES:
            self.stdout.write("Removing {model} for days={days} project={project}\n".format(
                model=model.__name__,
                days=self.days,
                project=self.project or '*',
            ))
            self.generic_delete(model, dtfield)

        # EventMapping is fairly expensive and is special cased as it's likely you
        # won't need a reference to an event for nearly as long
        self.stdout.write("Removing expired values for EventMapping\n")
        self.bulk_delete(EventMapping, 'date_added', days=min(self.days, 7))
<commit_msg>Remove remaining reference to Alert<commit_after>"""
sentry.management.commands.cleanup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:copyright: (c) 2012 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
from __future__ import absolute_import, print_function

from datetime import timedelta
from django.core.management.base import BaseCommand
from django.db import connections
from django.utils import timezone
from nydus.utils import ThreadPool
from optparse import make_option

from sentry.app import nodestore
from sentry.models import (
    Activity, Event, EventMapping, Group, GroupRuleStatus, GroupTagValue,
    LostPasswordHash, TagValue
)
from sentry.utils import db

def delete_object(item):
    item.delete()

class Command(BaseCommand):
    help = 'Deletes a portion of trailing data based on creation date'

    option_list = BaseCommand.option_list + (
        make_option('--days', default='30', type=int, help='Numbers of days to truncate on.'),
        make_option('--project', type=int, help='Limit truncation to only entries from project.'),
        make_option('--concurrency', type=int, default=1, help='The number of concurrent workers to run.'),
    )

    # these models should be safe to delete without cascades, in order
    BULK_DELETES = (
        (GroupRuleStatus, 'date_added'),
        (GroupTagValue, 'last_seen'),
        (Activity, 'datetime'),
        (TagValue, 'last_seen'),
    )

    GENERIC_DELETES = (
        (Event, 'datetime'),
        (Group, 'last_seen'),
    )

    def _postgres_bulk_speed_delete(self, model, dtfield, days=None,
                                    chunk_size=100000):
        """
        Cleanup models which we know dont need expensive (in-app) cascades or
        cache handling.

        This chunks up delete statements but still does them in bulk.
        """
        cursor = connections['default'].cursor()
        quote_name = connections['default'].ops.quote_name

        if days is None:
            days = self.days

        if self.project:
            where_extra = 'and project_id = %d' % (self.project,)
        else:
            where_extra = ''

        keep_it_going = True
        while keep_it_going:
            cursor.execute("""
            delete from %(table)s
            where id = any(array(
                select id
                from %(table)s
                where %(dtfield)s < now() - interval '%(days)d days'
                %(where_extra)s
                limit %(chunk_size)d
            ));
            """ % dict(
                table=model._meta.db_table,
                dtfield=quote_name(dtfield),
                days=days,
                where_extra=where_extra,
                chunk_size=chunk_size,
            ))
            keep_it_going = cursor.rowcount > 0

    def bulk_delete(self, model, dtfield, days=None):
        if db.is_postgres():
            self._postgres_bulk_speed_delete(model, dtfield, days=days)
        else:
            self.generic_delete(model, dtfield, days=days)

    def generic_delete(self, model, dtfield, days=None, chunk_size=1000):
        if days is None:
            days = self.days

        cutoff = timezone.now() - timedelta(days=days)

        qs = model.objects.filter(**{'%s__lte' % (dtfield,): cutoff})
        if self.project:
            qs = qs.filter(project=self.project)

        # XXX: we step through because the deletion collector will pull all
        # relations into memory
        count = 0
        while qs.exists():
            # TODO(dcramer): change this to delete by chunks of IDs and utilize
            # bulk_delete_objects
            self.stdout.write("Removing {model} chunk {count}\n".format(
                model=model.__name__,
                count=count,
            ))
            if self.concurrency > 1:
                worker_pool = ThreadPool(workers=self.concurrency)
                for obj in qs[:chunk_size].iterator():
                    worker_pool.add(obj.id, delete_object, [obj])
                    count += 1
                worker_pool.join()
                del worker_pool
            else:
                for obj in qs[:chunk_size].iterator():
                    delete_object(obj)
                    count += 1

    def handle(self, **options):
        self.days = options['days']
        self.concurrency = options['concurrency']
        self.project = options['project']

        self.stdout.write("Removing expired values for LostPasswordHash\n")
        LostPasswordHash.objects.filter(
            date_added__lte=timezone.now() - timedelta(hours=48)
        ).delete()

        if self.project:
            self.stderr.write("Bulk NodeStore deletion not available for project selection\n")
        else:
            self.stdout.write("Removing old NodeStore values\n")
            cutoff = timezone.now() - timedelta(days=self.days)
            try:
                nodestore.cleanup(cutoff)
            except NotImplementedError:
                self.stderr.write("NodeStore backend does not support cleanup operation\n")

        for model, dtfield in self.BULK_DELETES:
            self.stdout.write("Removing {model} for days={days} project={project}\n".format(
                model=model.__name__,
                days=self.days,
                project=self.project or '*',
            ))
            self.bulk_delete(model, dtfield)

        for model, dtfield in self.GENERIC_DELETES:
            self.stdout.write("Removing {model} for days={days} project={project}\n".format(
                model=model.__name__,
                days=self.days,
                project=self.project or '*',
            ))
            self.generic_delete(model, dtfield)

        # EventMapping is fairly expensive and is special cased as it's likely you
        # won't need a reference to an event for nearly as long
        self.stdout.write("Removing expired values for EventMapping\n")
        self.bulk_delete(EventMapping, 'date_added', days=min(self.days, 7))
<|endoftext|>


<commit_before>#
# ovirt-engine-setup -- ovirt engine setup
# Copyright (C) 2013-2015 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

""" DB Async tasks handling plugin."""

import distutils.version
import gettext
import time

from otopi import constants as otopicons
from otopi import base, plugin, util

from async_tasks_map import ASYNC_TASKS_MAP
from ovirt_engine_setup import constants as osetupcons
from ovirt_engine_setup import dialog
from ovirt_engine_setup.engine import constants as oenginecons
from ovirt_engine_setup.engine import vdcoption
from ovirt_engine_setup.engine_common import constants as oengcommcons
from ovirt_engine_setup.engine_common import database

def _(m):
    return gettext.dgettext(message=m, domain='ovirt-engine-setup')

@util.export
class Plugin(plugin.PluginBase):
    """ DB Async tasks handling plugin."""

    class _engineInMaintenance(base.Base):

        def __init__(
            self,
            parent,
            dbstatement,
        ):
            self._parent = parent
            self._dbstatement = dbstatement

        def _setEngineMode(self, maintenance, timeout=0):
            mode = (
                'MAINTENANCE' if maintenance
                else 'ACTIVE'
            )
            try:
                self._parent.logger.debug(
                    'Setting engine into {mode} mode'.format(
                        mode=mode,
                    )
                )

                vdcoption.VdcOption(
                    statement=self._dbstatement,
                ).updateVdcOptions(
                    options=(
                        {
                            'name': 'EngineMode',
                            'value': mode,
                        },
                    ),
                    ownConnection=True,
                )
            except Exception as e:
                self._parent.logger.debug(
                    'Cannot set engine mode',
                    exc_info=True,
                )
                raise RuntimeError(
                    _(
                        'Failed to set engine to {mode} mode.\n'
                        'Error: {error}\n'
                        'Please check that engine is in correct state '
                        'and try running upgrade again.'
                    ).format(
                        mode=mode,
                        error=e,
                    )
                )

        def __enter__(self):
            self._setEngineMode(
                maintenance=True,
            )
            self._parent.services.state(
                name=oenginecons.Const.ENGINE_SERVICE_NAME,
                state=True,
            )

        def __exit__(self, exc_type, exc_value, traceback):
            self._parent.services.state(
                name=oenginecons.Const.ENGINE_SERVICE_NAME,
                state=False,
            )
            self._setEngineMode(
                maintenance=False,
            )

    def _clearZombies(self):
        inst_v = distutils.version.LooseVersion(
            self.environment[
                osetupcons.CoreEnv.ORIGINAL_GENERATED_BY_VERSION
            ]
        ).version[:2]
        _args_base = (
            oenginecons.FileLocations.OVIRT_ENGINE_TASKCLEANER,
            '-l', self.environment[otopicons.CoreEnv.LOG_FILE_NAME],
            '-u', self.environment[oenginecons.EngineDBEnv.USER],
            '-s', self.environment[oenginecons.EngineDBEnv.HOST],
            '-p', str(self.environment[oenginecons.EngineDBEnv.PORT]),
            '-d', self.environment[oenginecons.EngineDBEnv.DATABASE],
            '-q',
        )
        envPwd = {
            'DBFUNC_DB_PGPASSFILE': self.environment[
                oenginecons.EngineDBEnv.PGPASS_FILE
            ]
        }

        if inst_v > [3, 4]:
            # removing zombie commands if present (just for 3.5 and upper)
            _args_commands = _args_base + ('-r', '-Z',)
            rc, tasks, stderr = self.execute(
                args=_args_commands,
                raiseOnError=False,
                envAppend=envPwd,
            )
            if rc:
                raise RuntimeError(
                    _(
                        'Failed to clear zombie commands. '
                        'Please access support in attempt to resolve '
                        'the problem'
                    )
                )

        # than remove zombie tasks ans related jobs and compensation entries
        _args_tasks = _args_base + ('-R', '-z', '-A',)
        rc, tasks, stderr = self.execute(
            args=_args_tasks,
            raiseOnError=False,
            envAppend=envPwd,
        )
        if rc:
            raise RuntimeError(
                _(
                    'Failed to clear zombie tasks. '
                    'Please access support in attempt to resolve '
                    'the problem'
                )
            )

    def _getRunningTasks(self, dbstatement):

        tasks = dbstatement.execute(
            statement="""
                select
                async_tasks.action_type,
                async_tasks.task_id,
                async_tasks.started_at,
                storage_pool.name
                from async_tasks, storage_pool
                where async_tasks.storage_pool_id = storage_pool.id
            """,
            ownConnection=True,
            transaction=False,
        )

        def taskinfo(task):
            return ASYNC_TASKS_MAP.get(
                str(task['action_type']),
                ['Unknown', 'Unknown']
            )

        return (
            [
                _(
                    'Task ID:           {task_id:30}\n'
                    'Task Name:         {task_name:30}\n'
                    'Task Description:  {task_desc:30}\n'
                    'Started at:        {started_at:30}\n'
                    'DC Name:           {name:30}'
                ).format(
                    task_id=entry['task_id'],
                    task_name=taskinfo(entry)[0],
                    task_desc=taskinfo(entry)[1],
                    started_at=entry['started_at'],
                    name=entry['name'],
                )
                for entry in tasks
            ]
        )

    def _getCommandEntitiesTableExists(self, dbstatement):

        command_entities = dbstatement.execute(
            statement="""
                select relname
                from pg_class
                where relname = 'command_entities'
            """,
            ownConnection=True,
            transaction=False,
        )

        return (
            [
                _(
                    'Relname:           {relname:30}'
                ).format(
                    relname=entry['relname'],
                )
                for entry in command_entities
            ]
        )

    def _getRunningCommands(self, dbstatement):

        if not self._getCommandEntitiesTableExists(dbstatement):
            return []

        commands = dbstatement.execute(
            statement="""
                select
                command_entities.command_type,
                command_entities.command_id,
                command_entities.created_at,
                command_entities.status
                from command_entities
                where command_entities.callback_enabled = 'true'
                  and command_entities.callback_notified = 'false'
            """,
            ownConnection=True,
            transaction=False,
        )

        return (
            [
                _(
                    'Command ID:           {command_id:30}\n'
                    'Command Type:         {command_type:30}\n'
                    'Created at:           {created_at:30}\n'
                    'Status:               {status:30}'
                ).format(
                    command_id=entry['command_id'],
                    command_type=entry['command_type'],
                    created_at=entry['created_at'],
                    status=entry['status'],
                )
                for entry in commands
            ]
        )

    def _getCompensations(self, dbstatement):

        compensations = dbstatement.execute(
            statement="""
                select command_type, entity_type
                from business_entity_snapshot
            """,
            ownConnection=True,
            transaction=False,
        )

        return (
            [
                '{command_type:30} {entity_type:30}'.format(**entry)
                for entry in compensations
            ]
        )

    def _askUserToWaitForTasks(
        self,
        runningTasks,
        runningCommands,
        compensations,
    ):
        self.dialog.note(
            text=_(
                'The following system tasks have been '
                'found running in the system:\n'
                '{tasks}'
            ).format(
                tasks='\n'.join(runningTasks),
            )
        )
        self.dialog.note(
            text=_(
                'The following commands have been '
                'found running in the system:\n'
                '{commands}'
            ).format(
                commands='\n'.join(runningCommands),
            )
        )
        self.dialog.note(
            text=_(
                'The following compensations have been '
                'found running in the system:\n'
                '{compensations}'
            ).format(
                compensations='\n'.join(compensations),
            )
        )
        if not dialog.queryBoolean(
            dialog=self.dialog,
            name='OVESETUP_WAIT_RUNNING_TASKS',
            note=_(
                'Would you like to try to wait for that?\n'
                '(Answering "no" will stop the upgrade (@VALUES@) '
            ),
            prompt=True,
        ):
            raise RuntimeError(
                _(
                    'Upgrade cannot be completed; asynchronious tasks or '
                    'commands or compensations are still running. Please '
                    'make sure that there are no running tasks before you '
                    'continue.'
                )
            )

    def _checkRunningTasks(self):
        dbstatement = database.Statement(
            dbenvkeys=oenginecons.Const.ENGINE_DB_ENV_KEYS,
            environment=self.environment,
        )
        return (
            self._getRunningTasks(dbstatement),
            self._getRunningCommands(dbstatement),
            self._getCompensations(dbstatement),
        )

    def _unlockAll(self):
        args = (
            oenginecons.FileLocations.OVIRT_ENGINE_UNLOCK_ENTITY,
            '-t', 'all',
            '-l', self.environment[otopicons.CoreEnv.LOG_FILE_NAME],
            '-u', self.environment[oenginecons.EngineDBEnv.USER],
            '-s', self.environment[oenginecons.EngineDBEnv.HOST],
            '-p', str(self.environment[oenginecons.EngineDBEnv.PORT]),
            '-d', self.environment[oenginecons.EngineDBEnv.DATABASE],
            '-i',
        )
        envPwd = {
            'DBFUNC_DB_PGPASSFILE': self.environment[
                oenginecons.EngineDBEnv.PGPASS_FILE
            ]
        }
        rc, tasks, stderr = self.execute(
            args=args,
            raiseOnError=False,
            envAppend=envPwd,
        )
        if rc:
            raise RuntimeError(
                _(
                    'Failed to unlock entities. '
                    'Please access support in attempt to resolve '
                    'the problem'
                )
            )

    def _waitForTasksToClear(self):
        while True:
            (
                runningTasks,
                runningCommands,
                compensations,
            ) = self._checkRunningTasks()
            if (
                not runningTasks and
                not runningCommands and
                not compensations
            ):
                break

            self.dialog.note(
                text=_(
                    'Waiting for the completion of {number} '
                    'running tasks during the next '
                    '{cleanup_wait} seconds.\n'
                    'Press Ctrl+C to interrupt. '
                ).format(
                    cleanup_wait=self.environment[
                        oenginecons.AsyncTasksEnv.
                        CLEAR_TASKS_WAIT_PERIOD
                    ],
                    number=(
                        len(runningTasks) +
                        len(runningCommands) +
                        len(compensations)
                    ),
                )
            )
            time.sleep(
                self.environment[
                    oenginecons.AsyncTasksEnv.
                    CLEAR_TASKS_WAIT_PERIOD
                ]
            )

    def __init__(self, context):
        super(Plugin, self).__init__(context=context)
        self._enabled = False

    @plugin.event(
        stage=plugin.Stages.STAGE_INIT,
    )
    def _init(self):
        self.environment.setdefault(
            oenginecons.AsyncTasksEnv.CLEAR_TASKS,
            True
        )
        self.environment.setdefault(
            oenginecons.AsyncTasksEnv.CLEAR_TASKS_WAIT_PERIOD,
            oenginecons.Defaults.DEFAULT_CLEAR_TASKS_WAIT_PERIOD
        )

    @plugin.event(
        stage=plugin.Stages.STAGE_VALIDATION,
        priority=plugin.Stages.PRIORITY_HIGH,
    )
    def _validateEnv(self):
        self._enabled = (
            self.environment[oenginecons.CoreEnv.ENABLE] and
            not self.environment[
                oenginecons.EngineDBEnv.NEW_DATABASE
            ] and
            self.environment[
                oenginecons.AsyncTasksEnv.CLEAR_TASKS
            ] and
            not self.environment[
                osetupcons.CoreEnv.DEVELOPER_MODE
            ]
        )

    @plugin.event(
        stage=plugin.Stages.STAGE_VALIDATION,
        condition=lambda self: self._enabled,
        after=(
            oengcommcons.Stages.DB_CREDENTIALS_AVAILABLE_EARLY,
        ),
    )
    def _validateZombies(self):
        self.logger.info(
            _('Cleaning stale zombie tasks and commands')
        )
        self._clearZombies()

    @plugin.event(
        stage=plugin.Stages.STAGE_VALIDATION,
        priority=plugin.Stages.PRIORITY_LOW,
        condition=lambda self: self._enabled,
    )
    def _validateAsyncTasks(self):
        self.logger.info(
            _('Cleaning async tasks and compensations')
        )

        (
            runningTasks,
            runningCommands,
            compensations,
        ) = self._checkRunningTasks()

        dbstatement = database.Statement(
            dbenvkeys=oenginecons.Const.ENGINE_DB_ENV_KEYS,
            environment=self.environment,
        )
        with self._engineInMaintenance(
            dbstatement=dbstatement,
            parent=self,
        ):
            if runningTasks or runningCommands or compensations:
                self._askUserToWaitForTasks(
                    runningTasks,
                    runningCommands,
                    compensations,
                )
                try:
                    self._waitForTasksToClear()
                except KeyboardInterrupt:
                    self.logger.error(
                        _(
                            'Upgrade cannot be completed; asynchronious tasks '
                            'or commands or compensations are still running. '
                            'Please make sure that there are no running tasks '
                            'before you continue.'
                        )
                    )
                    raise RuntimeError(
                        _('Upgrade cannot be completed due to running tasks.')
                    )
            self.logger.info(
                _('Unlocking existing entities')
            )
            self._unlockAll()

# vim: expandtab tabstop=4 shiftwidth=4
<commit_msg>packaging: setup: asynctasks: do not start/stop engine<commit_after>#
# ovirt-engine-setup -- ovirt engine setup
# Copyright (C) 2013-2015 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

""" DB Async tasks handling plugin."""

import distutils.version
import gettext
import time

from otopi import constants as otopicons
from otopi import base, plugin, util

from async_tasks_map import ASYNC_TASKS_MAP
from ovirt_engine_setup import constants as osetupcons
from ovirt_engine_setup import dialog
from ovirt_engine_setup.engine import constants as oenginecons
from ovirt_engine_setup.engine import vdcoption
from ovirt_engine_setup.engine_common import constants as oengcommcons
from ovirt_engine_setup.engine_common import database

def _(m):
    return gettext.dgettext(message=m, domain='ovirt-engine-setup')

@util.export
class Plugin(plugin.PluginBase):
    """ DB Async tasks handling plugin."""

    class _engineInMaintenance(base.Base):

        def __init__(
            self,
            parent,
            dbstatement,
        ):
            self._parent = parent
            self._dbstatement = dbstatement

        def _setEngineMode(self, maintenance, timeout=0):
            mode = (
                'MAINTENANCE' if maintenance
                else 'ACTIVE'
            )
            try:
                self._parent.logger.debug(
                    'Setting engine into {mode} mode'.format(
                        mode=mode,
                    )
                )

                vdcoption.VdcOption(
                    statement=self._dbstatement,
                ).updateVdcOptions(
                    options=(
                        {
                            'name': 'EngineMode',
                            'value': mode,
                        },
                    ),
                    ownConnection=True,
                )
            except Exception as e:
                self._parent.logger.debug(
                    'Cannot set engine mode',
                    exc_info=True,
                )
                raise RuntimeError(
                    _(
                        'Failed to set engine to {mode} mode.\n'
                        'Error: {error}\n'
                        'Please check that engine is in correct state '
                        'and try running upgrade again.'
                    ).format(
                        mode=mode,
                        error=e,
                    )
                )

        def __enter__(self):
            self._setEngineMode(
                maintenance=True,
            )

        def __exit__(self, exc_type, exc_value, traceback):
            self._setEngineMode(
                maintenance=False,
            )

    def _clearZombies(self):
        inst_v = distutils.version.LooseVersion(
            self.environment[
                osetupcons.CoreEnv.ORIGINAL_GENERATED_BY_VERSION
            ]
        ).version[:2]
        _args_base = (
            oenginecons.FileLocations.OVIRT_ENGINE_TASKCLEANER,
            '-l', self.environment[otopicons.CoreEnv.LOG_FILE_NAME],
            '-u', self.environment[oenginecons.EngineDBEnv.USER],
            '-s', self.environment[oenginecons.EngineDBEnv.HOST],
            '-p', str(self.environment[oenginecons.EngineDBEnv.PORT]),
            '-d', self.environment[oenginecons.EngineDBEnv.DATABASE],
            '-q',
        )
        envPwd = {
            'DBFUNC_DB_PGPASSFILE': self.environment[
                oenginecons.EngineDBEnv.PGPASS_FILE
            ]
        }

        if inst_v > [3, 4]:
            # removing zombie commands if present (just for 3.5 and upper)
            _args_commands = _args_base + ('-r', '-Z',)
            rc, tasks, stderr = self.execute(
                args=_args_commands,
                raiseOnError=False,
                envAppend=envPwd,
            )
            if rc:
                raise RuntimeError(
                    _(
                        'Failed to clear zombie commands. '
                        'Please access support in attempt to resolve '
                        'the problem'
                    )
                )

        # than remove zombie tasks ans related jobs and compensation entries
        _args_tasks = _args_base + ('-R', '-z', '-A',)
        rc, tasks, stderr = self.execute(
            args=_args_tasks,
            raiseOnError=False,
            envAppend=envPwd,
        )
        if rc:
            raise RuntimeError(
                _(
                    'Failed to clear zombie tasks. '
                    'Please access support in attempt to resolve '
                    'the problem'
                )
            )

    def _getRunningTasks(self, dbstatement):

        tasks = dbstatement.execute(
            statement="""
                select
                async_tasks.action_type,
                async_tasks.task_id,
                async_tasks.started_at,
                storage_pool.name
                from async_tasks, storage_pool
                where async_tasks.storage_pool_id = storage_pool.id
            """,
            ownConnection=True,
            transaction=False,
        )

        def taskinfo(task):
            return ASYNC_TASKS_MAP.get(
                str(task['action_type']),
                ['Unknown', 'Unknown']
            )

        return (
            [
                _(
                    'Task ID:           {task_id:30}\n'
                    'Task Name:         {task_name:30}\n'
                    'Task Description:  {task_desc:30}\n'
                    'Started at:        {started_at:30}\n'
                    'DC Name:           {name:30}'
                ).format(
                    task_id=entry['task_id'],
                    task_name=taskinfo(entry)[0],
                    task_desc=taskinfo(entry)[1],
                    started_at=entry['started_at'],
                    name=entry['name'],
                )
                for entry in tasks
            ]
        )

    def _getCommandEntitiesTableExists(self, dbstatement):

        command_entities = dbstatement.execute(
            statement="""
                select relname
                from pg_class
                where relname = 'command_entities'
            """,
            ownConnection=True,
            transaction=False,
        )

        return (
            [
                _(
                    'Relname:           {relname:30}'
                ).format(
                    relname=entry['relname'],
                )
                for entry in command_entities
            ]
        )

    def _getRunningCommands(self, dbstatement):

        if not self._getCommandEntitiesTableExists(dbstatement):
            return []

        commands = dbstatement.execute(
            statement="""
                select
                command_entities.command_type,
                command_entities.command_id,
                command_entities.created_at,
                command_entities.status
                from command_entities
                where command_entities.callback_enabled = 'true'
                  and command_entities.callback_notified = 'false'
            """,
            ownConnection=True,
            transaction=False,
        )

        return (
            [
                _(
                    'Command ID:           {command_id:30}\n'
                    'Command Type:         {command_type:30}\n'
                    'Created at:           {created_at:30}\n'
                    'Status:               {status:30}'
                ).format(
                    command_id=entry['command_id'],
                    command_type=entry['command_type'],
                    created_at=entry['created_at'],
                    status=entry['status'],
                )
                for entry in commands
            ]
        )

    def _getCompensations(self, dbstatement):

        compensations = dbstatement.execute(
            statement="""
                select command_type, entity_type
                from business_entity_snapshot
            """,
            ownConnection=True,
            transaction=False,
        )

        return (
            [
                '{command_type:30} {entity_type:30}'.format(**entry)
                for entry in compensations
            ]
        )

    def _askUserToWaitForTasks(
        self,
        runningTasks,
        runningCommands,
        compensations,
    ):
        self.dialog.note(
            text=_(
                'The following system tasks have been '
                'found running in the system:\n'
                '{tasks}'
            ).format(
                tasks='\n'.join(runningTasks),
            )
        )
        self.dialog.note(
            text=_(
                'The following commands have been '
                'found running in the system:\n'
                '{commands}'
            ).format(
                commands='\n'.join(runningCommands),
            )
        )
        self.dialog.note(
            text=_(
                'The following compensations have been '
                'found running in the system:\n'
                '{compensations}'
            ).format(
                compensations='\n'.join(compensations),
            )
        )
        if not dialog.queryBoolean(
            dialog=self.dialog,
            name='OVESETUP_WAIT_RUNNING_TASKS',
            note=_(
                'Would you like to try to wait for that?\n'
                '(Answering "no" will stop the upgrade (@VALUES@) '
            ),
            prompt=True,
        ):
            raise RuntimeError(
                _(
                    'Upgrade cannot be completed; asynchronious tasks or '
                    'commands or compensations are still running. Please '
                    'make sure that there are no running tasks before you '
                    'continue.'
                )
            )

    def _checkRunningTasks(self):
        dbstatement = database.Statement(
            dbenvkeys=oenginecons.Const.ENGINE_DB_ENV_KEYS,
            environment=self.environment,
        )
        return (
            self._getRunningTasks(dbstatement),
            self._getRunningCommands(dbstatement),
            self._getCompensations(dbstatement),
        )

    def _unlockAll(self):
        args = (
            oenginecons.FileLocations.OVIRT_ENGINE_UNLOCK_ENTITY,
            '-t', 'all',
            '-l', self.environment[otopicons.CoreEnv.LOG_FILE_NAME],
            '-u', self.environment[oenginecons.EngineDBEnv.USER],
            '-s', self.environment[oenginecons.EngineDBEnv.HOST],
            '-p', str(self.environment[oenginecons.EngineDBEnv.PORT]),
            '-d', self.environment[oenginecons.EngineDBEnv.DATABASE],
            '-i',
        )
        envPwd = {
            'DBFUNC_DB_PGPASSFILE': self.environment[
                oenginecons.EngineDBEnv.PGPASS_FILE
            ]
        }
        rc, tasks, stderr = self.execute(
            args=args,
            raiseOnError=False,
            envAppend=envPwd,
        )
        if rc:
            raise RuntimeError(
                _(
                    'Failed to unlock entities. '
                    'Please access support in attempt to resolve '
                    'the problem'
                )
            )

    def _waitForTasksToClear(self):
        while True:
            (
                runningTasks,
                runningCommands,
                compensations,
            ) = self._checkRunningTasks()
            if (
                not runningTasks and
                not runningCommands and
                not compensations
            ):
                break

            self.dialog.note(
                text=_(
                    'Waiting for the completion of {number} '
                    'running tasks during the next '
                    '{cleanup_wait} seconds.\n'
                    'Press Ctrl+C to interrupt. '
                ).format(
                    cleanup_wait=self.environment[
                        oenginecons.AsyncTasksEnv.
                        CLEAR_TASKS_WAIT_PERIOD
                    ],
                    number=(
                        len(runningTasks) +
                        len(runningCommands) +
                        len(compensations)
                    ),
                )
            )
            if (
                not self.services.exists(
                    name=oenginecons.Const.ENGINE_SERVICE_NAME
                ) or not self.services.status(
                    name=oenginecons.Const.ENGINE_SERVICE_NAME
                )
            ):
                self.dialog.note(
                    text=_(
                        'Please note that the engine is currently down. you '
                        'may want to try to start it using the following '
                        'command:\n'
                        '# service {service} start\n'
                    ).format(
                        service=oenginecons.Const.ENGINE_SERVICE_NAME,
                    )
                )
            time.sleep(
                self.environment[
                    oenginecons.AsyncTasksEnv.
                    CLEAR_TASKS_WAIT_PERIOD
                ]
            )

    def __init__(self, context):
        super(Plugin, self).__init__(context=context)
        self._enabled = False

    @plugin.event(
        stage=plugin.Stages.STAGE_INIT,
    )
    def _init(self):
        self.environment.setdefault(
            oenginecons.AsyncTasksEnv.CLEAR_TASKS,
            True
        )
        self.environment.setdefault(
            oenginecons.AsyncTasksEnv.CLEAR_TASKS_WAIT_PERIOD,
            oenginecons.Defaults.DEFAULT_CLEAR_TASKS_WAIT_PERIOD
        )

    @plugin.event(
        stage=plugin.Stages.STAGE_VALIDATION,
        priority=plugin.Stages.PRIORITY_HIGH,
    )
    def _validateEnv(self):
        self._enabled = (
            self.environment[oenginecons.CoreEnv.ENABLE] and
            not self.environment[
                oenginecons.EngineDBEnv.NEW_DATABASE
            ] and
            self.environment[
                oenginecons.AsyncTasksEnv.CLEAR_TASKS
            ] and
            not self.environment[
                osetupcons.CoreEnv.DEVELOPER_MODE
            ]
        )

    @plugin.event(
        stage=plugin.Stages.STAGE_VALIDATION,
        condition=lambda self: self._enabled,
        after=(
            oengcommcons.Stages.DB_CREDENTIALS_AVAILABLE_EARLY,
        ),
    )
    def _validateZombies(self):
        self.logger.info(
            _('Cleaning stale zombie tasks and commands')
        )
        self._clearZombies()

    @plugin.event(
        stage=plugin.Stages.STAGE_VALIDATION,
        priority=plugin.Stages.PRIORITY_LOW,
        condition=lambda self: self._enabled,
    )
    def _validateAsyncTasks(self):
        self.logger.info(
            _('Cleaning async tasks and compensations')
        )

        (
            runningTasks,
            runningCommands,
            compensations,
        ) = self._checkRunningTasks()

        dbstatement = database.Statement(
            dbenvkeys=oenginecons.Const.ENGINE_DB_ENV_KEYS,
            environment=self.environment,
        )
        with self._engineInMaintenance(
            dbstatement=dbstatement,
            parent=self,
        ):
            if runningTasks or runningCommands or compensations:
                self._askUserToWaitForTasks(
                    runningTasks,
                    runningCommands,
                    compensations,
                )
                try:
                    self._waitForTasksToClear()
                except KeyboardInterrupt:
                    self.logger.error(
                        _(
                            'Upgrade cannot be completed; asynchronious tasks '
                            'or commands or compensations are still running. '
                            'Please make sure that there are no running tasks '
                            'before you continue.'
                        )
                    )
                    raise RuntimeError(
                        _('Upgrade cannot be completed due to running tasks.')
                    )
            self.logger.info(
                _('Unlocking existing entities')
            )
            self._unlockAll()

# vim: expandtab tabstop=4 shiftwidth=4
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# Copyright (C) 2012 Alexander Shorin
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.
#

"""Common ASTM records structure."""

from datetime import datetime
from .mapping import (
    Record, ConstantField, DateTimeField, IntegerField, NotUsedField
)

__all__ = ['HeaderRecord', 'PatientRecord', 'OrderRecord',
           'ResultRecord' 'CommentRecord', 'TerminatorRecord']

HeaderRecord = Record.build(
    ConstantField(name='type', default='H'),
    ConstantField(name='delimeter', default='\^&'),
    NotUsedField(name='message_id'),
    NotUsedField(name='password'),
    NotUsedField(name='sender'),
    NotUsedField(name='address'),
    NotUsedField(name='reserved'),
    NotUsedField(name='phone'),
    NotUsedField(name='chars'),
    NotUsedField(name='receiver'),
    NotUsedField(name='comments'),
    ConstantField(name='processing_id', default='P'),
    NotUsedField(name='version'),
    DateTimeField(name='timestamp', default=datetime.now),
)

PatientRecord = Record.build(
    ConstantField(name='type', default='P'),
    IntegerField(name='seq', default=1),
    NotUsedField(name='practice_id'),
    NotUsedField(name='laboratory_id'),
    NotUsedField(name='id'),
    NotUsedField(name='name'),
    NotUsedField(name='maiden_name'),
    NotUsedField(name='birthdate'),
    NotUsedField(name='sex'),
    NotUsedField(name='race'),
    NotUsedField(name='address'),
    NotUsedField(name='reserved'),
    NotUsedField(name='phone'),
    NotUsedField(name='physician_id'),
    NotUsedField(name='special_1'),
    NotUsedField(name='special_2'),
    NotUsedField(name='height'),
    NotUsedField(name='weight'),
    NotUsedField(name='diagnosis'),
    NotUsedField(name='medication'),
    NotUsedField(name='diet'),
    NotUsedField(name='practice_field_1'),
    NotUsedField(name='practice_field_2'),
    NotUsedField(name='admission_date'),
    NotUsedField(name='admission_status'),
    NotUsedField(name='location'),
    NotUsedField(name='diagnostic_code_nature'),
    NotUsedField(name='diagnostic_code'),
    NotUsedField(name='religion'),
    NotUsedField(name='martial_status'),
    NotUsedField(name='isolation_status'),
    NotUsedField(name='language'),
    NotUsedField(name='hospital_service'),
    NotUsedField(name='hospital_institution'),
    NotUsedField(name='dosage_category'),
)

OrderRecord = Record.build(
    ConstantField(name='type', default='O'),
    IntegerField(name='seq', default=1),
    NotUsedField(name='sample_id'),
    NotUsedField(name='instrument_id'),
    NotUsedField(name='test'),
    NotUsedField(name='priority'),
    DateTimeField(name='created_at'),
    DateTimeField(name='sampled_at'),
    NotUsedField(name='collected_at'),
    NotUsedField(name='volume'),
    NotUsedField(name='collector'),
    NotUsedField(name='action_code'),
    NotUsedField(name='danger_code'),
    NotUsedField(name='clinical_info'),
    DateTimeField(name='delivered_at'),
    NotUsedField(name='specimen_descriptor'),
    NotUsedField(name='physician'),
    NotUsedField(name='physician_phone'),
    NotUsedField(name='user_field_1'),
    NotUsedField(name='user_field_2'),
    NotUsedField(name='laboratory_field_1'),
    NotUsedField(name='laboratory_field_2'),
    DateTimeField(name='modified_at'),
    NotUsedField(name='instrument_charge'),
    NotUsedField(name='instrument_section'),
    NotUsedField(name='report_type'),
    NotUsedField(name='reserved'),
    NotUsedField(name='location_ward'),
    NotUsedField(name='infection_flag'),
    NotUsedField(name='specimen_service'),
    NotUsedField(name='laboratory')
)

ResultRecord = Record.build(
    ConstantField(name='type', default='R'),
    IntegerField(name='seq', default=1),
    NotUsedField(name='test'),
    NotUsedField(name='value'),
    NotUsedField(name='units'),
    NotUsedField(name='reference_ranges'),
    NotUsedField(name='is_abnormal'),
    NotUsedField(name='abnormality_nature'),
    NotUsedField(name='status'),
    NotUsedField(name='normatives_changed_at'),
    NotUsedField(name='operator'),
    NotUsedField(name='started_at'),
    NotUsedField(name='completed_at'),
    NotUsedField(name='instrument'),
)

CommentRecord = Record.build(
    ConstantField(name='type', default='C'),
    IntegerField(name='seq', default=1),
    NotUsedField(name='source'),
    NotUsedField(name='text'),
    NotUsedField(name='type')
)

TerminatorRecord = Record.build(
    ConstantField(name='type', default='L'),
    IntegerField(name='seq', default=1),
    ConstantField(name='code', default='N')
)
<commit_msg>Remove field type from explicit datetimes.<commit_after># -*- coding: utf-8 -*-
#
# Copyright (C) 2012 Alexander Shorin
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.
#

"""Common ASTM records structure."""

from datetime import datetime
from .mapping import (
    Record, ConstantField, DateTimeField, IntegerField, NotUsedField
)

__all__ = ['HeaderRecord', 'PatientRecord', 'OrderRecord',
           'ResultRecord' 'CommentRecord', 'TerminatorRecord']

HeaderRecord = Record.build(
    ConstantField(name='type', default='H'),
    ConstantField(name='delimeter', default='\^&'),
    NotUsedField(name='message_id'),
    NotUsedField(name='password'),
    NotUsedField(name='sender'),
    NotUsedField(name='address'),
    NotUsedField(name='reserved'),
    NotUsedField(name='phone'),
    NotUsedField(name='chars'),
    NotUsedField(name='receiver'),
    NotUsedField(name='comments'),
    ConstantField(name='processing_id', default='P'),
    NotUsedField(name='version'),
    DateTimeField(name='timestamp', default=datetime.now),
)

PatientRecord = Record.build(
    ConstantField(name='type', default='P'),
    IntegerField(name='seq', default=1),
    NotUsedField(name='practice_id'),
    NotUsedField(name='laboratory_id'),
    NotUsedField(name='id'),
    NotUsedField(name='name'),
    NotUsedField(name='maiden_name'),
    NotUsedField(name='birthdate'),
    NotUsedField(name='sex'),
    NotUsedField(name='race'),
    NotUsedField(name='address'),
    NotUsedField(name='reserved'),
    NotUsedField(name='phone'),
    NotUsedField(name='physician_id'),
    NotUsedField(name='special_1'),
    NotUsedField(name='special_2'),
    NotUsedField(name='height'),
    NotUsedField(name='weight'),
    NotUsedField(name='diagnosis'),
    NotUsedField(name='medication'),
    NotUsedField(name='diet'),
    NotUsedField(name='practice_field_1'),
    NotUsedField(name='practice_field_2'),
    NotUsedField(name='admission_date'),
    NotUsedField(name='admission_status'),
    NotUsedField(name='location'),
    NotUsedField(name='diagnostic_code_nature'),
    NotUsedField(name='diagnostic_code'),
    NotUsedField(name='religion'),
    NotUsedField(name='martial_status'),
    NotUsedField(name='isolation_status'),
    NotUsedField(name='language'),
    NotUsedField(name='hospital_service'),
    NotUsedField(name='hospital_institution'),
    NotUsedField(name='dosage_category'),
)

OrderRecord = Record.build(
    ConstantField(name='type', default='O'),
    IntegerField(name='seq', default=1),
    NotUsedField(name='sample_id'),
    NotUsedField(name='instrument_id'),
    NotUsedField(name='test'),
    NotUsedField(name='priority'),
    NotUsedField(name='created_at'),
    NotUsedField(name='sampled_at'),
    NotUsedField(name='collected_at'),
    NotUsedField(name='volume'),
    NotUsedField(name='collector'),
    NotUsedField(name='action_code'),
    NotUsedField(name='danger_code'),
    NotUsedField(name='clinical_info'),
    NotUsedField(name='delivered_at'),
    NotUsedField(name='specimen_descriptor'),
    NotUsedField(name='physician'),
    NotUsedField(name='physician_phone'),
    NotUsedField(name='user_field_1'),
    NotUsedField(name='user_field_2'),
    NotUsedField(name='laboratory_field_1'),
    NotUsedField(name='laboratory_field_2'),
    NotUsedField(name='modified_at'),
    NotUsedField(name='instrument_charge'),
    NotUsedField(name='instrument_section'),
    NotUsedField(name='report_type'),
    NotUsedField(name='reserved'),
    NotUsedField(name='location_ward'),
    NotUsedField(name='infection_flag'),
    NotUsedField(name='specimen_service'),
    NotUsedField(name='laboratory')
)

ResultRecord = Record.build(
    ConstantField(name='type', default='R'),
    IntegerField(name='seq', default=1),
    NotUsedField(name='test'),
    NotUsedField(name='value'),
    NotUsedField(name='units'),
    NotUsedField(name='reference_ranges'),
    NotUsedField(name='is_abnormal'),
    NotUsedField(name='abnormality_nature'),
    NotUsedField(name='status'),
    NotUsedField(name='normatives_changed_at'),
    NotUsedField(name='operator'),
    NotUsedField(name='started_at'),
    NotUsedField(name='completed_at'),
    NotUsedField(name='instrument'),
)

CommentRecord = Record.build(
    ConstantField(name='type', default='C'),
    IntegerField(name='seq', default=1),
    NotUsedField(name='source'),
    NotUsedField(name='text'),
    NotUsedField(name='type')
)

TerminatorRecord = Record.build(
    ConstantField(name='type', default='L'),
    IntegerField(name='seq', default=1),
    ConstantField(name='code', default='N')
)
<|endoftext|>