def FromJsonString(self, value):
    """Converts string to FieldMask according to proto3 JSON spec."""
    self.Clear()
    for path in value.split(','):
      self.paths.append(path)

def FromJsonString ( self , value ) : self . Clear ( ) for path in value . split ( ',' ) : self . paths . append ( path )

Converts string to FieldMask according to proto3 JSON spec .


def get_doc(doc_id, db_name, server_url='http://127.0.0.1:5984/', rev=None):
    """Return a CouchDB document, given its ID, revision and database name."""
    db = get_server(server_url)[db_name]
    if rev:
        headers, response = db.resource.get(doc_id, rev=rev)
        return couchdb.client.Document(response)
    return db[doc_id]

def get_doc ( doc_id , db_name , server_url = 'http://127.0.0.1:5984/' , rev = None ) : db = get_server ( server_url ) [ db_name ] if rev : headers , response = db . resource . get ( doc_id , rev = rev ) return couchdb . client . Document ( response ) return db [ doc_id ]

Return a CouchDB document given its ID revision and database name .


def read(readme):
    """Give reST format README for pypi."""
    extend = os.path.splitext(readme)[1]
    if (extend == '.rst'):
        import codecs
        return codecs.open(readme, 'r', 'utf-8').read()
    elif (extend == '.md'):
        import pypandoc
        return pypandoc.convert(readme, 'rst')

def read ( readme ) : extend = os . path . splitext ( readme ) [ 1 ] if ( extend == '.rst' ) : import codecs return codecs . open ( readme , 'r' , 'utf-8' ) . read ( ) elif ( extend == '.md' ) : import pypandoc return pypandoc . convert ( readme , 'rst' )


def remove(self, collection, **kwargs):
        '''
        remove records from collection whose parameters match kwargs
        '''
        callback = kwargs.pop('callback')
        yield Op(self.db[collection].remove, kwargs)
        callback()

def remove ( self , collection , ** kwargs ) : callback = kwargs . pop ( 'callback' ) yield Op ( self . db [ collection ] . remove , kwargs ) callback ( )


def _url(self):
        """
        Resolve the URL to this point.

        >>> trello = TrelloAPIV1('APIKEY')
        >>> trello.batch._url
        '1/batch'
        >>> trello.boards(board_id='BOARD_ID')._url
        '1/boards/BOARD_ID'
        >>> trello.boards(board_id='BOARD_ID')(field='FIELD')._url
        '1/boards/BOARD_ID/FIELD'
        >>> trello.boards(board_id='BOARD_ID').cards(filter='FILTER')._url
        '1/boards/BOARD_ID/cards/FILTER'

        """
        if self._api_arg:
            mypart = str(self._api_arg)
        else:
            mypart = self._name

        if self._parent:
            return '/'.join(filter(None, [self._parent._url, mypart]))
        else:
            return mypart

def _url ( self ) : if self . _api_arg : mypart = str ( self . _api_arg ) else : mypart = self . _name if self . _parent : return '/' . join ( filter ( None , [ self . _parent . _url , mypart ] ) ) else : return mypart


def _api_call(self, method_name, *args, **kwargs):
        """
        Makes the HTTP request.

        """
        params = kwargs.setdefault('params', {})
        params.update({'key': self._apikey})
        if self._token is not None:
            params.update({'token': self._token})

        http_method = getattr(requests, method_name)
        return http_method(TRELLO_URL + self._url, *args, **kwargs)

def _api_call ( self , method_name , * args , ** kwargs ) : params = kwargs . setdefault ( 'params' , { } ) params . update ( { 'key' : self . _apikey } ) if self . _token is not None : params . update ( { 'token' : self . _token } ) http_method = getattr ( requests , method_name ) return http_method ( TRELLO_URL + self . _url , * args , ** kwargs )


def _SkipFieldValue(tokenizer):
  """Skips over a field value.

  Args:
    tokenizer: A tokenizer to parse the field name and values.

  Raises:
    ParseError: In case an invalid field value is found.
  """
  # String/bytes tokens can come in multiple adjacent string literals.
  # If we can consume one, consume as many as we can.
  if tokenizer.TryConsumeByteString():
    while tokenizer.TryConsumeByteString():
      pass
    return

  if (not tokenizer.TryConsumeIdentifier() and
      not tokenizer.TryConsumeInt64() and
      not tokenizer.TryConsumeUint64() and
      not tokenizer.TryConsumeFloat()):
    raise ParseError('Invalid field value: ' + tokenizer.token)

def
_SkipFieldValue
(
tokenizer
)
:
if
tokenizer
.
TryConsumeByteString
(
)
:
while
tokenizer
.
TryConsumeByteString
(
)
:
pass
return
if
(
not
tokenizer
.
TryConsumeIdentifier
(
)
and
not
tokenizer
.
TryConsumeInt64
(
)
and
not
tokenizer
.
TryConsumeUint64
(
)
and
not
tokenizer
.
TryConsumeFloat
(
)
)
:
raise
ParseError
(
'Invalid field value: '
+
tokenizer
.
token
)


def ParseInteger(text, is_signed=False, is_long=False):
  """Parses an integer.

  Args:
    text: The text to parse.
    is_signed: True if a signed integer must be parsed.
    is_long: True if a long integer must be parsed.

  Returns:
    The integer value.

  Raises:
    ValueError: Thrown Iff the text is not a valid integer.
  """
  # Do the actual parsing. Exception handling is propagated to caller.
  try:
    # We force 32-bit values to int and 64-bit values to long to make
    # alternate implementations where the distinction is more significant
    # (e.g. the C++ implementation) simpler.
    if is_long:
      result = long(text, 0)
    else:
      result = int(text, 0)
  except ValueError:
    raise ValueError('Couldn\'t parse integer: %s' % text)

  # Check if the integer is sane. Exceptions handled by callers.
  checker = _INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)]
  checker.CheckValue(result)
  return result

def
ParseInteger
(
text
,
is_signed
=
False
,
is_long
=
False
)
:
try
:
if
is_long
:
result
=
long
(
text
,
0
)
else
:
result
=
int
(
text
,
0
)
except
ValueError
:
raise
ValueError
(
'Couldn\'t parse integer: %s'
%
text
)
checker
=
_INTEGER_CHECKERS
[
2
*
int
(
is_long
)
+
int
(
is_signed
)
]
checker
.
CheckValue
(
result
)
return
result


def PrintMessage(self, message):
    """Convert protobuf message to text format.

    Args:
      message: The protocol buffers message.
    """
    fields = message.ListFields()
    if self.use_index_order:
      fields.sort(key=lambda x: x[0].index)
    for field, value in fields:
      if _IsMapEntry(field):
        for key in sorted(value):
          # This is slow for maps with submessage entires because it copies the
          # entire tree.  Unfortunately this would take significant refactoring
          # of this file to work around.
          #
          # TODO(haberman): refactor and optimize if this becomes an issue.
          entry_submsg = field.message_type._concrete_class(
              key=key, value=value[key])
          self.PrintField(field, entry_submsg)
      elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
        for element in value:
          self.PrintField(field, element)
      else:
        self.PrintField(field, value)

def PrintMessage ( self , message ) : fields = message . ListFields ( ) if self . use_index_order : fields . sort ( key = lambda x : x [ 0 ] . index ) for field , value in fields : if _IsMapEntry ( field ) : for key in sorted ( value ) : entry_submsg = field . message_type . _concrete_class ( key = key , value = value [ key ] ) self . PrintField ( field , entry_submsg ) elif field . label == descriptor . FieldDescriptor . LABEL_REPEATED : for element in value : self . PrintField ( field , element ) else : self . PrintField ( field , value )

Convert protobuf message to text format .


def _ParseOrMerge(self, lines, message):
    """Converts an text representation of a protocol message into a message.

    Args:
      lines: Lines of a message's text representation.
      message: A protocol buffer message to merge into.

    Raises:
      ParseError: On text parsing problems.
    """
    tokenizer = _Tokenizer(lines)
    while not tokenizer.AtEnd():
      self._MergeField(tokenizer, message)

def _ParseOrMerge ( self , lines , message ) : tokenizer = _Tokenizer ( lines ) while not tokenizer . AtEnd ( ) : self . _MergeField ( tokenizer , message )

Converts an text representation of a protocol message into a message .


def _MergeMessageField(self, tokenizer, message, field):
    """Merges a single scalar field into a message.

    Args:
      tokenizer: A tokenizer to parse the field value.
      message: The message of which field is a member.
      field: The descriptor of the field to be merged.

    Raises:
      ParseError: In case of text parsing problems.
    """
    is_map_entry = _IsMapEntry(field)

    if tokenizer.TryConsume('<'):
      end_token = '>'
    else:
      tokenizer.Consume('{')
      end_token = '}'

    if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
      if field.is_extension:
        sub_message = message.Extensions[field].add()
      elif is_map_entry:
        # pylint: disable=protected-access
        sub_message = field.message_type._concrete_class()
      else:
        sub_message = getattr(message, field.name).add()
    else:
      if field.is_extension:
        sub_message = message.Extensions[field]
      else:
        sub_message = getattr(message, field.name)
      sub_message.SetInParent()

    while not tokenizer.TryConsume(end_token):
      if tokenizer.AtEnd():
        raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token,))
      self._MergeField(tokenizer, sub_message)

    if is_map_entry:
      value_cpptype = field.message_type.fields_by_name['value'].cpp_type
      if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
        value = getattr(message, field.name)[sub_message.key]
        value.MergeFrom(sub_message.value)
      else:
        getattr(message, field.name)[sub_message.key] = sub_message.value

def
_MergeMessageField
(
self
,
tokenizer
,
message
,
field
)
:
is_map_entry
=
_IsMapEntry
(
field
)
if
tokenizer
.
TryConsume
(
'<'
)
:
end_token
=
'>'
else
:
tokenizer
.
Consume
(
'{'
)
end_token
=
'}'
if
field
.
label
==
descriptor
.
FieldDescriptor
.
LABEL_REPEATED
:
if
field
.
is_extension
:
sub_message
=
message
.
Extensions
[
field
]
.
add
(
)
elif
is_map_entry
:
sub_message
=
field
.
message_type
.
_concrete_class
(
)
else
:
sub_message
=
getattr
(
message
,
field
.
name
)
.
add
(
)
else
:
if
field
.
is_extension
:
sub_message
=
message
.
Extensions
[
field
]
else
:
sub_message
=
getattr
(
message
,
field
.
name
)
sub_message
.
SetInParent
(
)
while
not
tokenizer
.
TryConsume
(
end_token
)
:
if
tokenizer
.
AtEnd
(
)
:
raise
tokenizer
.
ParseErrorPreviousToken
(
'Expected "%s".'
%
(
end_token
,
)
)
self
.
_MergeField
(
tokenizer
,
sub_message
)
if
is_map_entry
:
value_cpptype
=
field
.
message_type
.
fields_by_name
[
'value'
]
.
cpp_type
if
value_cpptype
==
descriptor
.
FieldDescriptor
.
CPPTYPE_MESSAGE
:
value
=
getattr
(
message
,
field
.
name
)
[
sub_message
.
key
]
value
.
MergeFrom
(
sub_message
.
value
)
else
:
getattr
(
message
,
field
.
name
)
[
sub_message
.
key
]
=
sub_message
.
value

Merges a single scalar field into a message .


