123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- """
- Useful functions to be used in Python scripts.
- Usage:
- ::
- from grass.script import utils as gutils
- (C) 2014 by the GRASS Development Team
- This program is free software under the GNU General Public
- License (>=v2). Read the file COPYING that comes with GRASS
- for details.
- .. sectionauthor:: Glynn Clements
- .. sectionauthor:: Martin Landa <landa.martin gmail.com>
- .. sectionauthor:: Anna Petrasova <kratochanna gmail.com>
- """
- import os
- import sys
- import shutil
- import locale
- import shlex
- def float_or_dms(s):
- """Convert DMS to float.
- >>> round(float_or_dms('26:45:30'), 5)
- 26.75833
- >>> round(float_or_dms('26:0:0.1'), 5)
- 26.00003
- :param s: DMS value
- :return: float value
- """
- return sum(float(x) / 60 ** n for (n, x) in enumerate(s.split(':')))
- def separator(sep):
- """Returns separator from G_OPT_F_SEP appropriately converted
- to character.
- >>> separator('pipe')
- '|'
- >>> separator('comma')
- ','
- If the string does not match any of the spearator keywords,
- it is returned as is:
- >>> separator(', ')
- ', '
- :param str separator: character or separator keyword
- :return: separator character
- """
- if sep == "pipe":
- return "|"
- elif sep == "comma":
- return ","
- elif sep == "space":
- return " "
- elif sep == "tab" or sep == "\\t":
- return "\t"
- elif sep == "newline" or sep == "\\n":
- return "\n"
- return sep
- def diff_files(filename_a, filename_b):
- """Diffs two text files and returns difference.
- :param str filename_a: first file path
- :param str filename_b: second file path
- :return: list of strings
- """
- import difflib
- differ = difflib.Differ()
- fh_a = open(filename_a, 'r')
- fh_b = open(filename_b, 'r')
- result = list(differ.compare(fh_a.readlines(),
- fh_b.readlines()))
- return result
- def try_remove(path):
- """Attempt to remove a file; no exception is generated if the
- attempt fails.
- :param str path: path to file to remove
- """
- try:
- os.remove(path)
- except:
- pass
- def try_rmdir(path):
- """Attempt to remove a directory; no exception is generated if the
- attempt fails.
- :param str path: path to directory to remove
- """
- try:
- os.rmdir(path)
- except:
- shutil.rmtree(path, ignore_errors=True)
- def basename(path, ext=None):
- """Remove leading directory components and an optional extension
- from the specified path
- :param str path: path
- :param str ext: extension
- """
- name = os.path.basename(path)
- if not ext:
- return name
- fs = name.rsplit('.', 1)
- if len(fs) > 1 and fs[1].lower() == ext:
- name = fs[0]
- return name
- class KeyValue(dict):
- """A general-purpose key-value store.
- KeyValue is a subclass of dict, but also allows entries to be read and
- written using attribute syntax. Example:
- >>> reg = KeyValue()
- >>> reg['north'] = 489
- >>> reg.north
- 489
- >>> reg.south = 205
- >>> reg['south']
- 205
- """
- def __getattr__(self, key):
- return self[key]
- def __setattr__(self, key, value):
- self[key] = value
- def parse_key_val(s, sep='=', dflt=None, val_type=None, vsep=None):
- """Parse a string into a dictionary, where entries are separated
- by newlines and the key and value are separated by `sep` (default: `=`)
- >>> parse_key_val('min=20\\nmax=50') == {'min': '20', 'max': '50'}
- True
- >>> parse_key_val('min=20\\nmax=50',
- ... val_type=float) == {'min': 20, 'max': 50}
- True
- :param str s: string to be parsed
- :param str sep: key/value separator
- :param dflt: default value to be used
- :param val_type: value type (None for no cast)
- :param vsep: vertical separator (default is Python 'universal newlines' approach)
- :return: parsed input (dictionary of keys/values)
- """
- result = KeyValue()
- if not s:
- return result
- if vsep:
- lines = s.split(vsep)
- try:
- lines.remove('\n')
- except ValueError:
- pass
- else:
- lines = s.splitlines()
- for line in lines:
- kv = line.split(sep, 1)
- k = kv[0].strip()
- if len(kv) > 1:
- v = kv[1].strip()
- else:
- v = dflt
- if val_type:
- result[k] = val_type(v)
- else:
- result[k] = v
- return result
- def decode(string):
- """Decode string with defualt locale
- :param str string: the string to decode
- """
- enc = locale.getdefaultlocale()[1]
- if enc:
- return string.decode(enc)
- return string
- def encode(string):
- """Encode string with defualt locale
- :param str string: the string to encode
- """
- enc = locale.getdefaultlocale()[1]
- if enc:
- return string.encode(enc)
- return string
- def get_num_suffix(number, max_number):
- """Returns formatted number with number of padding zeros
- depending on maximum number, used for creating suffix for data series.
- Does not include the suffix separator.
- :param number: number to be formated as map suffix
- :param max_number: maximum number of the series to get number of digits
- >>> get_num_suffix(10, 1000)
- '0010'
- >>> get_num_suffix(10, 10)
- '10'
- """
- return '{number:0{width}d}'.format(width=len(str(max_number)),
- number=number)
- def split(s):
- """!Platform specific shlex.split"""
- if sys.version_info >= (2, 6):
- return shlex.split(s, posix = (sys.platform != "win32"))
- elif sys.platform == "win32":
- return shlex.split(s.replace('\\', r'\\'))
- else:
- return shlex.split(s)
|