Esempio n. 1
0
  def Open(self, path, mode='r'):
    # type: (str, str) -> mylib.LineReader
    """Opens a path for read, but moves it out of the reserved 3-9 fd range.

    Returns:
      A Python file object.  The caller is responsible for Close().

    Raises:
      OSError if the path can't be found.
    """
    if mode == 'r':
      fd_mode = posix.O_RDONLY
    elif mode == 'w':
      fd_mode = posix.O_CREAT | posix.O_RDWR
    else:
      raise AssertionError(mode)

    fd = posix.open(path, fd_mode, 0o666)  # may raise OSError
    new_fd = self._GetFreeDescriptor()
    posix.dup2(fd, new_fd)
    posix.close(fd)
    try:
      f = posix.fdopen(new_fd, mode)  # Might raise IOError
    except IOError as e:
      raise OSError(*e.args)  # Consistently raise OSError
    return f
    def Open(self, path, mode='r'):
        # type: (str, str) -> mylib.LineReader
        """Opens a path for read, but moves it out of the reserved 3-9 fd range.

    Returns:
      A Python file object.  The caller is responsible for Close().

    Raises:
      OSError if the path can't be found.
    """
        if mode == 'r':
            fd_mode = posix.O_RDONLY
        elif mode == 'w':
            fd_mode = posix.O_CREAT | posix.O_RDWR
        else:
            raise AssertionError(mode)

        fd = posix.open(path, fd_mode, 0o666)  # may raise OSError

        # Immediately move it to a new location
        new_fd = fcntl.fcntl(fd, fcntl.F_DUPFD, _SHELL_MIN_FD)
        posix.close(fd)

        # Return a Python file handle
        try:
            f = posix.fdopen(new_fd, mode)  # Might raise IOError
        except IOError as e:
            raise OSError(*e.args)  # Consistently raise OSError
        return f
Esempio n. 3
0
    def _Open(self, path, c_mode, fd_mode):
        # type: (str, str, int) -> mylib.LineReader
        fd = posix.open(path, fd_mode, 0o666)  # may raise OSError

        # Immediately move it to a new location
        new_fd = fcntl_.fcntl(fd, fcntl_.F_DUPFD, _SHELL_MIN_FD)  # type: int
        posix.close(fd)

        # Return a Python file handle
        # Might raise IOError.  Python-induced wart: we have to handle BOTH IOError
        # and OSError at higher levels.
        f = posix.fdopen(new_fd, c_mode)
        return f
Esempio n. 4
0
    def _Open(self, path, c_mode, fd_mode):
        # type: (str, str, int) -> mylib.LineReader
        fd = posix.open(path, fd_mode, 0o666)  # may raise OSError

        # Immediately move it to a new location
        new_fd = fcntl.fcntl(fd, fcntl.F_DUPFD, _SHELL_MIN_FD)
        posix.close(fd)

        # Return a Python file handle
        try:
            f = posix.fdopen(new_fd, c_mode)  # Might raise IOError
        except IOError as e:
            raise OSError(*e.args)  # Consistently raise OSError
        return f
Esempio n. 5
0
    def testPrint(self):
        # Conclusion: print CAN raise IOError with EINTR.

        if posix_.environ.get('EINTR_TEST'):

            signal.signal(signal.SIGTERM, _Handler)
            r, w = posix_.pipe()
            log('Hanging on write in pid %d', posix_.getpid())
            f = posix_.fdopen(w, 'w')

            # 1 byte bigger than pipe size
            print('x' * 65537, file=f)
            log('1: done')

            # write returns early when a signal interrupts it, and we read at least
            # one byte!  We do NOT get EINTR>

            # On the second try, it didn't write anything, and we get EINTR!

            log('Second try (pid %d)', posix_.getpid())
            print('x' * 65537, file=f)
            log('2: done')
Esempio n. 6
0
                     args.Int,
                     default=2,
                     help='Indent JSON by this amount')

JSON_READ_SPEC = flag_spec.OilFlags('json-read')
# yajl has this option
JSON_READ_SPEC.Flag('-validate',
                    args.Bool,
                    default=True,
                    help='Validate UTF-8')

_JSON_ACTION_ERROR = "builtin expects 'read' or 'write'"

# global file object that can be passed to yajl.load(), and that also can be
# used with redirects.  See comment below.
_STDIN = posix.fdopen(0)


class Json(vm._Builtin):
    """Json I/O.

  -indent pretty prints it.  Is the default indent 2?  -pretty=0 can turn it
  off.

  json echo :myobj

  json echo -indent 2 :myobj :other_obj {
    x = 1
    d = {name: 'andy'}
  }
Esempio n. 7
0
    def __call__(self, cmd_val):
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        arg_r.Next()  # skip 'json'

        action, action_spid = arg_r.Peek2()
        if action is None:
            raise args.UsageError(_JSON_ACTION_ERROR)
        arg_r.Next()

        if action == 'write':
            arg, _ = JSON_WRITE_SPEC.Parse(arg_r)

            # GetVar() of each name and print it.

            for var_name in arg_r.Rest():
                if var_name.startswith(':'):
                    var_name = var_name[1:]

                val = self.mem.GetVar(var_name)
                with tagswitch(val) as case:
                    if case(value_e.Undef):
                        # TODO: blame the right span_id
                        self.errfmt.Print("no variable named %r is defined",
                                          var_name)
                        return 1
                    elif case(value_e.Str):
                        obj = val.s
                    elif case(value_e.MaybeStrArray):
                        obj = val.strs
                    elif case(value_e.AssocArray):
                        obj = val.d
                    elif case(value_e.Obj):
                        obj = val.obj
                    else:
                        raise AssertionError(val)

                if arg.pretty:
                    indent = arg.indent
                    extra_newline = False
                else:
                    # How yajl works: if indent is -1, then everything is on one line.
                    indent = -1
                    extra_newline = True

                j = yajl.dump(obj, sys.stdout, indent=indent)
                if extra_newline:
                    sys.stdout.write('\n')

            # TODO: Accept a block.  They aren't hooked up yet.
            if cmd_val.block:
                # TODO: flatten value.{Str,Obj} into a flat dict?
                namespace = self.ex.EvalBlock(cmd_val.block)

                print(yajl.dump(namespace))

        elif action == 'read':
            arg, _ = JSON_READ_SPEC.Parse(arg_r)
            # TODO:
            # Respect -validate=F

            var_name, name_spid = arg_r.ReadRequired2("expected variable name")
            if var_name.startswith(':'):
                var_name = var_name[1:]

            if not match.IsValidVarName(var_name):
                raise args.UsageError('got invalid variable name %r' %
                                      var_name,
                                      span_id=name_spid)

            # Have to use this over sys.stdin because of redirects
            # TODO: change binding to yajl.readfd() ?
            stdin = posix_.fdopen(0)
            try:
                obj = yajl.load(stdin)
            except ValueError as e:
                self.errfmt.Print('json read: %s', e, span_id=action_spid)
                return 1

            self.mem.SetVar(sh_lhs_expr.Name(var_name), value.Obj(obj), (),
                            scope_e.LocalOnly)

        else:
            raise args.UsageError(_JSON_ACTION_ERROR, span_id=action_spid)

        return 0