def ConsumeIdentifier(self):
    """Consumes protocol message field identifier.

    Returns:
      Identifier string.

    Raises:
      ParseError: If an identifier couldn't be consumed.
    """
    result = self.token
    if not self._IDENTIFIER.match(result):
      raise self._ParseError('Expected identifier.')
    self.NextToken()
    return result

def
ConsumeIdentifier
(
self
)
:
result
=
self
.
token
if
not
self
.
_IDENTIFIER
.
match
(
result
)
:
raise
self
.
_ParseError
(
'Expected identifier.'
)
self
.
NextToken
(
)
return
result

Consumes protocol message field identifier .


def ConsumeInt32(self):
    """Consumes a signed 32bit integer number.

    Returns:
      The integer parsed.

    Raises:
      ParseError: If a signed 32bit integer couldn't be consumed.
    """
    try:
      result = ParseInteger(self.token, is_signed=True, is_long=False)
    except ValueError as e:
      raise self._ParseError(str(e))
    self.NextToken()
    return result

def ConsumeInt32 ( self ) : try : result = ParseInteger ( self . token , is_signed = True , is_long = False ) except ValueError as e : raise self . _ParseError ( str ( e ) ) self . NextToken ( ) return result

Consumes a signed 32bit integer number .


def ConsumeFloat(self):
    """Consumes an floating point number.

    Returns:
      The number parsed.

    Raises:
      ParseError: If a floating point number couldn't be consumed.
    """
    try:
      result = ParseFloat(self.token)
    except ValueError as e:
      raise self._ParseError(str(e))
    self.NextToken()
    return result

def ConsumeFloat ( self ) : try : result = ParseFloat ( self . token ) except ValueError as e : raise self . _ParseError ( str ( e ) ) self . NextToken ( ) return result


def ConsumeBool(self):
    """Consumes a boolean value.

    Returns:
      The bool parsed.

    Raises:
      ParseError: If a boolean value couldn't be consumed.
    """
    try:
      result = ParseBool(self.token)
    except ValueError as e:
      raise self._ParseError(str(e))
    self.NextToken()
    return result

def ConsumeBool ( self ) : try : result = ParseBool ( self . token ) except ValueError as e : raise self . _ParseError ( str ( e ) ) self . NextToken ( ) return result


def _ConsumeSingleByteString(self):
    """Consume one token of a string literal.

    String literals (whether bytes or text) can come in multiple adjacent
    tokens which are automatically concatenated, like in C or Python.  This
    method only consumes one token.

    Returns:
      The token parsed.
    Raises:
      ParseError: When the wrong format data is found.
    """
    text = self.token
    if len(text) < 1 or text[0] not in _QUOTES:
      raise self._ParseError('Expected string but found: %r' % (text,))

    if len(text) < 2 or text[-1] != text[0]:
      raise self._ParseError('String missing ending quote: %r' % (text,))

    try:
      result = text_encoding.CUnescape(text[1:-1])
    except ValueError as e:
      raise self._ParseError(str(e))
    self.NextToken()
    return result

def
_ConsumeSingleByteString
(
self
)
:
text
=
self
.
token
if
len
(
text
)
<
1
or
text
[
0
]
not
in
_QUOTES
:
raise
self
.
_ParseError
(
'Expected string but found: %r'
%
(
text
,
)
)
if
len
(
text
)
<
2
or
text
[
1
]
!=
text
[
0
]
:
raise
self
.
_ParseError
(
'String missing ending quote: %r'
%
(
text
,
)
)
try
:
result
=
text_encoding
.
CUnescape
(
text
[
1
:
1
]
)
except
ValueError
as
e
:
raise
self
.
_ParseError
(
str
(
e
)
)
self
.
NextToken
(
)
return
result


def arkt_to_unixt(ark_timestamp):
    """ convert ark timestamp to unix timestamp"""
    res = datetime.datetime(2017, 3, 21, 15, 55, 44) + datetime.timedelta(seconds=ark_timestamp)
    return res.timestamp()

def arkt_to_unixt ( ark_timestamp ) : res = datetime . datetime ( 2017 , 3 , 21 , 15 , 55 , 44 ) + datetime . timedelta ( seconds = ark_timestamp ) return res . timestamp ( )


def close(self):
        """Close the connection."""
        try:
            self.conn.close()
            self.logger.debug("Close connect succeed.")
        except pymssql.Error as e:
            self.unknown("Close connect error: %s" % e)

def
close
(
self
)
:
try
:
self
.
conn
.
close
(
)
self
.
logger
.
debug
(
"Close connect succeed."
)
except
pymssql
.
Error
as
e
:
self
.
unknown
(
"Close connect error: %s"
%
e
)


def process_macros(self, content: str) -> str:
        '''Replace macros with content defined in the config.

        :param content: Markdown content

        :returns: Markdown content without macros
        '''

        def _sub(macro):
            name = macro.group('body')
            params = self.get_options(macro.group('options'))

            return self.options['macros'].get(name, '').format_map(params)

        return self.pattern.sub(_sub, content)

def process_macros ( self , content : str ) -> str : def _sub ( macro ) : name = macro . group ( 'body' ) params = self . get_options ( macro . group ( 'options' ) ) return self . options [ 'macros' ] . get ( name , '' ) . format_map ( params ) return self . pattern . sub ( _sub , content )

Replace macros with content defined in the config .


def get_unique_pathname(path, root=''):
	"""Return a pathname possibly with a number appended to it so that it is
	unique in the directory."""
	path = os.path.join(root, path)
	# consider the path supplied, then the paths with numbers appended
	potentialPaths = itertools.chain((path,), __get_numbered_paths(path))
	potentialPaths = six.moves.filterfalse(os.path.exists, potentialPaths)
	return next(potentialPaths)

def get_unique_pathname ( path , root = '' ) : path = os . path . join ( root , path ) potentialPaths = itertools . chain ( ( path , ) , __get_numbered_paths ( path ) ) potentialPaths = six . moves . filterfalse ( os . path . exists , potentialPaths ) return next ( potentialPaths )

Return a pathname possibly with a number appended to it so that it is unique in the directory .


def __get_numbered_paths(filepath):
	"""Append numbers in sequential order to the filename or folder name
	Numbers should be appended before the extension on a filename."""
	format = '%s (%%d)%s' % splitext_files_only(filepath)
	return map(lambda n: format % n, itertools.count(1))

def
__get_numbered_paths
(
filepath
)
:
format
=
'%s (%%d)%s'
%
splitext_files_only
(
filepath
)
return
map
(
lambda
n
:
format
%
n
,
itertools
.
count
(
1
)
)

Append numbers in sequential order to the filename or folder name Numbers should be appended before the extension on a filename .


def splitext_files_only(filepath):
	"Custom version of splitext that doesn't perform splitext on directories"
	return (
		(filepath, '') if os.path.isdir(filepath) else os.path.splitext(filepath)
	)

Custom version of splitext that doesn t perform splitext on directories


def set_time(filename, mod_time):
	"""
	Set the modified time of a file
	"""
	log.debug('Setting modified time to %s', mod_time)
	mtime = calendar.timegm(mod_time.utctimetuple())
	# utctimetuple discards microseconds, so restore it (for consistency)
	mtime += mod_time.microsecond / 1000000
	atime = os.stat(filename).st_atime
	os.utime(filename, (atime, mtime))

def
set_time
(
filename
,
mod_time
)
:
log
.
debug
(
'Setting modified time to %s'
,
mod_time
)
mtime
=
calendar
.
timegm
(
mod_time
.
utctimetuple
(
)
)
mtime
+=
mod_time
.
microsecond
/
1000000
atime
=
os
.
stat
(
filename
)
.
st_atime
os
.
utime
(
filename
,
(
atime
,
mtime
)
)


def get_time(filename):
	"""
	Get the modified time for a file as a datetime instance
	"""
	ts = os.stat(filename).st_mtime
	return datetime.datetime.utcfromtimestamp(ts)

def get_time ( filename ) : ts = os . stat ( filename ) . st_mtime return datetime . datetime . utcfromtimestamp ( ts )


def ensure_dir_exists(func):
	"wrap a function that returns a dir, making sure it exists"
	@functools.wraps(func)
	def make_if_not_present():
		dir = func()
		if not os.path.isdir(dir):
			os.makedirs(dir)
		return dir
	return make_if_not_present

wrap a function that returns a dir making sure it exists


def is_hidden(path):
	"""
	Check whether a file is presumed hidden, either because
	the pathname starts with dot or because the platform
	indicates such.
	"""
	full_path = os.path.abspath(path)
	name = os.path.basename(full_path)

	def no(path):
		return False
	platform_hidden = globals().get('is_hidden_' + platform.system(), no)
	return name.startswith('.') or platform_hidden(full_path)

def is_hidden ( path ) : full_path = os . path . abspath ( path ) name = os . path . basename ( full_path ) def no ( path ) : return False platform_hidden = globals ( ) . get ( 'is_hidden_' + platform . system ( ) , no ) return name . startswith ( '.' ) or platform_hidden ( full_path )

Check whether a file is presumed hidden either because the pathname starts with dot or because the platform indicates such .


def age(self):
        """
        Get closer to your EOL
        """
        # 0 means this composer will never decompose
        if self.rounds == 1:
            self.do_run = False
        elif self.rounds > 1:
            self.rounds -= 1

def age ( self ) : if self . rounds == 1 : self . do_run = False elif self . rounds > 1 : self . rounds -= 1


def run(self):
        """
        Open a connection over the serial line and receive data lines
        """
        if not self.device:
            return
        try:
            data = ""
            while (self.do_run):
                try:
                    if (self.device.inWaiting() > 1):
                        l = self.device.readline()[:-2]
                        l = l.decode("UTF-8")

                        if (l == "["):
                            # start recording
                            data = "["
                        elif (l == "]") and (len(data) > 4) and (data[0] == "["):
                            # now parse the input
                            data = data + "]"
                            self.store.register_json(data)
                            self.age()
                        elif (l[0:3] == "  {"):
                            # this is a data line
                            data = data + " " + l
                    else:
                        # this is a slow interface - give it some time
                        sleep(1)
                        # then count down..
                        self.age()
                except (UnicodeDecodeError, ValueError):
                    # only accepting unicode: throw away the whole bunch
                    data = ""
                    # and count down the exit condition
                    self.age()

        except serial.serialutil.SerialException:
            print("Could not connect to the serial line at " + self.device_name)


def append_main_thread(self):
        """create & start main thread

        :return: None
        """
        thread = MainThread(main_queue=self.main_queue,
                            main_spider=self.main_spider,
                            branch_spider=self.branch_spider)
        thread.daemon = True
        thread.start()

def append_main_thread ( self ) : thread = MainThread ( main_queue = self . main_queue , main_spider = self . main_spider , branch_spider = self . branch_spider ) thread . daemon = True thread . start ( )


def getTextFromNode(node):
    """
    Scans through all children of node and gathers the
    text. If node has non-text child-nodes then
    NotTextNodeError is raised.
    """
    t = ""
    for n in node.childNodes:
        if n.nodeType == n.TEXT_NODE:
            t += n.nodeValue
        else:
            raise NotTextNodeError
    return t

def getTextFromNode ( node ) : t = "" for n in node . childNodes : if n . nodeType == n . TEXT_NODE : t += n . nodeValue else : raise NotTextNodeError return t

Scans through all children of node and gathers the text . If node has non - text child - nodes then NotTextNodeError is raised .


