<s> import collections <EOL> import numbers <EOL> import os <EOL> import re <EOL> from . errors import BlockadeConfigError <EOL> class BlockadeContainerConfig ( object ) : <EOL> '''<STR_LIT>''' <EOL> @ staticmethod <EOL> def from_dict ( name , values ) : <EOL> '''<STR_LIT>''' <EOL> count = <NUM_LIT:1> <EOL> count_value = values . get ( '<STR_LIT:count>' , <NUM_LIT:1> ) <EOL> if isinstance ( count_value , int ) : <EOL> count = max ( count_value , <NUM_LIT:1> ) <EOL> def with_index ( name , idx ) : <EOL> if name and idx : <EOL> return '<STR_LIT>' % ( name , idx ) <EOL> return name <EOL> def get_instance ( n , idx = None ) : <EOL> return BlockadeContainerConfig ( <EOL> with_index ( n , idx ) , <EOL> values [ '<STR_LIT:image>' ] , <EOL> command = values . get ( '<STR_LIT>' ) , <EOL> links = values . get ( '<STR_LIT>' ) , <EOL> volumes = values . get ( '<STR_LIT>' ) , <EOL> publish_ports = values . get ( '<STR_LIT>' ) , <EOL> expose_ports = values . get ( '<STR_LIT>' ) , <EOL> environment = values . get ( '<STR_LIT>' ) , <EOL> hostname = values . get ( '<STR_LIT>' ) , <EOL> dns = values . get ( '<STR_LIT>' ) , <EOL> start_delay = values . get ( '<STR_LIT>' , <NUM_LIT:0> ) , <EOL> neutral = values . get ( '<STR_LIT>' , False ) , <EOL> holy = values . get ( '<STR_LIT>' , False ) , <EOL> container_name = with_index ( values . get ( '<STR_LIT>' ) , idx ) ) <EOL> if count == <NUM_LIT:1> : <EOL> yield get_instance ( name ) <EOL> else : <EOL> for idx in range ( <NUM_LIT:1> , count + <NUM_LIT:1> ) : <EOL> yield get_instance ( name , idx ) <EOL> def __init__ ( self , name , image , command = None , links = None , volumes = None , <EOL> publish_ports = None , expose_ports = None , environment = None , <EOL> hostname = None , dns = None , start_delay = <NUM_LIT:0> , neutral = False , <EOL> holy = False , container_name = None ) : <EOL> self . name = name <EOL> self . hostname = hostname <EOL> self . dns = dns <EOL> self . image = image <EOL> self . command = command <EOL> self . links = _dictify ( links , '<STR_LIT>' ) <EOL> self . volumes = _dictify ( volumes , '<STR_LIT>' , lambda x : os . path . abspath ( _populate_env ( x ) ) ) <EOL> self . publish_ports = _dictify ( publish_ports , '<STR_LIT>' ) <EOL> self . neutral = neutral <EOL> self . holy = holy <EOL> self . container_name = container_name <EOL> if neutral and holy : <EOL> raise BlockadeConfigError ( "<STR_LIT>" ) <EOL> if not ( isinstance ( start_delay , numbers . Number ) and start_delay >= <NUM_LIT:0> ) : <EOL> raise BlockadeConfigError ( "<STR_LIT>" ) <EOL> self . start_delay = start_delay <EOL> self . expose_ports = list ( set ( <EOL> int ( port ) for port in <EOL> ( expose_ports or [ ] ) + list ( self . publish_ports . values ( ) ) <EOL> ) ) <EOL> self . environment = _dictify ( environment , _populate_env , _populate_env ) <EOL> _DEFAULT_NETWORK_CONFIG = { <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> } <EOL> class BlockadeConfig ( object ) : <EOL> @ staticmethod <EOL> def from_dict ( values ) : <EOL> '''<STR_LIT>''' <EOL> try : <EOL> containers = values [ '<STR_LIT>' ] <EOL> parsed_containers = { } <EOL> for name , container_dict in containers . items ( ) : <EOL> try : <EOL> for cnt in BlockadeContainerConfig . from_dict ( name , container_dict ) : <EOL> if cnt . container_name : <EOL> cname = cnt . container_name <EOL> existing = [ c for c in parsed_containers . values ( ) if c . container_name == cname ] <EOL> if existing : <EOL> raise BlockadeConfigError ( "<STR_LIT>" % ( cname ) ) <EOL> parsed_containers [ cnt . name ] = cnt <EOL> except Exception as err : <EOL> raise BlockadeConfigError ( <EOL> "<STR_LIT>" % ( name , err ) ) <EOL> network = values . get ( '<STR_LIT>' ) <EOL> if network : <EOL> defaults = _DEFAULT_NETWORK_CONFIG . copy ( ) <EOL> defaults . update ( network ) <EOL> network = defaults <EOL> else : <EOL> network = _DEFAULT_NETWORK_CONFIG . copy ( ) <EOL> return BlockadeConfig ( parsed_containers , network = network ) <EOL> except KeyError as err : <EOL> raise BlockadeConfigError ( "<STR_LIT>" + str ( err ) ) <EOL> except Exception as err : <EOL> raise BlockadeConfigError ( "<STR_LIT>" + str ( err ) ) <EOL> def __init__ ( self , containers , network = None ) : <EOL> self . containers = containers <EOL> self . sorted_containers = dependency_sorted ( containers ) <EOL> self . network = network or { } <EOL> def _populate_env ( value ) : <EOL> cwd = os . getcwd ( ) <EOL> builtins = { <EOL> '<STR_LIT>' : cwd , <EOL> '<STR_LIT>' : cwd <EOL> } <EOL> def get_env_value ( match ) : <EOL> key = match . group ( <NUM_LIT:1> ) <EOL> env = os . environ . get ( key ) or builtins . get ( key ) <EOL> if not env : <EOL> raise BlockadeConfigError ( "<STR_LIT>" % ( key ) ) <EOL> return env <EOL> return re . sub ( r"<STR_LIT>" , get_env_value , value ) <EOL> def _dictify ( data , name = '<STR_LIT:input>' , key_mod = lambda x : x , value_mod = lambda x : x ) : <EOL> if data : <EOL> if isinstance ( data , collections . Sequence ) : <EOL> return dict ( ( key_mod ( str ( v ) ) , value_mod ( str ( v ) ) ) for v in data ) <EOL> elif isinstance ( data , collections . Mapping ) : <EOL> return dict ( ( key_mod ( str ( k ) ) , value_mod ( str ( v or k ) ) ) for k , v in list ( data . items ( ) ) ) <EOL> else : <EOL> raise BlockadeConfigError ( "<STR_LIT>" <EOL> % ( name , ) ) <EOL> else : <EOL> return { } <EOL> def dependency_sorted ( containers ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( containers , collections . Mapping ) : <EOL> containers = dict ( ( c . name , c ) for c in containers ) <EOL> container_links = dict ( ( name , set ( c . links . keys ( ) ) ) <EOL> for name , c in containers . items ( ) ) <EOL> sorted_names = _resolve ( container_links ) <EOL> return [ containers [ name ] for name in sorted_names ] <EOL> def _resolve ( d ) : <EOL> all_keys = frozenset ( d . keys ( ) ) <EOL> result = [ ] <EOL> resolved_keys = set ( ) <EOL> while d : <EOL> resolved_this_round = set ( ) <EOL> for name , links in list ( d . items ( ) ) : <EOL> if not links or links <= resolved_keys : <EOL> result . append ( name ) <EOL> resolved_this_round . add ( name ) <EOL> del d [ name ] <EOL> unknown = links - all_keys <EOL> if len ( unknown ) == <NUM_LIT:1> : <EOL> raise BlockadeConfigError ( <EOL> "<STR_LIT>" % <EOL> ( name , list ( unknown ) [ <NUM_LIT:0> ] ) ) <EOL> elif len ( unknown ) > <NUM_LIT:1> : <EOL> raise BlockadeConfigError ( <EOL> "<STR_LIT>" % <EOL> ( name , unknown ) ) <EOL> if not resolved_this_round : <EOL> raise BlockadeConfigError ( "<STR_LIT>" ) <EOL> resolved_keys . update ( resolved_this_round ) <EOL> return result </s>
