From e88cd47f31f3e226bae8602c6ae48269bf531a31 Mon Sep 17 00:00:00 2001 From: Yang Yu Date: Mon, 16 Jan 2023 14:44:09 +0800 Subject: [PATCH 1/3] Add os.listdir --- stdlib/os/os.go | 57 ++++++++++++++++++++++++++++++ stdlib/os/testdata/test.py | 2 ++ stdlib/os/testdata/test_golden.txt | 2 ++ 3 files changed, 61 insertions(+) diff --git a/stdlib/os/os.go b/stdlib/os/os.go index f63586ce..cbe2ebca 100644 --- a/stdlib/os/os.go +++ b/stdlib/os/os.go @@ -61,6 +61,7 @@ func init() { py.MustNewMethod("rmdir", rmdir, 0, rmdir_doc), py.MustNewMethod("system", system, 0, "Run shell commands, prints stdout directly to default"), py.MustNewMethod("unsetenv", unsetenv, 0, "Unset (delete) the environment variable named key."), + py.MustNewMethod("listdir", listDir, 0, listDir_doc), } globals := py.StringDict{ "error": py.OSError, @@ -517,3 +518,59 @@ func system(self py.Object, args py.Tuple) (py.Object, error) { return py.Int(0), nil } + +const listDir_doc = ` +Return a list containing the names of the files in the directory. + +path can be specified as either str, bytes. If path is bytes, the filenames + returned will also be bytes; in all other circumstances + the filenames returned will be str. +If path is None, uses the path='.'. + +The list is in arbitrary order. It does not include the special +entries '.' and '..' even if they are present in the directory. +` + +func listDir(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Object, error) { + var ( + path py.Object = py.None + ) + err := py.ParseTupleAndKeywords(args, kwargs, "s:listdir", []string{"path"}, &path) + if err != nil { + return nil, err + } + + if path == py.None { + cwd, err := os.Getwd() + if err != nil { + return nil, py.ExceptionNewf(py.OSError, "cannot get cwd, error %s", err.Error()) + } + path = py.String(cwd) + } + + dirName := "" + returnsBytes := false + switch v := path.(type) { + case py.String: + dirName = string(v) + case py.Bytes: + dirName = string(v) + returnsBytes = true + default: + return nil, py.ExceptionNewf(py.TypeError, "str or bytes expected, not %T", path) + } + + dirEntries, err := os.ReadDir(dirName) + if err != nil { + return nil, py.ExceptionNewf(py.OSError, "cannot read directory %s, error %s", dirName, err.Error()) + } + result := py.NewListSized(len(dirEntries)) + for i, dirEntry := range dirEntries { + if returnsBytes { + result.Items[i] = py.Bytes(dirEntry.Name()) + } else { + result.Items[i] = py.String(dirEntry.Name()) + } + } + return result, nil +} diff --git a/stdlib/os/testdata/test.py b/stdlib/os/testdata/test.py index bbdf8b69..f36507ae 100644 --- a/stdlib/os/testdata/test.py +++ b/stdlib/os/testdata/test.py @@ -151,6 +151,7 @@ os.mkdir(dir1) os.mkdir(dir2) os.mkdir(dir11) + print(os.listdir(top)) os.removedirs(dir1) try: os.mkdir(dir11) @@ -181,6 +182,7 @@ print("INVALID error caught: %s" % e) os.remove(fname) os.rmdir(dir2) + print(os.listdir(top)) except Exception as e: print("could not create/remove directories: %s" % e) finally: diff --git a/stdlib/os/testdata/test_golden.txt b/stdlib/os/testdata/test_golden.txt index 4a0f640a..d93b505b 100644 --- a/stdlib/os/testdata/test_golden.txt +++ b/stdlib/os/testdata/test_golden.txt @@ -25,8 +25,10 @@ os.linesep: [OK] os.devnull: [OK] os.altsep: [OK] caught: OSError: 'Bad file descriptor' [OK] +['dir1', 'dir2'] caught: SystemError - no such file or directory [OK] caught: FileExistsError [OK] caught: SystemError - directory not empty [OK] +['dir1'] os.{mkdir,rmdir,remove,removedirs} worked as expected OK From f766f9d49af202a17e19e1653d343a59547d693b Mon Sep 17 00:00:00 2001 From: Yang Yu Date: Mon, 16 Jan 2023 19:40:09 +0800 Subject: [PATCH 2/3] Follow comments and fix bugs --- stdlib/os/os.go | 114 ++++++++++++++--------------- stdlib/os/testdata/test.py | 6 +- stdlib/os/testdata/test_golden.txt | 1 + 3 files changed, 63 insertions(+), 58 deletions(-) diff --git a/stdlib/os/os.go b/stdlib/os/os.go index cbe2ebca..a4240a6e 100644 --- a/stdlib/os/os.go +++ b/stdlib/os/os.go @@ -53,6 +53,7 @@ func init() { py.MustNewMethod("chdir", chdir, 0, "Change the current working directory"), py.MustNewMethod("getenv", getenv, 0, "Return the value of the environment variable key if it exists, or default if it doesn’t. key, default and the result are str."), py.MustNewMethod("getpid", getpid, 0, "Return the current process id."), + py.MustNewMethod("listdir", listDir, 0, listDir_doc), py.MustNewMethod("makedirs", makedirs, 0, makedirs_doc), py.MustNewMethod("mkdir", mkdir, 0, mkdir_doc), py.MustNewMethod("putenv", putenv, 0, "Set the environment variable named key to the string value."), @@ -61,7 +62,6 @@ func init() { py.MustNewMethod("rmdir", rmdir, 0, rmdir_doc), py.MustNewMethod("system", system, 0, "Run shell commands, prints stdout directly to default"), py.MustNewMethod("unsetenv", unsetenv, 0, "Unset (delete) the environment variable named key."), - py.MustNewMethod("listdir", listDir, 0, listDir_doc), } globals := py.StringDict{ "error": py.OSError, @@ -235,6 +235,62 @@ func getpid(self py.Object, args py.Tuple) (py.Object, error) { return py.Int(os.Getpid()), nil } +const listDir_doc = ` +Return a list containing the names of the files in the directory. + +path can be specified as either str, bytes. If path is bytes, the filenames + returned will also be bytes; in all other circumstances + the filenames returned will be str. +If path is None, uses the path='.'. + +The list is in arbitrary order. It does not include the special +entries '.' and '..' even if they are present in the directory. +` + +func listDir(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Object, error) { + var ( + path py.Object = py.None + ) + err := py.ParseTupleAndKeywords(args, kwargs, "|O:listdir", []string{"path"}, &path) + if err != nil { + return nil, err + } + + if path == py.None { + cwd, err := os.Getwd() + if err != nil { + return nil, py.ExceptionNewf(py.OSError, "cannot get cwd, error %s", err.Error()) + } + path = py.String(cwd) + } + + dirName := "" + returnsBytes := false + switch v := path.(type) { + case py.String: + dirName = string(v) + case py.Bytes: + dirName = string(v) + returnsBytes = true + default: + return nil, py.ExceptionNewf(py.TypeError, "str or bytes expected, not %T", path) + } + + dirEntries, err := os.ReadDir(dirName) + if err != nil { + return nil, py.ExceptionNewf(py.OSError, "cannot read directory %s, error %s", dirName, err.Error()) + } + result := py.NewListSized(len(dirEntries)) + for i, dirEntry := range dirEntries { + if returnsBytes { + result.Items[i] = py.Bytes(dirEntry.Name()) + } else { + result.Items[i] = py.String(dirEntry.Name()) + } + } + return result, nil +} + const makedirs_doc = `makedirs(name [, mode=0o777][, exist_ok=False]) Super-mkdir; create a leaf directory and all intermediate ones. Works like @@ -518,59 +574,3 @@ func system(self py.Object, args py.Tuple) (py.Object, error) { return py.Int(0), nil } - -const listDir_doc = ` -Return a list containing the names of the files in the directory. - -path can be specified as either str, bytes. If path is bytes, the filenames - returned will also be bytes; in all other circumstances - the filenames returned will be str. -If path is None, uses the path='.'. - -The list is in arbitrary order. It does not include the special -entries '.' and '..' even if they are present in the directory. -` - -func listDir(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Object, error) { - var ( - path py.Object = py.None - ) - err := py.ParseTupleAndKeywords(args, kwargs, "s:listdir", []string{"path"}, &path) - if err != nil { - return nil, err - } - - if path == py.None { - cwd, err := os.Getwd() - if err != nil { - return nil, py.ExceptionNewf(py.OSError, "cannot get cwd, error %s", err.Error()) - } - path = py.String(cwd) - } - - dirName := "" - returnsBytes := false - switch v := path.(type) { - case py.String: - dirName = string(v) - case py.Bytes: - dirName = string(v) - returnsBytes = true - default: - return nil, py.ExceptionNewf(py.TypeError, "str or bytes expected, not %T", path) - } - - dirEntries, err := os.ReadDir(dirName) - if err != nil { - return nil, py.ExceptionNewf(py.OSError, "cannot read directory %s, error %s", dirName, err.Error()) - } - result := py.NewListSized(len(dirEntries)) - for i, dirEntry := range dirEntries { - if returnsBytes { - result.Items[i] = py.Bytes(dirEntry.Name()) - } else { - result.Items[i] = py.String(dirEntry.Name()) - } - } - return result, nil -} diff --git a/stdlib/os/testdata/test.py b/stdlib/os/testdata/test.py index f36507ae..7b5b6815 100644 --- a/stdlib/os/testdata/test.py +++ b/stdlib/os/testdata/test.py @@ -151,7 +151,11 @@ os.mkdir(dir1) os.mkdir(dir2) os.mkdir(dir11) - print(os.listdir(top)) + print(os.listdir(bytes(top, "utf-8"))) + orig = os.getcwd() + os.chdir(top) + print(os.listdir()) + os.chdir(orig) os.removedirs(dir1) try: os.mkdir(dir11) diff --git a/stdlib/os/testdata/test_golden.txt b/stdlib/os/testdata/test_golden.txt index d93b505b..fd5fc39b 100644 --- a/stdlib/os/testdata/test_golden.txt +++ b/stdlib/os/testdata/test_golden.txt @@ -25,6 +25,7 @@ os.linesep: [OK] os.devnull: [OK] os.altsep: [OK] caught: OSError: 'Bad file descriptor' [OK] +[b'dir1', b'dir2'] ['dir1', 'dir2'] caught: SystemError - no such file or directory [OK] caught: FileExistsError [OK] From 41b8ddffff5905c51d8fa302832d74e0d32bd256 Mon Sep 17 00:00:00 2001 From: Yang Yu Date: Mon, 16 Jan 2023 19:43:01 +0800 Subject: [PATCH 3/3] Use z* instead of O --- stdlib/os/os.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/os/os.go b/stdlib/os/os.go index a4240a6e..c37fce19 100644 --- a/stdlib/os/os.go +++ b/stdlib/os/os.go @@ -251,7 +251,7 @@ func listDir(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Object, er var ( path py.Object = py.None ) - err := py.ParseTupleAndKeywords(args, kwargs, "|O:listdir", []string{"path"}, &path) + err := py.ParseTupleAndKeywords(args, kwargs, "|z*:listdir", []string{"path"}, &path) if err != nil { return nil, err }