def getbalance(self, url='http://services.ambientmobile.co.za/credits'):
        """
        Get the number of credits remaining at AmbientSMS
        """
        postXMLList = []
        postXMLList.append("<api-key>%s</api-key>" % self.api_key)
        postXMLList.append("<password>%s</password>" % self.password)
        postXML = '<sms>%s</sms>' % "".join(postXMLList)
        result = self.curl(url, postXML)

        if result.get("credits", None):
            return result["credits"]
        else:
            raise AmbientSMSError(result["status"])


def sendmsg(self,
                message,
                recipient_mobiles=[],
                url='http://services.ambientmobile.co.za/sms',
                concatenate_message=True,
                message_id=str(time()).replace(".", ""),
                reply_path=None,
                allow_duplicates=True,
                allow_invalid_numbers=True,
                ):

        """
        Send a mesage via the AmbientSMS API server
        """
        if not recipient_mobiles or not(isinstance(recipient_mobiles, list) \
                or isinstance(recipient_mobiles, tuple)):
            raise AmbientSMSError("Missing recipients")

        if not message or not len(message):
            raise AmbientSMSError("Missing message")

        postXMLList = []
        postXMLList.append("<api-key>%s</api-key>" % self.api_key)
        postXMLList.append("<password>%s</password>" % self.password)
        postXMLList.append("<recipients>%s</recipients>" % \
                "".join(["<mobile>%s</mobile>" % \
                m for m in recipient_mobiles]))
        postXMLList.append("<msg>%s</msg>" % message)
        postXMLList.append("<concat>%s</concat>" % \
                (1 if concatenate_message else 0))
        postXMLList.append("<message_id>%s</message_id>" % message_id)
        postXMLList.append("<allow_duplicates>%s</allow_duplicates>" % \
                (1 if allow_duplicates else 0))
        postXMLList.append(
            "<allow_invalid_numbers>%s</allow_invalid_numbers>" % \
                    (1 if allow_invalid_numbers else 0)
        )
        if reply_path:
            postXMLList.append("<reply_path>%s</reply_path>" % reply_path)

        postXML = '<sms>%s</sms>' % "".join(postXMLList)
        result = self.curl(url, postXML)

        status = result.get("status", None)
        if status and int(status) in [0, 1, 2]:
            return result
        else:
            raise AmbientSMSError(int(status))


def curl(self, url, post):
        """
        Inteface for sending web requests to the AmbientSMS API Server
        """
        try:
            req = urllib2.Request(url)
            req.add_header("Content-type", "application/xml")
            data = urllib2.urlopen(req, post.encode('utf-8')).read()
        except urllib2.URLError, v:
            raise AmbientSMSError(v)
        return dictFromXml(data)

def curl ( self , url , post ) : try : req = urllib2 . Request ( url ) req . add_header ( "Content-type" , "application/xml" ) data = urllib2 . urlopen ( req , post . encode ( 'utf-8' ) ) . read ( ) except urllib2 . URLError , v : raise AmbientSMSError ( v ) return dictFromXml ( data )


def contents(self, f, text):
        """
        Called for each file
        Must return file content
        Can be wrapped

        :type f: static_bundle.files.StaticFileResult
        :type text: str|unicode
        :rtype: str|unicode
        """
        text += self._read(f.abs_path) + "\r\n"
        return text

def contents ( self , f , text ) : text += self . _read ( f . abs_path ) + "\r\n" return text


def is_date_type(cls):
    """Return True if the class is a date type."""
    if not isinstance(cls, type):
        return False
    return issubclass(cls, date) and not issubclass(cls, datetime)

def is_date_type ( cls ) : if not isinstance ( cls , type ) : return False return issubclass ( cls , date ) and not issubclass ( cls , datetime )

Return True if the class is a date type .


def to_datetime(when):
    """
    Convert a date or time to a datetime. If when is a date then it sets the time to midnight. If
    when is a time it sets the date to the epoch. If when is None or a datetime it returns when.
    Otherwise a TypeError is raised. Returned datetimes have tzinfo set to None unless when is a
    datetime with tzinfo set in which case it remains the same.
    """
    if when is None or is_datetime(when):
        return when
    if is_time(when):
        return datetime.combine(epoch.date(), when)
    if is_date(when):
        return datetime.combine(when, time(0))
    raise TypeError("unable to convert {} to datetime".format(when.__class__.__name__))

def
to_datetime
(
when
)
:
if
when
is
or
is_datetime
(
when
)
:
return
when
if
is_time
(
when
)
:
return
datetime
.
combine
(
epoch
.
date
(
)
,
when
)
if
is_date
(
when
)
:
return
datetime
.
combine
(
when
,
time
(
0
)
)
raise
TypeError
(
"unable to convert {} to datetime"
.
format
(
when
.
__class__
.
__name__
)
)

Convert a date or time to a datetime . If when is a date then it sets the time to midnight . If when is a time it sets the date to the epoch . If when is None or a datetime it returns when . Otherwise a TypeError is raised . Returned datetimes have tzinfo set to None unless when is a datetime with tzinfo set in which case it remains the same .


def totz(when, tz=None):
    """
    Return a date, time, or datetime converted to a datetime in the given timezone. If when is a
    datetime and has no timezone it is assumed to be local time. Date and time objects are also
    assumed to be UTC. The tz value defaults to UTC. Raise TypeError if when cannot be converted to
    a datetime.
    """
    if when is None:
        return None
    when = to_datetime(when)
    if when.tzinfo is None:
        when = when.replace(tzinfo=localtz)
    return when.astimezone(tz or utc)

def totz ( when , tz = None ) : if when is None : return None when = to_datetime ( when ) if when . tzinfo is None : when = when . replace ( tzinfo = localtz ) return when . astimezone ( tz or utc )

Return a date time or datetime converted to a datetime in the given timezone . If when is a datetime and has no timezone it is assumed to be local time . Date and time objects are also assumed to be UTC . The tz value defaults to UTC . Raise TypeError if when cannot be converted to a datetime .


def ts(when, tz=None):
    """
    Return a Unix timestamp in seconds for the provided datetime. The `totz` function is called
    on the datetime to convert it to the provided timezone. It will be converted to UTC if no
    timezone is provided.
    """
    if not when:
        return None
    when = totz(when, tz)
    return calendar.timegm(when.timetuple())

def ts ( when , tz = None ) : if not when : return None when = totz ( when , tz ) return calendar . timegm ( when . timetuple ( ) )

Return a Unix timestamp in seconds for the provided datetime . The totz function is called on the datetime to convert it to the provided timezone . It will be converted to UTC if no timezone is provided .


def tsms(when, tz=None):
    """
    Return a Unix timestamp in milliseconds for the provided datetime. The `totz` function is
    called on the datetime to convert it to the provided timezone. It will be converted to UTC if
    no timezone is provided.
    """
    if not when:
        return None
    when = totz(when, tz)
    return calendar.timegm(when.timetuple()) * 1000 + int(round(when.microsecond / 1000.0))

def tsms ( when , tz = None ) : if not when : return None when = totz ( when , tz ) return calendar . timegm ( when . timetuple ( ) ) * 1000 + int ( round ( when . microsecond / 1000.0 ) )

Return a Unix timestamp in milliseconds for the provided datetime . The totz function is called on the datetime to convert it to the provided timezone . It will be converted to UTC if no timezone is provided .


def fromts(ts, tzin=None, tzout=None):
    """
    Return the datetime representation of the provided Unix timestamp. By defaults the timestamp is
    interpreted as UTC. If tzin is set it will be interpreted as this timestamp instead. By default
    the output datetime will have UTC time. If tzout is set it will be converted in this timezone
    instead.
    """
    if ts is None:
        return None
    when = datetime.utcfromtimestamp(ts).replace(tzinfo=tzin or utc)
    return totz(when, tzout)

def fromts ( ts , tzin = None , tzout = None ) : if ts is None : return None when = datetime . utcfromtimestamp ( ts ) . replace ( tzinfo = tzin or utc ) return totz ( when , tzout )

Return the datetime representation of the provided Unix timestamp . By defaults the timestamp is interpreted as UTC . If tzin is set it will be interpreted as this timestamp instead . By default the output datetime will have UTC time . If tzout is set it will be converted in this timezone instead .


def fromtsms(ts, tzin=None, tzout=None):
    """
    Return the Unix timestamp in milliseconds as a datetime object. If tz is set it will be
    converted to the requested timezone otherwise it defaults to UTC.
    """
    if ts is None:
        return None
    when = datetime.utcfromtimestamp(ts / 1000).replace(microsecond=ts % 1000 * 1000)
    when = when.replace(tzinfo=tzin or utc)
    return totz(when, tzout)

def fromtsms ( ts , tzin = None , tzout = None ) : if ts is None : return None when = datetime . utcfromtimestamp ( ts / 1000 ) . replace ( microsecond = ts % 1000 * 1000 ) when = when . replace ( tzinfo = tzin or utc ) return totz ( when , tzout )

Return the Unix timestamp in milliseconds as a datetime object . If tz is set it will be converted to the requested timezone otherwise it defaults to UTC .


def truncate(when, unit, week_start=mon):
    """Return the datetime truncated to the precision of the provided unit."""
    if is_datetime(when):
        if unit == millisecond:
            return when.replace(microsecond=int(round(when.microsecond / 1000.0)) * 1000)
        elif unit == second:
            return when.replace(microsecond=0)
        elif unit == minute:
            return when.replace(second=0, microsecond=0)
        elif unit == hour:
            return when.replace(minute=0, second=0, microsecond=0)
        elif unit == day:
            return when.replace(hour=0, minute=0, second=0, microsecond=0)
        elif unit == week:
            weekday = prevweekday(when, week_start)
            return when.replace(year=weekday.year, month=weekday.month, day=weekday.day,
                                hour=0, minute=0, second=0, microsecond=0)
        elif unit == month:
            return when.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        elif unit == year:
            return when.replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
    elif is_date(when):
        if unit == week:
            return prevweekday(when, week_start)
        elif unit == month:
            return when.replace(day=1)
        elif unit == year:
            return when.replace(month=1, day=1)
    elif is_time(when):
        if unit == millisecond:
            return when.replace(microsecond=int(when.microsecond / 1000.0) * 1000)
        elif unit == second:
            return when.replace(microsecond=0)
        elif unit == minute:
            return when.replace(second=0, microsecond=0)
    return when

def truncate ( when , unit , week_start = mon ) : if is_datetime ( when ) : if unit == millisecond : return when . replace ( microsecond = int ( round ( when . microsecond / 1000.0 ) ) * 1000 ) elif unit == second : return when . replace ( microsecond = 0 ) elif unit == minute : return when . replace ( second = 0 , microsecond = 0 ) elif unit == hour : return when . replace ( minute = 0 , second = 0 , microsecond = 0 ) elif unit == day : return when . replace ( hour = 0 , minute = 0 , second = 0 , microsecond = 0 ) elif unit == week : weekday = prevweekday ( when , week_start ) return when . replace ( year = weekday . year , month = weekday . month , day = weekday . day , hour = 0 , minute = 0 , second = 0 , microsecond = 0 ) elif unit == month : return when . replace ( day = 1 , hour = 0 , minute = 0 , second = 0 , microsecond = 0 ) elif unit == year : return when . replace ( month = 1 , day = 1 , hour = 0 , minute = 0 , second = 0 , microsecond = 0 ) elif is_date ( when ) : if unit == week : return prevweekday ( when , week_start ) elif unit == month : return when . replace ( day = 1 ) elif unit == year : return when . replace ( month = 1 , day = 1 ) elif is_time ( when ) : if unit == millisecond : return when . replace ( microsecond = int ( when . microsecond / 1000.0 ) * 1000 ) elif unit == second : return when . replace ( microsecond = 0 ) elif unit == minute : return when . replace ( second = 0 , microsecond = 0 ) return when

