#!/usr/bin/env python
"""Generate PostgreSQL classify functions from custom YAML mapping
Usage:
  generate_sql.py <config_file>
  generate_sql.py (-h | --help)
Options:
  -h --help                 Show this screen.
  --version                 Show version.
"""
from docopt import docopt
import yaml


class Classification(object):
    """Classification of a type (YAML key) to a class (YAML values)"""
    def __init__(self, classification_name, mappings):
        self.classification_name = classification_name
        self.mappings = mappings

    def generate_sql(self):
        generate_when = Classification._generate_when_statement
        when_statements = [generate_when(cl, val) for cl, val in self.mappings]

        return """CREATE OR REPLACE FUNCTION classify_{0}(type VARCHAR)
RETURNS VARCHAR AS $$
    BEGIN
        RETURN CASE
{1}
        END;
    END;
$$ LANGUAGE plpgsql IMMUTABLE;
        """.format(self.classification_name, "\n".join(when_statements))

    @staticmethod
    def _generate_when_statement(class_name, mapping_values):
        in_statements = ["'{}'".format(value) for value in mapping_values]
        return " " * 12 + "WHEN type IN ({0}) THEN '{1}'".format(
            ','.join(in_statements),
            class_name
        )


def find_classifications(config):
    for cl_name, cl_value in config['classifications'].items():
        mappings = cl_value.items()
        yield Classification(cl_name, mappings)


if __name__ == '__main__':
    args = docopt(__doc__)
    config_file = args['<config_file>']

    with open(config_file, 'r') as f:
        config = yaml.load(f)
        for cl in find_classifications(config):
            print(cl.generate_sql())

@@ -254,16 +254,51 @@
 on.%0A%22%22%22%0A
+from collections import namedtuple%0A
 from doc
@@ -329,22 +329,16 @@
  yaml%0A%0A%0A
-class 
 Classifi
@@ -347,113 +347,24 @@
 tion
-(object):%0A    %22%22%22Classification of a type (YAML key) to a class (YAML values)%22%22%22%0A    def __init__(self, c
+ = namedtuple('C
 lass
@@ -372,31 +372,37 @@
 fication
-_
+', %5B'
 name
+'
 , 
+'
 mappings
 ):%0A     
@@ -397,196 +397,48 @@
 ings
-):%0A        self.classification_name = classification_name%0A        self.mappings = mappings%0A%0A    def generate_sql(self):%0A        generate_when = Classification._generate_when_statement%0A    
+'%5D)%0A%0A%0Adef generate_sql(classification):%0A
     
@@ -456,16 +456,17 @@
 ents = %5B
+_
 generate
@@ -470,16 +470,26 @@
 ate_when
+_statement
 (cl, val
@@ -508,13 +508,46 @@
 l in
- self
+%0A                       classification
 .map
@@ -554,20 +554,16 @@
 pings%5D%0A%0A
-    
     retu
@@ -648,22 +648,14 @@
  $$%0A
-    
 BEGIN%0A
-    
     
@@ -674,21 +674,8 @@
 %7B1%7D%0A
-        END;%0A
     
@@ -679,16 +679,21 @@
    END;%0A
+END;%0A
 $$ LANGU
@@ -715,20 +715,16 @@
 UTABLE;%0A
-    
     %22%22%22.
@@ -734,13 +734,8 @@
 mat(
-self.
 clas
@@ -744,17 +744,17 @@
 fication
-_
+.
 name, %22%5C
@@ -784,30 +784,9 @@
 ))%0A%0A
-    @staticmethod%0A    
+%0A
 def 
@@ -843,20 +843,16 @@
 s):%0A    
-    
 in_state
@@ -914,20 +914,16 @@
 es%5D%0A    
-    
 return %22
@@ -980,20 +980,16 @@
         
-    
 ','.join
@@ -1009,28 +1009,24 @@
 s),%0A        
-    
 class_name%0A 
@@ -1024,20 +1024,16 @@
 ss_name%0A
-    
     )%0A%0A%0A
@@ -1449,11 +1449,8 @@
 int(
-cl.
 gene
@@ -1458,11 +1458,13 @@
 ate_sql(
+cl
 ))%0A

Remove classes, functions is all we need