Robot Framework Integrated Development Environment (RIDE)
OperatingSystem.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import fnmatch
17 import glob
18 import io
19 import os
20 import shutil
21 import sys
22 import tempfile
23 import time
24 
25 from robotide.lib.robot.version import get_version
26 from robotide.lib.robot.api import logger
27 from robotide.lib.robot.utils import (abspath, ConnectionCache, console_decode, del_env_var,
28  get_env_var, get_env_vars, get_time, is_truthy,
29  is_unicode, normpath, parse_time, plural_or_not,
30  secs_to_timestamp, secs_to_timestr, seq2str,
31  set_env_var, timestr_to_secs, unic, CONSOLE_ENCODING,
32  IRONPYTHON, JYTHON, PY2, PY3, SYSTEM_ENCODING, WINDOWS)
33 
34 __version__ = get_version()
35 PROCESSES = ConnectionCache('No active processes.')
36 
37 
38 
141  ROBOT_LIBRARY_SCOPE = 'GLOBAL'
142  ROBOT_LIBRARY_VERSION = __version__
143 
144 
179  def run(self, command):
180  return self._run_run(command)[1]
181 
182 
206  def run_and_return_rc(self, command):
207  return self._run_run(command)[0]
208 
209 
228  def run_and_return_rc_and_output(self, command):
229  return self._run_run(command)
230 
231  def _run(self, command):
232  process = _Process(command)
233  self._info_info("Running command '%s'." % process)
234  stdout = process.read()
235  rc = process.close()
236  return rc, stdout
237 
238 
265  def get_file(self, path, encoding='UTF-8', encoding_errors='strict'):
266  path = self._absnorm_absnorm(path)
267  self._link_link("Getting file '%s'.", path)
268  encoding = self._map_encoding_map_encoding(encoding)
269  if IRONPYTHON:
270  # https://github.com/IronLanguages/main/issues/1233
271  with open(path) as f:
272  content = f.read().decode(encoding, encoding_errors)
273  else:
274  with io.open(path, encoding=encoding, errors=encoding_errors,
275  newline='') as f:
276  content = f.read()
277  return content.replace('\r\n', '\n')
278 
279  def _map_encoding(self, encoding):
280  # Python 3 opens files in native system encoding by default.
281  if PY3 and encoding.upper() == 'SYSTEM':
282  return None
283  return {'SYSTEM': SYSTEM_ENCODING,
284  'CONSOLE': CONSOLE_ENCODING}.get(encoding.upper(), encoding)
285 
286 
291  def get_binary_file(self, path):
292  path = self._absnorm_absnorm(path)
293  self._link_link("Getting file '%s'.", path)
294  with open(path, 'rb') as f:
295  return bytes(f.read())
296 
297 
319  def grep_file(self, path, pattern, encoding='UTF-8', encoding_errors='strict'):
320  pattern = '*%s*' % pattern
321  path = self._absnorm_absnorm(path)
322  lines = []
323  total_lines = 0
324  self._link_link("Reading file '%s'.", path)
325  with io.open(path, encoding=encoding, errors=encoding_errors) as f:
326  for line in f.readlines():
327  total_lines += 1
328  line = line.rstrip('\r\n')
329  if fnmatch.fnmatchcase(line, pattern):
330  lines.append(line)
331  self._info_info('%d out of %d lines matched' % (len(lines), total_lines))
332  return '\n'.join(lines)
333 
334 
343  def log_file(self, path, encoding='UTF-8', encoding_errors='strict'):
344  content = self.get_fileget_file(path, encoding, encoding_errors)
345  self._info_info(content)
346  return content
347 
348  # File and directory existence
349 
350 
356  def should_exist(self, path, msg=None):
357  path = self._absnorm_absnorm(path)
358  if not self._glob_glob(path):
359  self._fail_fail(msg, "Path '%s' does not exist." % path)
360  self._link_link("Path '%s' exists.", path)
361 
362 
368  def should_not_exist(self, path, msg=None):
369  path = self._absnorm_absnorm(path)
370  matches = self._glob_glob(path)
371  if matches:
372  self._fail_fail(msg, self._get_matches_error_get_matches_error('Path', path, matches))
373  self._link_link("Path '%s' does not exist.", path)
374 
375  def _glob(self, path):
376  return glob.glob(path) if not os.path.exists(path) else [path]
377 
378  def _get_matches_error(self, what, path, matches):
379  if not self._is_glob_path_is_glob_path(path):
380  return "%s '%s' exists." % (what, path)
381  return "%s '%s' matches %s." % (what, path, seq2str(sorted(matches)))
382 
383  def _is_glob_path(self, path):
384  return '*' in path or '?' in path or ('[' in path and ']' in path)
385 
386 
392  def file_should_exist(self, path, msg=None):
393  path = self._absnorm_absnorm(path)
394  matches = [p for p in self._glob_glob(path) if os.path.isfile(p)]
395  if not matches:
396  self._fail_fail(msg, "File '%s' does not exist." % path)
397  self._link_link("File '%s' exists.", path)
398 
399 
405  def file_should_not_exist(self, path, msg=None):
406  path = self._absnorm_absnorm(path)
407  matches = [p for p in self._glob_glob(path) if os.path.isfile(p)]
408  if matches:
409  self._fail_fail(msg, self._get_matches_error_get_matches_error('File', path, matches))
410  self._link_link("File '%s' does not exist.", path)
411 
412 
418  def directory_should_exist(self, path, msg=None):
419  path = self._absnorm_absnorm(path)
420  matches = [p for p in self._glob_glob(path) if os.path.isdir(p)]
421  if not matches:
422  self._fail_fail(msg, "Directory '%s' does not exist." % path)
423  self._link_link("Directory '%s' exists.", path)
424 
425 
431  def directory_should_not_exist(self, path, msg=None):
432  path = self._absnorm_absnorm(path)
433  matches = [p for p in self._glob_glob(path) if os.path.isdir(p)]
434  if matches:
435  self._fail_fail(msg, self._get_matches_error_get_matches_error('Directory', path, matches))
436  self._link_link("Directory '%s' does not exist.", path)
437 
438  # Waiting file/dir to appear/disappear
439 
440 
455  def wait_until_removed(self, path, timeout='1 minute'):
456  path = self._absnorm_absnorm(path)
457  timeout = timestr_to_secs(timeout)
458  maxtime = time.time() + timeout
459  while self._glob_glob(path):
460  if timeout >= 0 and time.time() > maxtime:
461  self._fail_fail("'%s' was not removed in %s."
462  % (path, secs_to_timestr(timeout)))
463  time.sleep(0.1)
464  self._link_link("'%s' was removed.", path)
465 
466 
481  def wait_until_created(self, path, timeout='1 minute'):
482  path = self._absnorm_absnorm(path)
483  timeout = timestr_to_secs(timeout)
484  maxtime = time.time() + timeout
485  while not self._glob_glob(path):
486  if timeout >= 0 and time.time() > maxtime:
487  self._fail_fail("'%s' was not created in %s."
488  % (path, secs_to_timestr(timeout)))
489  time.sleep(0.1)
490  self._link_link("'%s' was created.", path)
491 
492  # Dir/file empty
493 
494 
498  def directory_should_be_empty(self, path, msg=None):
499  path = self._absnorm_absnorm(path)
500  items = self._list_dir_list_dir(path)
501  if items:
502  self._fail_fail(msg, "Directory '%s' is not empty. Contents: %s."
503  % (path, seq2str(items, lastsep=', ')))
504  self._link_link("Directory '%s' is empty.", path)
505 
506 
510  def directory_should_not_be_empty(self, path, msg=None):
511  path = self._absnorm_absnorm(path)
512  items = self._list_dir_list_dir(path)
513  if not items:
514  self._fail_fail(msg, "Directory '%s' is empty." % path)
515  self._link_link("Directory '%%s' contains %d item%s."
516  % (len(items), plural_or_not(items)), path)
517 
518 
522  def file_should_be_empty(self, path, msg=None):
523  path = self._absnorm_absnorm(path)
524  if not os.path.isfile(path):
525  self._error_error("File '%s' does not exist." % path)
526  size = os.stat(path).st_size
527  if size > 0:
528  self._fail_fail(msg,
529  "File '%s' is not empty. Size: %d bytes." % (path, size))
530  self._link_link("File '%s' is empty.", path)
531 
532 
536  def file_should_not_be_empty(self, path, msg=None):
537  path = self._absnorm_absnorm(path)
538  if not os.path.isfile(path):
539  self._error_error("File '%s' does not exist." % path)
540  size = os.stat(path).st_size
541  if size == 0:
542  self._fail_fail(msg, "File '%s' is empty." % path)
543  self._link_link("File '%%s' contains %d bytes." % size, path)
544 
545  # Creating and removing files and directory
546 
547 
573  def create_file(self, path, content='', encoding='UTF-8'):
574  path = self._write_to_file_write_to_file(path, content, encoding)
575  self._link_link("Created file '%s'.", path)
576 
577  def _write_to_file(self, path, content, encoding=None, mode='w'):
578  path = self._absnorm_absnorm(path)
579  parent = os.path.dirname(path)
580  if not os.path.exists(parent):
581  os.makedirs(parent)
582  # io.open() only accepts Unicode, not byte-strings, in text mode.
583  # We expect possible byte-strings to be all ASCII.
584  if PY2 and isinstance(content, str) and 'b' not in mode:
585  content = unicode(content)
586  if encoding:
587  encoding = self._map_encoding_map_encoding(encoding)
588  with io.open(path, mode, encoding=encoding) as f:
589  f.write(content)
590  return path
591 
592 
612  def create_binary_file(self, path, content):
613  if is_unicode(content):
614  content = bytes(bytearray(ord(c) for c in content))
615  path = self._write_to_file_write_to_file(path, content, mode='wb')
616  self._link_link("Created binary file '%s'.", path)
617 
618 
630  def append_to_file(self, path, content, encoding='UTF-8'):
631  path = self._write_to_file_write_to_file(path, content, encoding, mode='a')
632  self._link_link("Appended to file '%s'.", path)
633 
634 
643  def remove_file(self, path):
644  path = self._absnorm_absnorm(path)
645  matches = self._glob_glob(path)
646  if not matches:
647  self._link_link("File '%s' does not exist.", path)
648  for match in matches:
649  if not os.path.isfile(match):
650  self._error_error("Path '%s' is not a file." % match)
651  os.remove(match)
652  self._link_link("Removed file '%s'.", match)
653 
654 
659  def remove_files(self, *paths):
660  for path in paths:
661  self.remove_fileremove_file(path)
662 
663 
669  def empty_directory(self, path):
670  path = self._absnorm_absnorm(path)
671  for item in self._list_dir_list_dir(path, absolute=True):
672  if os.path.isdir(item):
673  shutil.rmtree(item)
674  else:
675  os.remove(item)
676  self._link_link("Emptied directory '%s'.", path)
677 
678 
684  def create_directory(self, path):
685  path = self._absnorm_absnorm(path)
686  if os.path.isdir(path):
687  self._link_link("Directory '%s' already exists.", path )
688  elif os.path.exists(path):
689  self._error_error("Path '%s' is not a directory." % path)
690  else:
691  os.makedirs(path)
692  self._link_link("Created directory '%s'.", path)
693 
694 
703  def remove_directory(self, path, recursive=False):
704  path = self._absnorm_absnorm(path)
705  if not os.path.exists(path):
706  self._link_link("Directory '%s' does not exist.", path)
707  elif not os.path.isdir(path):
708  self._error_error("Path '%s' is not a directory." % path)
709  else:
710  if is_truthy(recursive):
711  shutil.rmtree(path)
712  else:
713  self.directory_should_be_emptydirectory_should_be_empty(
714  path, "Directory '%s' is not empty." % path)
715  os.rmdir(path)
716  self._link_link("Removed directory '%s'.", path)
717 
718  # Moving and copying files and directories
719 
720 
746  def copy_file(self, source, destination):
747  source, destination = \
748  self._prepare_copy_and_move_file_prepare_copy_and_move_file(source, destination)
749  if not self._are_source_and_destination_same_file_are_source_and_destination_same_file(source, destination):
750  source, destination = self._atomic_copy_atomic_copy(source, destination)
751  self._link_link("Copied file from '%s' to '%s'.", source, destination)
752  return destination
753 
754  def _prepare_copy_and_move_file(self, source, destination):
755  source = self._normalize_copy_and_move_source_normalize_copy_and_move_source(source)
756  destination = self._normalize_copy_and_move_destination_normalize_copy_and_move_destination(destination)
757  if os.path.isdir(destination):
758  destination = os.path.join(destination, os.path.basename(source))
759  return source, destination
760 
762  source = self._absnorm_absnorm(source)
763  sources = self._glob_glob(source)
764  if len(sources) > 1:
765  self._error_error("Multiple matches with source pattern '%s'." % source)
766  if sources:
767  source = sources[0]
768  if not os.path.exists(source):
769  self._error_error("Source file '%s' does not exist." % source)
770  if not os.path.isfile(source):
771  self._error_error("Source file '%s' is not a regular file." % source)
772  return source
773 
774  def _normalize_copy_and_move_destination(self, destination):
775  is_dir = os.path.isdir(destination) or destination.endswith(('/', '\\'))
776  destination = self._absnorm_absnorm(destination)
777  directory = destination if is_dir else os.path.dirname(destination)
778  self._ensure_destination_directory_exists_ensure_destination_directory_exists(directory)
779  return destination
780 
782  if not os.path.exists(path):
783  os.makedirs(path)
784  elif not os.path.isdir(path):
785  self._error_error("Destination '%s' exists and is not a directory." % path)
786 
787  def _are_source_and_destination_same_file(self, source, destination):
788  if self._force_normalize_force_normalize(source) == self._force_normalize_force_normalize(destination):
789  self._link_link("Source '%s' and destination '%s' point to the same "
790  "file.", source, destination)
791  return True
792  return False
793 
794  def _force_normalize(self, path):
795  # TODO: Should normalize_path also support link normalization?
796  # TODO: Should we handle dos paths like 'exampl~1.txt'?
797  return os.path.realpath(normpath(path, case_normalize=True))
798 
799 
815  def _atomic_copy(self, source, destination):
816  temp_directory = tempfile.mkdtemp(dir=os.path.dirname(destination))
817  temp_file = os.path.join(temp_directory, os.path.basename(source))
818  try:
819  shutil.copy(source, temp_file)
820  if os.path.exists(destination):
821  os.remove(destination)
822  shutil.move(temp_file, destination)
823  finally:
824  shutil.rmtree(temp_directory)
825  return source, destination
826 
827 
838  def move_file(self, source, destination):
839  source, destination = \
840  self._prepare_copy_and_move_file_prepare_copy_and_move_file(source, destination)
841  if not self._are_source_and_destination_same_file_are_source_and_destination_same_file(destination, source):
842  shutil.move(source, destination)
843  self._link_link("Moved file from '%s' to '%s'.", source, destination)
844  return destination
845 
846 
861  def copy_files(self, *sources_and_destination):
862  sources, destination \
863  = self._prepare_copy_and_move_files_prepare_copy_and_move_files(sources_and_destination)
864  for source in sources:
865  self.copy_filecopy_file(source, destination)
866 
868  if len(items) < 2:
869  self._error_error('Must contain destination and at least one source.')
870  sources = self._glob_files_glob_files(items[:-1])
871  destination = self._absnorm_absnorm(items[-1])
872  self._ensure_destination_directory_exists_ensure_destination_directory_exists(destination)
873  return sources, destination
874 
875  def _glob_files(self, patterns):
876  files = []
877  for pattern in patterns:
878  files.extend(self._glob_glob(self._absnorm_absnorm(pattern)))
879  return files
880 
881 
887  def move_files(self, *sources_and_destination):
888  sources, destination \
889  = self._prepare_copy_and_move_files_prepare_copy_and_move_files(sources_and_destination)
890  for source in sources:
891  self.move_filemove_file(source, destination)
892 
893 
899  def copy_directory(self, source, destination):
900  source, destination \
901  = self._prepare_copy_and_move_directory_prepare_copy_and_move_directory(source, destination)
902  try:
903  shutil.copytree(source, destination)
904  except shutil.Error:
905  # https://github.com/robotframework/robotframework/issues/2321
906  if not (WINDOWS and JYTHON):
907  raise
908  self._link_link("Copied directory from '%s' to '%s'.", source, destination)
909 
910  def _prepare_copy_and_move_directory(self, source, destination):
911  source = self._absnorm_absnorm(source)
912  destination = self._absnorm_absnorm(destination)
913  if not os.path.exists(source):
914  self._error_error("Source '%s' does not exist." % source)
915  if not os.path.isdir(source):
916  self._error_error("Source '%s' is not a directory." % source)
917  if os.path.exists(destination) and not os.path.isdir(destination):
918  self._error_error("Destination '%s' is not a directory." % destination)
919  if os.path.exists(destination):
920  base = os.path.basename(source)
921  destination = os.path.join(destination, base)
922  else:
923  parent = os.path.dirname(destination)
924  if not os.path.exists(parent):
925  os.makedirs(parent)
926  return source, destination
927 
928 
934  def move_directory(self, source, destination):
935  source, destination \
936  = self._prepare_copy_and_move_directory_prepare_copy_and_move_directory(source, destination)
937  shutil.move(source, destination)
938  self._link_link("Moved directory from '%s' to '%s'.", source, destination)
939 
940  # Environment Variables
941 
942 
953  def get_environment_variable(self, name, default=None):
954  value = get_env_var(name, default)
955  if value is None:
956  self._error_error("Environment variable '%s' does not exist." % name)
957  return value
958 
959 
964  def set_environment_variable(self, name, value):
965  set_env_var(name, value)
966  self._info_info("Environment variable '%s' set to value '%s'."
967  % (name, value))
968 
969 
989  def append_to_environment_variable(self, name, *values, **config):
990  sentinel = object()
991  initial = self.get_environment_variableget_environment_variable(name, sentinel)
992  if initial is not sentinel:
993  values = (initial,) + values
994  separator = config.pop('separator', os.pathsep)
995  if config:
996  config = ['='.join(i) for i in sorted(config.items())]
997  self._error_error('Configuration %s not accepted.'
998  % seq2str(config, lastsep=' or '))
999  self.set_environment_variableset_environment_variable(name, separator.join(values))
1000 
1001 
1008  def remove_environment_variable(self, *names):
1009  for name in names:
1010  value = del_env_var(name)
1011  if value:
1012  self._info_info("Environment variable '%s' deleted." % name)
1013  else:
1014  self._info_info("Environment variable '%s' does not exist." % name)
1015 
1016 
1020  def environment_variable_should_be_set(self, name, msg=None):
1021  value = get_env_var(name)
1022  if not value:
1023  self._fail_fail(msg, "Environment variable '%s' is not set." % name)
1024  self._info_info("Environment variable '%s' is set to '%s'." % (name, value))
1025 
1026 
1030  def environment_variable_should_not_be_set(self, name, msg=None):
1031  value = get_env_var(name)
1032  if value:
1033  self._fail_fail(msg, "Environment variable '%s' is set to '%s'."
1034  % (name, value))
1035  self._info_info("Environment variable '%s' is not set." % name)
1036 
1037 
1044  return get_env_vars()
1045 
1046 
1051  def log_environment_variables(self, level='INFO'):
1052  variables = get_env_vars()
1053  for name in sorted(variables, key=lambda item: item.lower()):
1054  self._log_log('%s = %s' % (name, variables[name]), level)
1055  return variables
1056 
1057  # Path
1058 
1059 
1078  def join_path(self, base, *parts):
1079  base = base.replace('/', os.sep)
1080  parts = [p.replace('/', os.sep) for p in parts]
1081  return self.normalize_pathnormalize_path(os.path.join(base, *parts))
1082 
1083 
1096  def join_paths(self, base, *paths):
1097  return [self.join_pathjoin_path(base, path) for path in paths]
1098 
1099 
1123  def normalize_path(self, path, case_normalize=False):
1124  path = os.path.normpath(os.path.expanduser(path.replace('/', os.sep)))
1125  # os.path.normcase doesn't normalize on OSX which also, by default,
1126  # has case-insensitive file system. Our robot.utils.normpath would
1127  # do that, but it's not certain would that, or other things that the
1128  # utility do, desirable.
1129  if case_normalize:
1130  path = os.path.normcase(path)
1131  return path or '.'
1132 
1133 
1149  def split_path(self, path):
1150  return os.path.split(self.normalize_pathnormalize_path(path))
1151 
1152 
1177  def split_extension(self, path):
1178  path = self.normalize_pathnormalize_path(path)
1179  basename = os.path.basename(path)
1180  if basename.startswith('.' * basename.count('.')):
1181  return path, ''
1182  if path.endswith('.'):
1183  path2 = path.rstrip('.')
1184  trailing_dots = '.' * (len(path) - len(path2))
1185  path = path2
1186  else:
1187  trailing_dots = ''
1188  basepath, extension = os.path.splitext(path)
1189  if extension.startswith('.'):
1190  extension = extension[1:]
1191  if extension:
1192  extension += trailing_dots
1193  else:
1194  basepath += trailing_dots
1195  return basepath, extension
1196 
1197  # Misc
1198 
1199 
1233  def get_modified_time(self, path, format='timestamp'):
1234  path = self._absnorm_absnorm(path)
1235  if not os.path.exists(path):
1236  self._error_error("Path '%s' does not exist." % path)
1237  mtime = get_time(format, os.stat(path).st_mtime)
1238  self._link_link("Last modified time of '%%s' is %s." % mtime, path)
1239  return mtime
1240 
1241 
1276  def set_modified_time(self, path, mtime):
1277  mtime = parse_time(mtime)
1278  path = self._absnorm_absnorm(path)
1279  if not os.path.exists(path):
1280  self._error_error("File '%s' does not exist." % path)
1281  if not os.path.isfile(path):
1282  self._error_error("Path '%s' is not a regular file." % path)
1283  os.utime(path, (mtime, mtime))
1284  time.sleep(0.1) # Give os some time to really set these times
1285  tstamp = secs_to_timestamp(mtime, seps=('-', ' ', ':'))
1286  self._link_link("Set modified time of '%%s' to %s." % tstamp, path)
1287 
1288 
1289  def get_file_size(self, path):
1290  path = self._absnorm_absnorm(path)
1291  if not os.path.isfile(path):
1292  self._error_error("File '%s' does not exist." % path)
1293  size = os.stat(path).st_size
1294  plural = plural_or_not(size)
1295  self._link_link("Size of file '%%s' is %d byte%s." % (size, plural), path)
1296  return size
1297 
1298 
1319  def list_directory(self, path, pattern=None, absolute=False):
1320  items = self._list_dir_list_dir(path, pattern, absolute)
1321  self._info_info('%d item%s:\n%s' % (len(items), plural_or_not(items),
1322  '\n'.join(items)))
1323  return items
1324 
1325 
1326  def list_files_in_directory(self, path, pattern=None, absolute=False):
1327  files = self._list_files_in_dir_list_files_in_dir(path, pattern, absolute)
1328  self._info_info('%d file%s:\n%s' % (len(files), plural_or_not(files),
1329  '\n'.join(files)))
1330  return files
1331 
1332 
1333  def list_directories_in_directory(self, path, pattern=None, absolute=False):
1334  dirs = self._list_dirs_in_dir_list_dirs_in_dir(path, pattern, absolute)
1335  self._info_info('%d director%s:\n%s' % (len(dirs),
1336  'y' if len(dirs) == 1 else 'ies',
1337  '\n'.join(dirs)))
1338  return dirs
1339 
1340 
1346  def count_items_in_directory(self, path, pattern=None):
1347  count = len(self._list_dir_list_dir(path, pattern))
1348  self._info_info("%s item%s." % (count, plural_or_not(count)))
1349  return count
1350 
1351 
1352  def count_files_in_directory(self, path, pattern=None):
1353  count = len(self._list_files_in_dir_list_files_in_dir(path, pattern))
1354  self._info_info("%s file%s." % (count, plural_or_not(count)))
1355  return count
1356 
1357 
1358  def count_directories_in_directory(self, path, pattern=None):
1359  count = len(self._list_dirs_in_dir_list_dirs_in_dir(path, pattern))
1360  self._info_info("%s director%s." % (count, 'y' if count == 1 else 'ies'))
1361  return count
1362 
1363  def _list_dir(self, path, pattern=None, absolute=False):
1364  path = self._absnorm_absnorm(path)
1365  self._link_link("Listing contents of directory '%s'.", path)
1366  if not os.path.isdir(path):
1367  self._error_error("Directory '%s' does not exist." % path)
1368  # result is already unicode but unic also handles NFC normalization
1369  items = sorted(unic(item) for item in os.listdir(path))
1370  if pattern:
1371  items = [i for i in items if fnmatch.fnmatchcase(i, pattern)]
1372  if is_truthy(absolute):
1373  path = os.path.normpath(path)
1374  items = [os.path.join(path, item) for item in items]
1375  return items
1376 
1377  def _list_files_in_dir(self, path, pattern=None, absolute=False):
1378  return [item for item in self._list_dir_list_dir(path, pattern, absolute)
1379  if os.path.isfile(os.path.join(path, item))]
1380 
1381  def _list_dirs_in_dir(self, path, pattern=None, absolute=False):
1382  return [item for item in self._list_dir_list_dir(path, pattern, absolute)
1383  if os.path.isdir(os.path.join(path, item))]
1384 
1385 
1393  def touch(self, path):
1394  path = self._absnorm_absnorm(path)
1395  if os.path.isdir(path):
1396  self._error_error("Cannot touch '%s' because it is a directory." % path)
1397  if not os.path.exists(os.path.dirname(path)):
1398  self._error_error("Cannot touch '%s' because its parent directory does "
1399  "not exist." % path)
1400  if os.path.exists(path):
1401  mtime = round(time.time())
1402  os.utime(path, (mtime, mtime))
1403  self._link_link("Touched existing file '%s'.", path)
1404  else:
1405  open(path, 'w').close()
1406  self._link_link("Touched new file '%s'.", path)
1407 
1408  def _absnorm(self, path):
1409  path = self.normalize_pathnormalize_path(path)
1410  try:
1411  return abspath(path)
1412  except ValueError: # http://ironpython.codeplex.com/workitem/29489
1413  return path
1414 
1415  def _fail(self, *messages):
1416  raise AssertionError(next(msg for msg in messages if msg))
1417 
1418  def _error(self, msg):
1419  raise RuntimeError(msg)
1420 
1421  def _info(self, msg):
1422  self._log_log(msg, 'INFO')
1423 
1424  def _link(self, msg, *paths):
1425  paths = tuple('<a href="file://%s">%s</a>' % (p, p) for p in paths)
1426  self._log_log(msg % paths, 'HTML')
1427 
1428  def _warn(self, msg):
1429  self._log_log(msg, 'WARN')
1430 
1431  def _log(self, msg, level):
1432  logger.write(msg, level)
1433 
1434 
1435 class _Process:
1436 
1437  def __init__(self, command):
1438  self._command_command = self._process_command_process_command(command)
1439  self._process_process = os.popen(self._command_command)
1440 
1441  def __str__(self):
1442  return self._command_command
1443 
1444  def read(self):
1445  return self._process_output_process_output(self._process_process.read())
1446 
1447  def close(self):
1448  try:
1449  rc = self._process_process.close()
1450  except IOError: # Has occurred sometimes in Windows
1451  return 255
1452  if rc is None:
1453  return 0
1454  # In Windows (Python and Jython) return code is value returned by
1455  # command (can be almost anything)
1456  # In other OS:
1457  # In Jython return code can be between '-255' - '255'
1458  # In Python return code must be converted with 'rc >> 8' and it is
1459  # between 0-255 after conversion
1460  if WINDOWS or JYTHON:
1461  return rc % 256
1462  return rc >> 8
1463 
1464  def _process_command(self, command):
1465  if '>' not in command:
1466  if command.endswith('&'):
1467  command = command[:-1] + ' 2>&1 &'
1468  else:
1469  command += ' 2>&1'
1470  return self._encode_to_file_system_encode_to_file_system(command)
1471 
1472  def _encode_to_file_system(self, string):
1473  enc = sys.getfilesystemencoding() if PY2 else None
1474  return string.encode(enc) if enc else string
1475 
1476  def _process_output(self, output):
1477  if '\r\n' in output:
1478  output = output.replace('\r\n', '\n')
1479  if output.endswith('\n'):
1480  output = output[:-1]
1481  return console_decode(output, force=True)
A test library providing keywords for OS related tasks.
def get_file_size(self, path)
Returns and logs file size as an integer in bytes.
def environment_variable_should_be_set(self, name, msg=None)
Fails if the specified environment variable is not set.
def should_not_exist(self, path, msg=None)
Fails if the given path (file or directory) exists.
def remove_file(self, path)
Removes a file with the given path.
def create_directory(self, path)
Creates the specified directory.
def wait_until_removed(self, path, timeout='1 minute')
Waits until the given file or directory is removed.
def directory_should_be_empty(self, path, msg=None)
Fails unless the specified directory is empty.
def create_binary_file(self, path, content)
Creates a binary file with the given content.
def touch(self, path)
Emulates the UNIX touch command.
def remove_files(self, *paths)
Uses Remove File to remove multiple files one-by-one.
def file_should_not_exist(self, path, msg=None)
Fails if the given path points to an existing file.
def copy_files(self, *sources_and_destination)
Copies specified files to the target directory.
def get_environment_variable(self, name, default=None)
Returns the value of an environment variable with the given name.
def log_file(self, path, encoding='UTF-8', encoding_errors='strict')
Wrapper for Get File that also logs the returned file.
def move_file(self, source, destination)
Moves the source file into the destination.
def set_modified_time(self, path, mtime)
Sets the file modification and access times.
def get_environment_variables(self)
Returns currently available environment variables as a dictionary.
def file_should_not_be_empty(self, path, msg=None)
Fails if the specified directory is empty.
def _list_dir(self, path, pattern=None, absolute=False)
def run_and_return_rc_and_output(self, command)
Runs the given command in the system and returns the RC and output.
def run(self, command)
Runs the given command in the system and returns the output.
def file_should_be_empty(self, path, msg=None)
Fails unless the specified file is empty.
def should_exist(self, path, msg=None)
Fails unless the given path (file or directory) exists.
def list_files_in_directory(self, path, pattern=None, absolute=False)
Wrapper for List Directory that returns only files.
def environment_variable_should_not_be_set(self, name, msg=None)
Fails if the specified environment variable is set.
def log_environment_variables(self, level='INFO')
Logs all environment variables using the given log level.
def _list_files_in_dir(self, path, pattern=None, absolute=False)
def set_environment_variable(self, name, value)
Sets an environment variable to a specified value.
def normalize_path(self, path, case_normalize=False)
Normalizes the given path.
def move_files(self, *sources_and_destination)
Moves specified files to the target directory.
def join_paths(self, base, *paths)
Joins given paths with base and returns resulted paths.
def split_extension(self, path)
Splits the extension from the given path.
def append_to_environment_variable(self, name, *values, **config)
Appends given values to environment variable name.
def _list_dirs_in_dir(self, path, pattern=None, absolute=False)
def _are_source_and_destination_same_file(self, source, destination)
def get_file(self, path, encoding='UTF-8', encoding_errors='strict')
Returns the contents of a specified file.
def file_should_exist(self, path, msg=None)
Fails unless the given path points to an existing file.
def wait_until_created(self, path, timeout='1 minute')
Waits until the given file or directory is created.
def get_modified_time(self, path, format='timestamp')
Returns the last modification time of a file or directory.
def directory_should_not_be_empty(self, path, msg=None)
Fails if the specified directory is empty.
def copy_directory(self, source, destination)
Copies the source directory into the destination.
def count_items_in_directory(self, path, pattern=None)
Returns and logs the number of all items in the given directory.
def move_directory(self, source, destination)
Moves the source directory into a destination.
def run_and_return_rc(self, command)
Runs the given command in the system and returns the return code.
def remove_environment_variable(self, *names)
Deletes the specified environment variable.
def join_path(self, base, *parts)
Joins the given path part(s) to the given base path.
def append_to_file(self, path, content, encoding='UTF-8')
Appends the given content to the specified file.
def grep_file(self, path, pattern, encoding='UTF-8', encoding_errors='strict')
Returns the lines of the specified file that match the pattern.
def get_binary_file(self, path)
Returns the contents of a specified file.
def list_directory(self, path, pattern=None, absolute=False)
Returns and logs items in a directory, optionally filtered with pattern.
def directory_should_exist(self, path, msg=None)
Fails unless the given path points to an existing directory.
def create_file(self, path, content='', encoding='UTF-8')
Creates a file with the given content and encoding.
def list_directories_in_directory(self, path, pattern=None, absolute=False)
Wrapper for List Directory that returns only directories.
def directory_should_not_exist(self, path, msg=None)
Fails if the given path points to an existing file.
def empty_directory(self, path)
Deletes all the content from the given directory.
def remove_directory(self, path, recursive=False)
Removes the directory pointed to by the given path.
def split_path(self, path)
Splits the given path from the last path separator (/ or \\‍).
def _atomic_copy(self, source, destination)
Copy file atomically (or at least try to).
def count_directories_in_directory(self, path, pattern=None)
Wrapper for Count Items In Directory returning only directory count.
def _write_to_file(self, path, content, encoding=None, mode='w')
def copy_file(self, source, destination)
Copies the source file into the destination.
def count_files_in_directory(self, path, pattern=None)
Wrapper for Count Items In Directory returning only file count.
unicode
Exceptions and return codes used internally.
Definition: errors.py:24
def console_decode(string, encoding=CONSOLE_ENCODING, force=False)
Decodes bytes from console encoding to Unicode.
Definition: encoding.py:45
def seq2str(sequence, quote="'", sep=', ', lastsep=' and ')
Returns sequence in format ‘'item 1’, 'item 2' and 'item 3'`.
Definition: misc.py:115
def get_env_vars(upper=os.sep !='/')
Definition: robotenv.py:41
def set_env_var(name, value)
Definition: robotenv.py:30
def get_env_var(name, default=None)
Definition: robotenv.py:21
def abspath(path, case_normalize=False)
Replacement for os.path.abspath with some enhancements and bug fixes.
Definition: robotpath.py:87
def normpath(path, case_normalize=False)
Replacement for os.path.normpath with some enhancements.
Definition: robotpath.py:68
def secs_to_timestamp(secs, seps=None, millis=False)
Definition: robottime.py:309
def get_time(format='timestamp', time_=None)
Return the given or current time in requested format.
Definition: robottime.py:211
def secs_to_timestr(secs, compact=False)
Converts time in seconds to a string representation.
Definition: robottime.py:126
def parse_time(timestr)
Parses the time string and returns its value as seconds since epoch.
Definition: robottime.py:246
def timestr_to_secs(timestr, round_to=3)
Parses time like '1h 10s', '01:00:10' or '42' and returns seconds.
Definition: robottime.py:45
def is_truthy(item)
Returns True or False depending is the item considered true or not.
Definition: robottypes.py:49
def get_version(naked=False)
Definition: version.py:24