Return the datetime truncated to the precision of the provided unit .


def weekday(when, weekday, start=mon):
    """Return the date for the day of this week."""
    if isinstance(when, datetime):
        when = when.date()

    today = when.weekday()
    delta = weekday - today
    if weekday < start and today >= start:
        delta += 7
    elif weekday >= start and today < start:
        delta -= 7
    return when + timedelta(days=delta)

def weekday ( when , weekday , start = mon ) : if isinstance ( when , datetime ) : when = when . date ( ) today = when . weekday ( ) delta = weekday - today if weekday < start and today >= start : delta += 7 elif weekday >= start and today < start : delta -= 7 return when + timedelta ( days = delta )

Return the date for the day of this week .


def _GetNativeEolStyle(platform=sys.platform):
    '''
    Internal function that determines EOL_STYLE_NATIVE constant with the proper value for the
    current platform.
    '''
    _NATIVE_EOL_STYLE_MAP = {
        'win32' : EOL_STYLE_WINDOWS,
        'linux2' : EOL_STYLE_UNIX,
        'linux' : EOL_STYLE_UNIX,
        'darwin' : EOL_STYLE_MAC,
    }
    result = _NATIVE_EOL_STYLE_MAP.get(platform)

    if result is None:
        from ._exceptions import UnknownPlatformError
        raise UnknownPlatformError(platform)

    return result

def _GetNativeEolStyle ( platform = sys . platform ) : _NATIVE_EOL_STYLE_MAP = { 'win32' : EOL_STYLE_WINDOWS , 'linux2' : EOL_STYLE_UNIX , 'linux' : EOL_STYLE_UNIX , 'darwin' : EOL_STYLE_MAC , } result = _NATIVE_EOL_STYLE_MAP . get ( platform ) if result is None : from . _exceptions import UnknownPlatformError raise UnknownPlatformError ( platform ) return result

Internal function that determines EOL_STYLE_NATIVE constant with the proper value for the current platform .


def NormalizePath(path):
    '''
    Normalizes a path maintaining the final slashes.

    Some environment variables need the final slash in order to work.

    Ex. The SOURCES_DIR set by subversion must end with a slash because of the way it is used
    in the Visual Studio projects.

    :param unicode path:
        The path to normalize.

    :rtype: unicode
    :returns:
        Normalized path
    '''
    if path.endswith('/') or path.endswith('\\'):
        slash = os.path.sep
    else:
        slash = ''
    return os.path.normpath(path) + slash

def NormalizePath ( path ) : if path . endswith ( '/' ) or path . endswith ( '\\' ) : slash = os . path . sep else : slash = '' return os . path . normpath ( path ) + slash

Normalizes a path maintaining the final slashes .


def CanonicalPath(path):
    '''
    Returns a version of a path that is unique.

    Given two paths path1 and path2:
        CanonicalPath(path1) == CanonicalPath(path2) if and only if they represent the same file on
        the host OS. Takes account of case, slashes and relative paths.

    :param unicode path:
        The original path.

    :rtype: unicode
    :returns:
        The unique path.
    '''
    path = os.path.normpath(path)
    path = os.path.abspath(path)
    path = os.path.normcase(path)

    return path

def CanonicalPath ( path ) : path = os . path . normpath ( path ) path = os . path . abspath ( path ) path = os . path . normcase ( path ) return path

Returns a version of a path that is unique .


def StandardizePath(path, strip=False):
    '''
    Replaces all slashes and backslashes with the target separator

    StandardPath:
        We are defining that the standard-path is the one with only back-slashes in it, either
        on Windows or any other platform.

    :param bool strip:
        If True, removes additional slashes from the end of the path.
    '''
    path = path.replace(SEPARATOR_WINDOWS, SEPARATOR_UNIX)
    if strip:
        path = path.rstrip(SEPARATOR_UNIX)
    return path

def StandardizePath ( path , strip = False ) : path = path . replace ( SEPARATOR_WINDOWS , SEPARATOR_UNIX ) if strip : path = path . rstrip ( SEPARATOR_UNIX ) return path


def CopyFile(source_filename, target_filename, override=True, md5_check=False, copy_symlink=True):
    '''
    Copy a file from source to target.

    :param  source_filename:
        @see _DoCopyFile

    :param  target_filename:
        @see _DoCopyFile

    :param bool md5_check:
        If True, checks md5 files (of both source and target files), if they match, skip this copy
        and return MD5_SKIP

        Md5 files are assumed to be {source, target} + '.md5'

        If any file is missing (source, target or md5), the copy will always be made.

    :param  copy_symlink:
        @see _DoCopyFile

    :raises FileAlreadyExistsError:
        If target_filename already exists, and override is False

    :raises NotImplementedProtocol:
        If file protocol is not accepted

        Protocols allowed are:
            source_filename: local, ftp, http
            target_filename: local, ftp

    :rtype: None | MD5_SKIP
    :returns:
        MD5_SKIP if the file was not copied because there was a matching .md5 file

    .. seealso:: FTP LIMITATIONS at this module's doc for performance issues information
    '''
    from ._exceptions import FileNotFoundError

    # Check override
    if not override and Exists(target_filename):
        from ._exceptions import FileAlreadyExistsError
        raise FileAlreadyExistsError(target_filename)

    # Don't do md5 check for md5 files themselves.
    md5_check = md5_check and not target_filename.endswith('.md5')

    # If we enabled md5 checks, ignore copy of files that haven't changed their md5 contents.
    if md5_check:
        source_md5_filename = source_filename + '.md5'
        target_md5_filename = target_filename + '.md5'
        try:
            source_md5_contents = GetFileContents(source_md5_filename)
        except FileNotFoundError:
            source_md5_contents = None

        try:
            target_md5_contents = GetFileContents(target_md5_filename)
        except FileNotFoundError:
            target_md5_contents = None

        if source_md5_contents is not None and \
           source_md5_contents == target_md5_contents and \
           Exists(target_filename):
            return MD5_SKIP

    # Copy source file
    _DoCopyFile(source_filename, target_filename, copy_symlink=copy_symlink)

    # If we have a source_md5, but no target_md5, create the target_md5 file
    if md5_check and source_md5_contents is not None and source_md5_contents != target_md5_contents:
        CreateFile(target_md5_filename, source_md5_contents)

def CopyFile ( source_filename , target_filename , override = True , md5_check = False , copy_symlink = True ) : from . _exceptions import FileNotFoundError if not override and Exists ( target_filename ) : from . _exceptions import FileAlreadyExistsError raise FileAlreadyExistsError ( target_filename ) md5_check = md5_check and not target_filename . endswith ( '.md5' ) if md5_check : source_md5_filename = source_filename + '.md5' target_md5_filename = target_filename + '.md5' try : source_md5_contents = GetFileContents ( source_md5_filename ) except FileNotFoundError : source_md5_contents = None try : target_md5_contents = GetFileContents ( target_md5_filename ) except FileNotFoundError : target_md5_contents = None if source_md5_contents is not None and source_md5_contents == target_md5_contents and Exists ( target_filename ) : return MD5_SKIP _DoCopyFile ( source_filename , target_filename , copy_symlink = copy_symlink ) if md5_check and source_md5_contents is not None and source_md5_contents != target_md5_contents : CreateFile ( target_md5_filename , source_md5_contents )


def _CopyFileLocal(source_filename, target_filename, copy_symlink=True):
    '''
    Copy a file locally to a directory.

    :param unicode source_filename:
        The filename to copy from.

    :param unicode target_filename:
        The filename to copy to.

    :param bool copy_symlink:
        If True and source_filename is a symlink, target_filename will also be created as
        a symlink.

        If False, the file being linked will be copied instead.
    '''
    import shutil
    try:
        # >>> Create the target_filename directory if necessary
        dir_name = os.path.dirname(target_filename)
        if dir_name and not os.path.isdir(dir_name):
            os.makedirs(dir_name)

        if copy_symlink and IsLink(source_filename):
            # >>> Delete the target_filename if it already exists
            if os.path.isfile(target_filename) or IsLink(target_filename):
                DeleteFile(target_filename)

            # >>> Obtain the relative path from link to source_filename (linkto)
            source_filename = ReadLink(source_filename)
            CreateLink(source_filename, target_filename)
        else:
            # shutil can't copy links in Windows, so we must find the real file manually
            if sys.platform == 'win32':
                while IsLink(source_filename):
                    link = ReadLink(source_filename)
                    if os.path.isabs(link):
                        source_filename = link
                    else:
                        source_filename = os.path.join(os.path.dirname(source_filename), link)

            shutil.copyfile(source_filename, target_filename)
            shutil.copymode(source_filename, target_filename)
    except Exception as e:
        reraise(e, 'While executiong _filesystem._CopyFileLocal(%s, %s)' % (source_filename, target_filename))


def CopyFiles(source_dir, target_dir, create_target_dir=False, md5_check=False):
    '''
    Copy files from the given source to the target.

    :param unicode source_dir:
        A filename, URL or a file mask.
        Ex.
            x:\coilib50
            x:\coilib50\*
            http://server/directory/file
            ftp://server/directory/file

    :param unicode target_dir:
        A directory or an URL
        Ex.
            d:\Temp
            ftp://server/directory

    :param bool create_target_dir:
        If True, creates the target path if it doesn't exists.

    :param bool md5_check:
        .. seealso:: CopyFile

    :raises DirectoryNotFoundError:
        If target_dir does not exist, and create_target_dir is False

    .. seealso:: CopyFile for documentation on accepted protocols

    .. seealso:: FTP LIMITATIONS at this module's doc for performance issues information
    '''
    import fnmatch

    # Check if we were given a directory or a directory with mask
    if IsDir(source_dir):
        # Yes, it's a directory, copy everything from it
        source_mask = '*'
    else:
        # Split directory and mask
        source_dir, source_mask = os.path.split(source_dir)

    # Create directory if necessary
    if not IsDir(target_dir):
        if create_target_dir:
            CreateDirectory(target_dir)
        else:
            from ._exceptions import DirectoryNotFoundError
            raise DirectoryNotFoundError(target_dir)

    # List and match files
    filenames = ListFiles(source_dir)

    # Check if we have a source directory
    if filenames is None:
        return

    # Copy files
    for i_filename in filenames:
        if md5_check and i_filename.endswith('.md5'):
            continue  # md5 files will be copied by CopyFile when copying their associated files

        if fnmatch.fnmatch(i_filename, source_mask):
            source_path = source_dir + '/' + i_filename
            target_path = target_dir + '/' + i_filename

            if IsDir(source_path):
                # If we found a directory, copy it recursively
                CopyFiles(source_path, target_path, create_target_dir=True, md5_check=md5_check)
            else:
                CopyFile(source_path, target_path, md5_check=md5_check)

def CopyFiles ( source_dir , target_dir , create_target_dir = False , md5_check = False ) : import fnmatch if IsDir ( source_dir ) : source_mask = '*' else : source_dir , source_mask = os . path . split ( source_dir ) if not IsDir ( target_dir ) : if create_target_dir : CreateDirectory ( target_dir ) else : from . _exceptions import DirectoryNotFoundError raise DirectoryNotFoundError ( target_dir ) filenames = ListFiles ( source_dir ) if filenames is None : return for i_filename in filenames : if md5_check and i_filename . endswith ( '.md5' ) : continue if fnmatch . fnmatch ( i_filename , source_mask ) : source_path = source_dir + '/' + i_filename target_path = target_dir + '/' + i_filename if IsDir ( source_path ) : CopyFiles ( source_path , target_path , create_target_dir = True , md5_check = md5_check ) else : CopyFile ( source_path , target_path , md5_check = md5_check )

Copy files from the given source to the target .


def CopyFilesX(file_mapping):
    '''
    Copies files into directories, according to a file mapping

    :param list(tuple(unicode,unicode)) file_mapping:
        A list of mappings between the directory in the target and the source.
        For syntax, @see: ExtendedPathMask

    :rtype: list(tuple(unicode,unicode))
    :returns:
        List of files copied. (source_filename, target_filename)

    .. seealso:: FTP LIMITATIONS at this module's doc for performance issues information
    '''
    # List files that match the mapping
    files = []
    for i_target_path, i_source_path_mask in file_mapping:
        tree_recurse, flat_recurse, dirname, in_filters, out_filters = ExtendedPathMask.Split(i_source_path_mask)

        _AssertIsLocal(dirname)

        filenames = FindFiles(dirname, in_filters, out_filters, tree_recurse)
        for i_source_filename in filenames:
            if os.path.isdir(i_source_filename):
                continue  # Do not copy dirs

            i_target_filename = i_source_filename[len(dirname) + 1:]
            if flat_recurse:
                i_target_filename = os.path.basename(i_target_filename)
            i_target_filename = os.path.join(i_target_path, i_target_filename)

            files.append((
                StandardizePath(i_source_filename),
                StandardizePath(i_target_filename)
            ))

    # Copy files
    for i_source_filename, i_target_filename in files:
        # Create target dir if necessary
        target_dir = os.path.dirname(i_target_filename)
        CreateDirectory(target_dir)

        CopyFile(i_source_filename, i_target_filename)

    return files

def CopyFilesX ( file_mapping ) : files = [ ] for i_target_path , i_source_path_mask in file_mapping : tree_recurse , flat_recurse , dirname , in_filters , out_filters = ExtendedPathMask . Split ( i_source_path_mask ) _AssertIsLocal ( dirname ) filenames = FindFiles ( dirname , in_filters , out_filters , tree_recurse ) for i_source_filename in filenames : if os . path . isdir ( i_source_filename ) : continue i_target_filename = i_source_filename [ len ( dirname ) + 1 : ] if flat_recurse : i_target_filename = os . path . basename ( i_target_filename ) i_target_filename = os . path . join ( i_target_path , i_target_filename ) files . append ( ( StandardizePath ( i_source_filename ) , StandardizePath ( i_target_filename ) ) ) for i_source_filename , i_target_filename in files : target_dir = os . path . dirname ( i_target_filename ) CreateDirectory ( target_dir ) CopyFile ( i_source_filename , i_target_filename ) return files

Copies files into directories according to a file mapping


def CopyDirectory(source_dir, target_dir, override=False):
    '''
    Recursively copy a directory tree.

    :param unicode source_dir:
        Where files will come from

    :param unicode target_dir:
        Where files will go to

    :param bool override:
        If True and target_dir already exists, it will be deleted before copying.

    :raises NotImplementedForRemotePathError:
        If trying to copy to/from remote directories
    '''
    _AssertIsLocal(source_dir)
    _AssertIsLocal(target_dir)

    if override and IsDir(target_dir):
        DeleteDirectory(target_dir, skip_on_error=False)

    import shutil
    shutil.copytree(source_dir, target_dir)

def CopyDirectory ( source_dir , target_dir , override = False ) : _AssertIsLocal ( source_dir ) _AssertIsLocal ( target_dir ) if override and IsDir ( target_dir ) : DeleteDirectory ( target_dir , skip_on_error = False ) import shutil shutil . copytree ( source_dir , target_dir )


def DeleteFile(target_filename):
    '''
    Deletes the given local filename.

    .. note:: If file doesn't exist this method has no effect.

    :param unicode target_filename:
        A local filename

    :raises NotImplementedForRemotePathError:
        If trying to delete a non-local path

    :raises FileOnlyActionError:
        Raised when filename refers to a directory.
    '''
    _AssertIsLocal(target_filename)

    try:
        if IsLink(target_filename):
            DeleteLink(target_filename)
        elif IsFile(target_filename):
            os.remove(target_filename)
        elif IsDir(target_filename):
            from ._exceptions import FileOnlyActionError
            raise FileOnlyActionError(target_filename)
    except Exception as e:
        reraise(e, 'While executing filesystem.DeleteFile(%s)' % (target_filename))


def AppendToFile(filename, contents, eol_style=EOL_STYLE_NATIVE, encoding=None, binary=False):
    '''
    Appends content to a local file.

    :param unicode filename:

    :param unicode contents:

    :type eol_style: EOL_STYLE_XXX constant
    :param eol_style:
        Replaces the EOL by the appropriate EOL depending on the eol_style value.
        Considers that all content is using only "\n" as EOL.

    :param unicode encoding:
        Target file's content encoding.
        Defaults to sys.getfilesystemencoding()

    :param bool binary:
        If True, content is appended in binary mode. In this case, `contents` must be `bytes` and not
        `unicode`

    :raises NotImplementedForRemotePathError:
        If trying to modify a non-local path

    :raises ValueError:
        If trying to mix unicode `contents` without `encoding`, or `encoding` without
        unicode `contents`
    '''
    _AssertIsLocal(filename)

    assert isinstance(contents, six.text_type) ^ binary, 'Must always receive unicode contents, unless binary=True'

    if not binary:
        # Replaces eol on each line by the given eol_style.
        contents = _HandleContentsEol(contents, eol_style)

        # Handle encoding here, and always write in binary mode. We can't use io.open because it
        # tries to do its own line ending handling.
        contents = contents.encode(encoding or sys.getfilesystemencoding())

    oss = open(filename, 'ab')
    try:
        oss.write(contents)
    finally:
        oss.close()


def MoveFile(source_filename, target_filename):
    '''
    Moves a file.

    :param unicode source_filename:

    :param unicode target_filename:

    :raises NotImplementedForRemotePathError:
        If trying to operate with non-local files.
    '''
    _AssertIsLocal(source_filename)
    _AssertIsLocal(target_filename)

    import shutil
    shutil.move(source_filename, target_filename)

def MoveFile ( source_filename , target_filename ) : _AssertIsLocal ( source_filename ) _AssertIsLocal ( target_filename ) import shutil shutil . move ( source_filename , target_filename )


def MoveDirectory(source_dir, target_dir):
    '''
    Moves a directory.

    :param unicode source_dir:

    :param unicode target_dir:

    :raises NotImplementedError:
        If trying to move anything other than:
            Local dir -> local dir
            FTP dir -> FTP dir (same host)
    '''
    if not IsDir(source_dir):
        from ._exceptions import DirectoryNotFoundError
        raise DirectoryNotFoundError(source_dir)

    if Exists(target_dir):
        from ._exceptions import DirectoryAlreadyExistsError
        raise DirectoryAlreadyExistsError(target_dir)

    from six.moves.urllib.parse import urlparse
    source_url = urlparse(source_dir)
    target_url = urlparse(target_dir)

    # Local to local
    if _UrlIsLocal(source_url) and _UrlIsLocal(target_url):
        import shutil
        shutil.move(source_dir, target_dir)

    # FTP to FTP
    elif source_url.scheme == 'ftp' and target_url.scheme == 'ftp':
        from ._exceptions import NotImplementedProtocol
        raise NotImplementedProtocol(target_url.scheme)
    else:
        raise NotImplementedError('Can only move directories local->local or ftp->ftp')


def GetFileContents(filename, binary=False, encoding=None, newline=None):
    '''
    Reads a file and returns its contents. Works for both local and remote files.

    :param unicode filename:

    :param bool binary:
        If True returns the file as is, ignore any EOL conversion.

    :param unicode encoding:
        File's encoding. If not None, contents obtained from file will be decoded using this
        `encoding`.

    :param None|''|'\n'|'\r'|'\r\n' newline:
        Controls universal newlines.
        See 'io.open' newline parameter documentation for more details.

    :returns str|unicode:
        The file's contents.
        Returns unicode string when `encoding` is not None.

    .. seealso:: FTP LIMITATIONS at this module's doc for performance issues information
    '''
    source_file = OpenFile(filename, binary=binary, encoding=encoding, newline=newline)
    try:
        contents = source_file.read()
    finally:
        source_file.close()

    return contents

def GetFileContents ( filename , binary = False , encoding = None , newline = None ) : source_file = OpenFile ( filename , binary = binary , encoding = encoding , newline = newline ) try : contents = source_file . read ( ) finally : source_file . close ( ) return contents

Reads a file and returns its contents . Works for both local and remote files .


def GetFileLines(filename, newline=None, encoding=None):
    '''
    Reads a file and returns its contents as a list of lines. Works for both local and remote files.

    :param unicode filename:

    :param None|''|'\n'|'\r'|'\r\n' newline:
        Controls universal newlines.
        See 'io.open' newline parameter documentation for more details.

    :param unicode encoding:
        File's encoding. If not None, contents obtained from file will be decoded using this
        `encoding`.

    :returns list(unicode):
        The file's lines

    .. seealso:: FTP LIMITATIONS at this module's doc for performance issues information
    '''
    return GetFileContents(
        filename,
        binary=False,
        encoding=encoding,
        newline=newline,
    ).split('\n')

def GetFileLines ( filename , newline = None , encoding = None ) : return GetFileContents ( filename , binary = False , encoding = encoding , newline = newline , ) . split ( '\n' )

Reads a file and returns its contents as a list of lines . Works for both local and remote files .


def ListFiles(directory):
    '''
    Lists the files in the given directory

    :type directory: unicode | unicode
    :param directory:
        A directory or URL

    :rtype: list(unicode) | list(unicode)
    :returns:
        List of filenames/directories found in the given directory.
        Returns None if the given directory does not exists.

        If `directory` is a unicode string, all files returned will also be unicode

    :raises NotImplementedProtocol:
        If file protocol is not local or FTP

    .. seealso:: FTP LIMITATIONS at this module's doc for performance issues information
    '''
    from six.moves.urllib.parse import urlparse
    directory_url = urlparse(directory)

    # Handle local
    if _UrlIsLocal(directory_url):
        if not os.path.isdir(directory):
            return None
        return os.listdir(directory)

    # Handle FTP
    elif directory_url.scheme == 'ftp':
        from ._exceptions import NotImplementedProtocol
        raise NotImplementedProtocol(directory_url.scheme)
    else:
        from ._exceptions import NotImplementedProtocol
        raise NotImplementedProtocol(directory_url.scheme)

def ListFiles ( directory ) : from six . moves . urllib . parse import urlparse directory_url = urlparse ( directory ) if _UrlIsLocal ( directory_url ) : if not os . path . isdir ( directory ) : return None return os . listdir ( directory ) elif directory_url . scheme == 'ftp' : from . _exceptions import NotImplementedProtocol raise NotImplementedProtocol ( directory_url . scheme ) else : from . _exceptions import NotImplementedProtocol raise NotImplementedProtocol ( directory_url . scheme )


def CreateFile(filename, contents, eol_style=EOL_STYLE_NATIVE, create_dir=True, encoding=None, binary=False):
    '''
    Create a file with the given contents.

    :param unicode filename:
        Filename and path to be created.

    :param unicode contents:
        The file contents as a string.

    :type eol_style: EOL_STYLE_XXX constant
    :param eol_style:
        Replaces the EOL by the appropriate EOL depending on the eol_style value.
        Considers that all content is using only "\n" as EOL.

    :param bool create_dir:
        If True, also creates directories needed in filename's path

    :param unicode encoding:
        Target file's content encoding. Defaults to sys.getfilesystemencoding()
        Ignored if `binary` = True

    :param bool binary:
        If True, file is created in binary mode. In this case, `contents` must be `bytes` and not
        `unicode`

    :return unicode:
        Returns the name of the file created.

    :raises NotImplementedProtocol:
        If file protocol is not local or FTP

    :raises ValueError:
        If trying to mix unicode `contents` without `encoding`, or `encoding` without
        unicode `contents`

    .. seealso:: FTP LIMITATIONS at this module's doc for performance issues information
    '''
    # Lots of checks when writing binary files
    if binary:
        if isinstance(contents, six.text_type):
            raise TypeError('contents must be str (bytes) when binary=True')
    else:
        if not isinstance(contents, six.text_type):
            raise TypeError('contents must be unicode when binary=False')

        # Replaces eol on each line by the given eol_style.
        contents = _HandleContentsEol(contents, eol_style)

        # Encode string and pretend we are using binary to prevent 'open' from automatically
        # changing Eols
        encoding = encoding or sys.getfilesystemencoding()
        contents = contents.encode(encoding)
        binary = True

    # If asked, creates directory containing file
    if create_dir:
        dirname = os.path.dirname(filename)
        if dirname:
            CreateDirectory(dirname)

    from six.moves.urllib.parse import urlparse
    filename_url = urlparse(filename)

    # Handle local
    if _UrlIsLocal(filename_url):
        # Always writing as binary (see handling above)
        with open(filename, 'wb') as oss:
            oss.write(contents)

    # Handle FTP
    elif filename_url.scheme == 'ftp':
        # Always writing as binary (see handling above)
        from ._exceptions import NotImplementedProtocol
        raise NotImplementedProtocol(directory_url.scheme)
    else:
        from ._exceptions import NotImplementedProtocol
        raise NotImplementedProtocol(filename_url.scheme)

    return filename


def ReplaceInFile(filename, old, new, encoding=None):
    '''
    Replaces all occurrences of "old" by "new" in the given file.

    :param unicode filename:
        The name of the file.

    :param unicode old:
        The string to search for.

    :param unicode new:
        Replacement string.

    :return unicode:
        The new contents of the file.
    '''
    contents = GetFileContents(filename, encoding=encoding)
    contents = contents.replace(old, new)
    CreateFile(filename, contents, encoding=encoding)
    return contents

def ReplaceInFile ( filename , old , new , encoding = None ) : contents = GetFileContents ( filename , encoding = encoding ) contents = contents . replace ( old , new ) CreateFile ( filename , contents , encoding = encoding ) return contents

Replaces all occurrences of old by new in the given file .


def CreateDirectory(directory):
    '''
    Create directory including any missing intermediate directory.

    :param unicode directory:

    :return unicode|urlparse.ParseResult:
        Returns the created directory or url (see urlparse).

    :raises NotImplementedProtocol:
        If protocol is not local or FTP.

    .. seealso:: FTP LIMITATIONS at this module's doc for performance issues information
    '''
    from six.moves.urllib.parse import urlparse
    directory_url = urlparse(directory)

    # Handle local
    if _UrlIsLocal(directory_url):
        if not os.path.exists(directory):
            os.makedirs(directory)
        return directory

    # Handle FTP
    elif directory_url.scheme == 'ftp':
        from ._exceptions import NotImplementedProtocol
        raise NotImplementedProtocol(directory_url.scheme)
    else:
        from ._exceptions import NotImplementedProtocol
        raise NotImplementedProtocol(directory_url.scheme)

def CreateDirectory ( directory ) : from six . moves . urllib . parse import urlparse directory_url = urlparse ( directory ) if _UrlIsLocal ( directory_url ) : if not os . path . exists ( directory ) : os . makedirs ( directory ) return directory elif directory_url . scheme == 'ftp' : from . _exceptions import NotImplementedProtocol raise NotImplementedProtocol ( directory_url . scheme ) else : from . _exceptions import NotImplementedProtocol raise NotImplementedProtocol ( directory_url . scheme )

Create directory including any missing intermediate directory .


def DeleteDirectory(directory, skip_on_error=False):
    '''
    Deletes a directory.

    :param unicode directory:

    :param bool skip_on_error:
        If True, ignore any errors when trying to delete directory (for example, directory not
        found)

    :raises NotImplementedForRemotePathError:
        If trying to delete a remote directory.
    '''
    _AssertIsLocal(directory)

    import shutil
    def OnError(fn, path, excinfo):
        '''
        Remove the read-only flag and try to remove again.
        On Windows, rmtree fails when trying to remove a read-only file. This fix it!
        Another case: Read-only directories return True in os.access test. It seems that read-only
        directories has it own flag (looking at the property windows on Explorer).
        '''
        if IsLink(path):
            return

        if fn is os.remove and os.access(path, os.W_OK):
            raise

        # Make the file WRITEABLE and executes the original delete function (osfunc)
        import stat
        os.chmod(path, stat.S_IWRITE)
        fn(path)

    try:
        if not os.path.isdir(directory):
            if skip_on_error:
                return
            from ._exceptions import DirectoryNotFoundError
            raise DirectoryNotFoundError(directory)
        shutil.rmtree(directory, onerror=OnError)
    except:
        if not skip_on_error:
            raise

def DeleteDirectory ( directory , skip_on_error = False ) : _AssertIsLocal ( directory ) import shutil def OnError ( fn , path , excinfo ) : if IsLink ( path ) : return if fn is os . remove and os . access ( path , os . W_OK ) : raise import stat os . chmod ( path , stat . S_IWRITE ) fn ( path ) try : if not os . path . isdir ( directory ) : if skip_on_error : return from . _exceptions import DirectoryNotFoundError raise DirectoryNotFoundError ( directory ) shutil . rmtree ( directory , onerror = OnError ) except : if not skip_on_error : raise


def ListMappedNetworkDrives():
    '''
    On Windows, returns a list of mapped network drives

    :return: tuple(string, string, bool)
        For each mapped netword drive, return 3 values tuple:
            - the local drive
            - the remote path-
            - True if the mapping is enabled (warning: not reliable)
    '''
    if sys.platform != 'win32':
        raise NotImplementedError
    drives_list = []
    netuse = _CallWindowsNetCommand(['use'])
    for line in netuse.split(EOL_STYLE_WINDOWS):
        match = re.match("(\w*)\s+(\w:)\s+(.+)", line.rstrip())
        if match:
            drives_list.append((match.group(2), match.group(3), match.group(1) == 'OK'))
    return drives_list

def ListMappedNetworkDrives ( ) : if sys . platform != 'win32' : raise NotImplementedError drives_list = [ ] netuse = _CallWindowsNetCommand ( [ 'use' ] ) for line in netuse . split ( EOL_STYLE_WINDOWS ) : match = re . match ( "(\w*)\s+(\w:)\s+(.+)" , line . rstrip ( ) ) if match : drives_list . append ( ( match . group ( 2 ) , match . group ( 3 ) , match . group ( 1 ) == 'OK' ) ) return drives_list

On Windows returns a list of mapped network drives


def CreateLink(target_path, link_path, override=True):
    '''
    Create a symbolic link at `link_path` pointing to `target_path`.

    :param unicode target_path:
        Link target

    :param unicode link_path:
        Fullpath to link name

    :param bool override:
        If True and `link_path` already exists as a link, that link is overridden.
    '''
    _AssertIsLocal(target_path)
    _AssertIsLocal(link_path)

    if override and IsLink(link_path):
        DeleteLink(link_path)

    # Create directories leading up to link
    dirname = os.path.dirname(link_path)
    if dirname:
        CreateDirectory(dirname)

    if sys.platform != 'win32':
        return os.symlink(target_path, link_path)  # @UndefinedVariable
    else:
        #import ntfsutils.junction
        #return ntfsutils.junction.create(target_path, link_path)

        import jaraco.windows.filesystem
        return jaraco.windows.filesystem.symlink(target_path, link_path)

        from ._easyfs_win32 import CreateSymbolicLink
        try:
            dw_flags = 0
            if target_path and os.path.isdir(target_path):
                dw_flags = 1
            return CreateSymbolicLink(target_path, link_path, dw_flags)
        except Exception as e:
            reraise(e, 'Creating link "%(link_path)s" pointing to "%(target_path)s"' % locals())

Create a symbolic link at link_path pointing to target_path .


def ReadLink(path):
    '''
    Read the target of the symbolic link at `path`.

    :param unicode path:
        Path to a symbolic link

    :returns unicode:
        Target of a symbolic link
    '''
    _AssertIsLocal(path)

    if sys.platform != 'win32':
        return os.readlink(path)  # @UndefinedVariable

    if not IsLink(path):
        from ._exceptions import FileNotFoundError
        raise FileNotFoundError(path)

    import jaraco.windows.filesystem
    result = jaraco.windows.filesystem.readlink(path)
    if '\\??\\' in result:
        result = result.split('\\??\\')[1]
    return result

def ReadLink ( path ) : _AssertIsLocal ( path ) if sys . platform != 'win32' : return os . readlink ( path ) if not IsLink ( path ) : from . _exceptions import FileNotFoundError raise FileNotFoundError ( path ) import jaraco . windows . filesystem result = jaraco . windows . filesystem . readlink ( path ) if '\\??\\' in result : result = result . split ( '\\??\\' ) [ 1 ] return result

Read the target of the symbolic link at path .


def _AssertIsLocal(path):
    '''
    Checks if a given path is local, raise an exception if not.

    This is used in filesystem functions that do not support remote operations yet.

    :param unicode path:

    :raises NotImplementedForRemotePathError:
        If the given path is not local
    '''
    from six.moves.urllib.parse import urlparse
    if not _UrlIsLocal(urlparse(path)):
        from ._exceptions import NotImplementedForRemotePathError
        raise NotImplementedForRemotePathError

def _AssertIsLocal ( path ) : from six . moves . urllib . parse import urlparse if not _UrlIsLocal ( urlparse ( path ) ) : from . _exceptions import NotImplementedForRemotePathError raise NotImplementedForRemotePathError

Checks if a given path is local raise an exception if not .


def _HandleContentsEol(contents, eol_style):
    '''
    Replaces eol on each line by the given eol_style.

    :param unicode contents:
    :type eol_style: EOL_STYLE_XXX constant
    :param eol_style:
    '''
    if eol_style == EOL_STYLE_NONE:
        return contents

    if eol_style == EOL_STYLE_UNIX:
        return contents.replace('\r\n', eol_style).replace('\r', eol_style)

    if eol_style == EOL_STYLE_MAC:
        return contents.replace('\r\n', eol_style).replace('\n', eol_style)

    if eol_style == EOL_STYLE_WINDOWS:
        return contents.replace('\r\n', '\n').replace('\r', '\n').replace('\n', EOL_STYLE_WINDOWS)

    raise ValueError('Unexpected eol style: %r' % (eol_style,))

def
_HandleContentsEol
(
contents
,
eol_style
)
:
if
eol_style
==
EOL_STYLE_NONE
:
return
contents
if
eol_style
==
EOL_STYLE_UNIX
:
return
contents
.
replace
(
'\r\n'
,
eol_style
)
.
replace
(
'\r'
,
eol_style
)
if
eol_style
==
EOL_STYLE_MAC
:
return
contents
.
replace
(
'\r\n'
,
eol_style
)
.
replace
(
'\n'
,
eol_style
)
if
eol_style
==
EOL_STYLE_WINDOWS
:
return
contents
.
replace
(
'\r\n'
,
'\n'
)
.
replace
(
'\r'
,
'\n'
)
.
replace
(
'\n'
,
EOL_STYLE_WINDOWS
)
raise
ValueError
(
'Unexpected eol style: %r'
%
(
eol_style
,
)
)

Replaces eol on each line by the given eol_style .


def MatchMasks(filename, masks):
    '''
    Verifies if a filename match with given patterns.

    :param str filename: The filename to match.
    :param list(str) masks: The patterns to search in the filename.
    :return bool:
        True if the filename has matched with one pattern, False otherwise.
    '''
    import fnmatch

    if not isinstance(masks, (list, tuple)):
        masks = [masks]

    for i_mask in masks:
        if fnmatch.fnmatch(filename, i_mask):
            return True
    return False

def MatchMasks ( filename , masks ) : import fnmatch if not isinstance ( masks , ( list , tuple ) ) : masks = [ masks ] for i_mask in masks : if fnmatch . fnmatch ( filename , i_mask ) : return True return False

Verifies if a filename match with given patterns .


def FindFiles(dir_, in_filters=None, out_filters=None, recursive=True, include_root_dir=True, standard_paths=False):
    '''
    Searches for files in a given directory that match with the given patterns.

    :param str dir_: the directory root, to search the files.
    :param list(str) in_filters: a list with patterns to match (default = all). E.g.: ['*.py']
    :param list(str) out_filters: a list with patterns to ignore (default = none). E.g.: ['*.py']
    :param bool recursive: if True search in subdirectories, otherwise, just in the root.
    :param bool include_root_dir: if True, includes the directory being searched in the returned paths
    :param bool standard_paths: if True, always uses unix path separators "/"
    :return list(str):
        A list of strings with the files that matched (with the full path in the filesystem).
    '''
    # all files
    if in_filters is None:
        in_filters = ['*']

    if out_filters is None:
        out_filters = []

    result = []

    # maintain just files that don't have a pattern that match with out_filters
    # walk through all directories based on dir
    for dir_root, directories, filenames in os.walk(dir_):

        for i_directory in directories[:]:
            if MatchMasks(i_directory, out_filters):
                directories.remove(i_directory)

        for filename in directories + filenames:
            if MatchMasks(filename, in_filters) and not MatchMasks(filename, out_filters):
                result.append(os.path.join(dir_root, filename))

        if not recursive:
            break

    if not include_root_dir:
        # Remove root dir from all paths
        dir_prefix = len(dir_) + 1
        result = [file[dir_prefix:] for file in result]

    if standard_paths:
        result = map(StandardizePath, result)

    return result

def FindFiles ( dir_ , in_filters = None , out_filters = None , recursive = True , include_root_dir = True , standard_paths = False ) : if in_filters is None : in_filters = [ '*' ] if out_filters is None : out_filters = [ ] result = [ ] for dir_root , directories , filenames in os . walk ( dir_ ) : for i_directory in directories [ : ] : if MatchMasks ( i_directory , out_filters ) : directories . remove ( i_directory ) for filename in directories + filenames : if MatchMasks ( filename , in_filters ) and not MatchMasks ( filename , out_filters ) : result . append ( os . path . join ( dir_root , filename ) ) if not recursive : break if not include_root_dir : dir_prefix = len ( dir_ ) + 1 result = [ file [ dir_prefix : ] for file in result ] if standard_paths : result = map ( StandardizePath , result ) return result

Searches for files in a given directory that match with the given patterns .


def ExpandUser(path):
    '''
    os.path.expanduser wrapper, necessary because it cannot handle unicode strings properly.

    This is not necessary in Python 3.

    :param path:
        .. seealso:: os.path.expanduser
    '''
    if six.PY2:
        encoding = sys.getfilesystemencoding()
        path = path.encode(encoding)
    result = os.path.expanduser(path)
    if six.PY2:
        result = result.decode(encoding)
    return result

def ExpandUser ( path ) : if six . PY2 : encoding = sys . getfilesystemencoding ( ) path = path . encode ( encoding ) result = os . path . expanduser ( path ) if six . PY2 : result = result . decode ( encoding ) return result

os . path . expanduser wrapper necessary because it cannot handle unicode strings properly .


def DumpDirHashToStringIO(directory, stringio, base='', exclude=None, include=None):
    '''
    Helper to iterate over the files in a directory putting those in the passed StringIO in ini
    format.

    :param unicode directory:
        The directory for which the hash should be done.

    :param StringIO stringio:
        The string to which the dump should be put.

    :param unicode base:
        If provided should be added (along with a '/') before the name=hash of file.

    :param unicode exclude:
        Pattern to match files to exclude from the hashing. E.g.: *.gz

    :param unicode include:
        Pattern to match files to include in the hashing. E.g.: *.zip
    '''
    import fnmatch
    import os

    files = [(os.path.join(directory, i), i) for i in os.listdir(directory)]
    files = [i for i in files if os.path.isfile(i[0])]
    for fullname, filename in files:
        if include is not None:
            if not fnmatch.fnmatch(fullname, include):
                continue

        if exclude is not None:
            if fnmatch.fnmatch(fullname, exclude):
                continue

        md5 = Md5Hex(fullname)
        if base:
            stringio.write('%s/%s=%s\n' % (base, filename, md5))
        else:
            stringio.write('%s=%s\n' % (filename, md5))

def DumpDirHashToStringIO ( directory , stringio , base = '' , exclude = None , include = None ) : import fnmatch import os files = [ ( os . path . join ( directory , i ) , i ) for i in os . listdir ( directory ) ] files = [ i for i in files if os . path . isfile ( i [ 0 ] ) ] for fullname , filename in files : if include is not None : if not fnmatch . fnmatch ( fullname , include ) : continue if exclude is not None : if fnmatch . fnmatch ( fullname , exclude ) : continue md5 = Md5Hex ( fullname ) if base : stringio . write ( '%s/%s=%s\n' % ( base , filename , md5 ) ) else : stringio . write ( '%s=%s\n' % ( filename , md5 ) )

Helper to iterate over the files in a directory putting those in the passed StringIO in ini format .


def IterHashes(iterator_size, hash_length=7):
    '''
    Iterator for random hexadecimal hashes

    :param iterator_size:
        Amount of hashes return before this iterator stops.
        Goes on forever if `iterator_size` is negative.

    :param int hash_length:
        Size of each hash returned.

    :return generator(unicode):
    '''
    if not isinstance(iterator_size, int):
        raise TypeError('iterator_size must be integer.')

    count = 0
    while count != iterator_size:
        count += 1
        yield GetRandomHash(hash_length)

def
IterHashes
(
iterator_size
,
hash_length
=
7
)
:
if
not
isinstance
(
iterator_size
,
int
)
:
raise
TypeError
(
'iterator_size must be integer.'
)
count
=
0
while
count
!=
iterator_size
:
count
+=
1
yield
GetRandomHash
(
hash_length
)


def PushPopItem(obj, key, value):
    '''
    A context manager to replace and restore a value using a getter and setter.

    :param object obj: The object to replace/restore.
    :param object key: The key to replace/restore in the object.
    :param object value: The value to replace.

    Example::

      with PushPop2(sys.modules, 'alpha', None):
        pytest.raises(ImportError):
          import alpha
    '''
    if key in obj:
        old_value = obj[key]
        obj[key] = value
        yield value
        obj[key] = old_value

    else:
        obj[key] = value
        yield value
        del obj[key]

def PushPopItem ( obj , key , value ) : if key in obj : old_value = obj [ key ] obj [ key ] = value yield value obj [ key ] = old_value else : obj [ key ] = value yield value del obj [ key ]

A context manager to replace and restore a value using a getter and setter .


def db_to_specifier(db_string):
    """
    Return the database specifier for a database string.

    This accepts a database name or URL, and returns a database specifier in the
    format accepted by ``specifier_to_db``. It is recommended that you consult
    the documentation for that function for an explanation of the format.
    """
    local_match = PLAIN_RE.match(db_string)
    remote_match = URL_RE.match(db_string)
    # If this looks like a local specifier:
    if local_match:
        return 'local:' + local_match.groupdict()['database']
    # If this looks like a remote specifier:
    elif remote_match:
        # Just a fancy way of getting 3 variables in 2 lines...
        hostname, portnum, database = map(remote_match.groupdict().get,
            ('hostname', 'portnum', 'database'))
        local_url = settings._('COUCHDB_SERVER', 'http://127.0.0.1:5984/')
        localhost, localport = urlparse.urlparse(local_url)[1].split(':')
        # If it's the local server, then return a local specifier.
        if (localhost == hostname) and (localport == portnum):
            return 'local:' + database
        # Otherwise, prepare and return the remote specifier.
        return 'remote:%s:%s:%s' % (hostname, portnum, database)
    # Throw a wobbly.
    raise ValueError('Invalid database string: %r' % (db_string,))

def
db_to_specifier
(
db_string
)
:
local_match
=
PLAIN_RE
.
match
(
db_string
)
remote_match
=
URL_RE
.
match
(
db_string
)
if
local_match
:
return
'local:'
+
local_match
.
groupdict
(
)
[
'database'
]
elif
remote_match
:
hostname
,
portnum
,
database
=
map
(
remote_match
.
groupdict
(
)
.
get
,
(
'hostname'
,
'portnum'
,
'database'
)
)
local_url
=
settings
.
_
(
'COUCHDB_SERVER'
,
'http://127.0.0.1:5984/'
)
localhost
,
localport
=
urlparse
.
urlparse
(
local_url
)
[
1
]
.
split
(
':'
)
if
(
localhost
==
hostname
)
and
(
localport
==
portnum
)
:
return
'local:'
+
database
return
'remote:%s:%s:%s'
%
(
hostname
,
portnum
,
database
)
raise
ValueError
(
'Invalid database string: %r'
%
(
db_string
,
)
)

Return the database specifier for a database string . This accepts a database name or URL and returns a database specifier in the format accepted by specifier_to_db . It is recommended that you consult the documentation for that function for an explanation of the format .


def get_db_from_db(db_string):
    """Return a CouchDB database instance from a database string."""
    server = get_server_from_db(db_string)
    local_match = PLAIN_RE.match(db_string)
    remote_match = URL_RE.match(db_string)
    # If this looks like a local specifier:
    if local_match:
        return server[local_match.groupdict()['database']]
    elif remote_match:
        return server[remote_match.groupdict()['database']]
    raise ValueError('Invalid database string: %r' % (db_string,))

def
get_db_from_db
(
db_string
)
:
server
=
get_server_from_db
(
db_string
)
local_match
=
PLAIN_RE
.
match
(
db_string
)
remote_match
=
URL_RE
.
match
(
db_string
)
if
local_match
:
return
server
[
local_match
.
groupdict
(
)
[
'database'
]
]
elif
remote_match
:
return
server
[
remote_match
.
groupdict
(
)
[
'database'
]
]
raise
ValueError
(
'Invalid database string: %r'
%
(
db_string
,
)
)

Return a CouchDB database instance from a database string .


def ensure_specifier_exists(db_spec):
    """Make sure a DB specifier exists, creating it if necessary."""
    local_match = LOCAL_RE.match(db_spec)
    remote_match = REMOTE_RE.match(db_spec)
    plain_match = PLAIN_RE.match(db_spec)
    if local_match:
        db_name = local_match.groupdict().get('database')
        server = shortcuts.get_server()
        if db_name not in server:
            server.create(db_name)
        return True
    elif remote_match:
        hostname, portnum, database = map(remote_match.groupdict().get,
            ('hostname', 'portnum', 'database'))
        server = shortcuts.get_server(
            server_url=('http://%s:%s' % (hostname, portnum)))
        if database not in server:
            server.create(database)
        return True
    elif plain_match:
        db_name = plain_match.groupdict().get('database')
        server = shortcuts.get_server()
        if db_name not in server:
            server.create(db_name)
        return True
    return False

def ensure_specifier_exists ( db_spec ) : local_match = LOCAL_RE . match ( db_spec ) remote_match = REMOTE_RE . match ( db_spec ) plain_match = PLAIN_RE . match ( db_spec ) if local_match : db_name = local_match . groupdict ( ) . get ( 'database' ) server = shortcuts . get_server ( ) if db_name not in server : server . create ( db_name ) return True elif remote_match : hostname , portnum , database = map ( remote_match . groupdict ( ) . get , ( 'hostname' , 'portnum' , 'database' ) ) server = shortcuts . get_server ( server_url = ( 'http://%s:%s' % ( hostname , portnum ) ) ) if database not in server : server . create ( database ) return True elif plain_match : db_name = plain_match . groupdict ( ) . get ( 'database' ) server = shortcuts . get_server ( ) if db_name not in server : server . create ( db_name ) return True return False

Make sure a DB specifier exists creating it if necessary .


def coerce(value1, value2, default=None):
    """Exclude NoSet objec

    .. code-block::

        >>> coerce(NoSet, 'value')
        'value'

    """
    if value1 is not NoSet:
        return value1
    elif value2 is not NoSet:
        return value2
    else:
        return default

def coerce ( value1 , value2 , default = None ) : if value1 is not NoSet : return value1 elif value2 is not NoSet : return value2 else : return default


def parse_hub_key(key):
    """Parse a hub key into a dictionary of component parts

    :param key: str, a hub key
    :returns: dict, hub key split into parts
    :raises: ValueError
    """
    if key is None:
        raise ValueError('Not a valid key')

    match = re.match(PATTERN, key)
    if not match:
        match = re.match(PATTERN_S0, key)
        if not match:
            raise ValueError('Not a valid key')

        return dict(map(normalise_part, zip([p for p in PARTS_S0.keys()], match.groups())))

    return dict(zip(PARTS.keys(), match.groups()))

def
parse_hub_key
(
key
)
:
if
key
is
:
raise
ValueError
(
'Not a valid key'
)
match
=
re
.
match
(
PATTERN
,
key
)
if
not
match
:
match
=
re
.
match
(
PATTERN_S0
,
key
)
if
not
match
:
raise
ValueError
(
'Not a valid key'
)
return
dict
(
map
(
normalise_part
,
zip
(
[
p
for
p
in
PARTS_S0
.
keys
(
)
]
,
match
.
groups
(
)
)
)
)
return
dict
(
zip
(
PARTS
.
keys
(
)
,
match
.
groups
(
)
)
)


def match_part(string, part):
    """Raise an exception if string doesn't match a part's regex

    :param string: str
    :param part: a key in the PARTS dict
    :raises: ValueError, TypeError
    """
    if not string or not re.match('^(' + PARTS[part] + ')$', string):
        raise ValueError('{} should match {}'.format(part, PARTS[part]))

def
match_part
(
string
,
part
)
:
if
not
string
or
not
re
.
match
(
'^('
+
PARTS
[
part
]
+
')$'
,
string
)
:
raise
ValueError
(
'{} should match {}'
.
format
(
part
,
PARTS
[
part
]
)
)

Raise an exception if string doesn t match a part s regex


def apply_defaults(self, commands):
        """ apply default settings to commands
            not static, shadow "self" in eval
        """
        for command in commands:
            if 'action' in command and "()" in command['action']:
                command['action'] = eval("self.{}".format(command['action']))
            if command['keys'][0].startswith('-'):
                if 'required' not in command:
                    command['required'] = False

def apply_defaults ( self , commands ) : for command in commands : if 'action' in command and "()" in command [ 'action' ] : command [ 'action' ] = eval ( "self.{}" . format ( command [ 'action' ] ) ) if command [ 'keys' ] [ 0 ] . startswith ( '-' ) : if 'required' not in command : command [ 'required' ] = False

apply default settings to commands not static shadow self in eval


def create_commands(self, commands, parser):
        """ add commands to parser """
        self.apply_defaults(commands)
        def create_single_command(command):
            keys = command['keys']
            del command['keys']
            kwargs = {}
            for item in command:
                kwargs[item] = command[item]
            parser.add_argument(*keys, **kwargs)

        if len(commands) > 1:
            for command in commands:
                create_single_command(command)
        else:
            create_single_command(commands[0])

def create_commands ( self , commands , parser ) : self . apply_defaults ( commands ) def create_single_command ( command ) : keys = command [ 'keys' ] del command [ 'keys' ] kwargs = { } for item in command : kwargs [ item ] = command [ item ] parser . add_argument ( * keys , ** kwargs ) if len ( commands ) > 1 : for command in commands : create_single_command ( command ) else : create_single_command ( commands [ 0 ] )


def create_subparsers(self, parser):
        """ get config for subparser and create commands"""
        subparsers = parser.add_subparsers()
        for name in self.config['subparsers']:
            subparser = subparsers.add_parser(name)
            self.create_commands(self.config['subparsers'][name], subparser)

def create_subparsers ( self , parser ) : subparsers = parser . add_subparsers ( ) for name in self . config [ 'subparsers' ] : subparser = subparsers . add_parser ( name ) self . create_commands ( self . config [ 'subparsers' ] [ name ] , subparser )


def show_version(self):
        """ custom command line  action to show version """
        class ShowVersionAction(argparse.Action):
            def __init__(inner_self, nargs=0, **kw):
                super(ShowVersionAction, inner_self).__init__(nargs=nargs, **kw)

            def __call__(inner_self, parser, args, value, option_string=None):
                print("{parser_name} version: {version}".format(
                    parser_name=self.config.get(
                        "parser", {}).get("prog"),
                    version=self.prog_version))
        return ShowVersionAction

def
show_version
(
self
)
:
class
ShowVersionAction
(
argparse
.
Action
)
:
def
__init__
(
inner_self
,
nargs
=
0
,
**
kw
)
:
super
(
ShowVersionAction
,
inner_self
)
.
__init__
(
nargs
=
nargs
,
**
kw
)
def
__call__
(
inner_self
,
parser
,
args
,
value
,
option_string
=
)
:
print
(
"{parser_name} version: {version}"
.
format
(
parser_name
=
self
.
config
.
get
(
"parser"
,
{
}
)
.
get
(
"prog"
)
,
version
=
self
.
prog_version
)
)
return
ShowVersionAction


def check_path_action(self):
        """ custom command line action to check file exist """
        class CheckPathAction(argparse.Action):
            def __call__(self, parser, args, value, option_string=None):
                if type(value) is list:
                    value = value[0]
                user_value = value
                if option_string == 'None':
                    if not os.path.isdir(value):
                        _current_user = os.path.expanduser("~")
                        if not value.startswith(_current_user) \
                                and not value.startswith(os.getcwd()):
                            if os.path.isdir(os.path.join(_current_user, value)):
                                value = os.path.join(_current_user, value)
                            elif os.path.isdir(os.path.join(os.getcwd(), value)):
                                value = os.path.join(os.getcwd(), value)
                            else:
                                value = None
                        else:
                            value = None
                elif option_string == '--template-name':
                    if not os.path.isdir(value):
                        if not os.path.isdir(os.path.join(args.target, value)):
                            value = None
                if not value:
                    logger.error("Could not to find path %s. Please provide "
                                 "correct path to %s option",
                                 user_value, option_string)
                    exit(1)
                setattr(args, self.dest, value)

        return CheckPathAction


def new_user(yaml_path):
    '''
    Return the consumer and oauth tokens with three-legged OAuth process and
    save in a yaml file in the user's home directory.
    '''

    print 'Retrieve API Key from https://www.shirts.io/accounts/api_console/'
    api_key = raw_input('Shirts.io API Key: ')

    tokens = {
        'api_key': api_key,
    }

    yaml_file = open(yaml_path, 'w+')
    yaml.dump(tokens, yaml_file, indent=2)
    yaml_file.close()

    return tokens

Return the consumer and oauth tokens with three - legged OAuth process and save in a yaml file in the user s home directory .


def _AddPropertiesForExtensions(descriptor, cls):
  """Adds properties for all fields in this protocol message type."""
  extension_dict = descriptor.extensions_by_name
  for extension_name, extension_field in extension_dict.items():
    constant_name = extension_name.upper() + "_FIELD_NUMBER"
    setattr(cls, constant_name, extension_field.number)

def _AddPropertiesForExtensions ( descriptor , cls ) : extension_dict = descriptor . extensions_by_name for extension_name , extension_field in extension_dict . items ( ) : constant_name = extension_name . upper ( ) + "_FIELD_NUMBER" setattr ( cls , constant_name , extension_field . number )

Adds properties for all fields in this protocol message type .


def _InternalUnpackAny(msg):
  """Unpacks Any message and returns the unpacked message.

  This internal method is differnt from public Any Unpack method which takes
  the target message as argument. _InternalUnpackAny method does not have
  target message type and need to find the message type in descriptor pool.

  Args:
    msg: An Any message to be unpacked.

  Returns:
    The unpacked message.
  """
  type_url = msg.type_url
  db = symbol_database.Default()

  if not type_url:
    return None

  # TODO(haberman): For now we just strip the hostname.  Better logic will be
  # required.
  type_name = type_url.split("/")[-1]
  descriptor = db.pool.FindMessageTypeByName(type_name)

  if descriptor is None:
    return None

  message_class = db.GetPrototype(descriptor)
  message = message_class()

  message.ParseFromString(msg.value)
  return message

def _InternalUnpackAny ( msg ) : type_url = msg . type_url db = symbol_database . Default ( ) if not type_url : return None type_name = type_url . split ( "/" ) [ - 1 ] descriptor = db . pool . FindMessageTypeByName ( type_name ) if descriptor is None : return None message_class = db . GetPrototype ( descriptor ) message = message_class ( ) message . ParseFromString ( msg . value ) return message

Unpacks Any message and returns the unpacked message .