This is an automated email from the ASF dual-hosted git repository.

bkietz pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new fd75cbdb38 GH-40342: [C++] move LocalFileSystem to the registry 
(#40356)
fd75cbdb38 is described below

commit fd75cbdb38836b66dbae81094cf06821e5d25cb1
Author: Benjamin Kietzman <[email protected]>
AuthorDate: Wed Apr 24 10:27:17 2024 -0400

    GH-40342: [C++] move LocalFileSystem to the registry (#40356)
    
    ### Rationale for this change
    
    Moving LocalFileSystem into the registry is a good first usage and will 
help us hammer out which aspects of built in file systems should remain public.
    
    ### What changes are included in this PR?
    
    A factory for LocalFileSystem is added to the registry. 
`FileSystem::MakeUri` ( https://github.com/apache/arrow/issues/18316 ) is added 
to enable roundtripping filesystems through URIs. `file://` URIs now support a 
use_mmap query parameter, and `local://` URIs are also supported as an alias.
    
    <h6 id="reduce">Reducing the set of bound classes</h6>
    
    Some unnecessary bindings to the LocalFileSystem concrete class are 
removed. This demonstrates that with a registered factory pattern, it is no 
longer necessary to keep a class hierarchy public for binding. Eventually (if 
desired), we can move concrete subclasses of FileSystem entirely out of public 
headers.
    
    ### Are these changes tested?
    
    Yes, all existing tests for file:// URIs continue to pass
    
    ### Are there any user-facing changes?
    
    For consistency, local:// URIs will now be considered equivalent to 
corresponding file:// URIs
    
    * GitHub Issue: #40342
    
    Authored-by: Benjamin Kietzman <[email protected]>
    Signed-off-by: Benjamin Kietzman <[email protected]>
---
 .../arrow/filesystem_definition_example.cc         |  4 +--
 cpp/src/arrow/filesystem/CMakeLists.txt            |  4 ++-
 cpp/src/arrow/filesystem/filesystem.cc             | 35 ++++++++++----------
 cpp/src/arrow/filesystem/filesystem.h              | 30 ++++++++++++++++--
 cpp/src/arrow/filesystem/localfs.cc                | 37 ++++++++++++++++++++--
 cpp/src/arrow/filesystem/localfs.h                 |  1 +
 cpp/src/arrow/filesystem/localfs_test.cc           | 29 ++++++++++-------
 cpp/src/arrow/testing/examplefs.cc                 |  4 +--
 docs/source/cpp/io.rst                             |  7 ++--
 python/pyarrow/_fs.pxd                             |  3 --
 python/pyarrow/_fs.pyx                             | 34 ++++++++------------
 python/pyarrow/includes/libarrow_fs.pxd            | 16 ++--------
 r/R/arrowExports.R                                 |  4 ---
 r/R/filesystem.R                                   |  3 +-
 r/src/arrowExports.cpp                             |  8 -----
 r/src/filesystem.cpp                               | 14 +++-----
 16 files changed, 130 insertions(+), 103 deletions(-)

diff --git a/cpp/examples/arrow/filesystem_definition_example.cc 
b/cpp/examples/arrow/filesystem_definition_example.cc
index efe1bd1047..65301bb843 100644
--- a/cpp/examples/arrow/filesystem_definition_example.cc
+++ b/cpp/examples/arrow/filesystem_definition_example.cc
@@ -138,7 +138,7 @@ class ExampleFileSystem : public fs::FileSystem {
   }
 };
 
-fs::FileSystemRegistrar kExampleFileSystemModule{
+auto kExampleFileSystemModule = ARROW_REGISTER_FILESYSTEM(
     "example",
     [](const arrow::util::Uri& uri, const io::IOContext& io_context,
        std::string* out_path) -> Result<std::shared_ptr<fs::FileSystem>> {
@@ -148,4 +148,4 @@ fs::FileSystemRegistrar kExampleFileSystemModule{
       }
       return fs;
     },
-};
+    {});
diff --git a/cpp/src/arrow/filesystem/CMakeLists.txt 
b/cpp/src/arrow/filesystem/CMakeLists.txt
index deac04af72..0a31a64b7a 100644
--- a/cpp/src/arrow/filesystem/CMakeLists.txt
+++ b/cpp/src/arrow/filesystem/CMakeLists.txt
@@ -28,7 +28,9 @@ add_arrow_test(filesystem-test
                EXTRA_LABELS
                filesystem
                DEFINITIONS
-               
ARROW_FILESYSTEM_EXAMPLE_LIBPATH="$<TARGET_FILE:arrow_filesystem_example>")
+               
ARROW_FILESYSTEM_EXAMPLE_LIBPATH="$<TARGET_FILE:arrow_filesystem_example>"
+               EXTRA_DEPENDENCIES
+               arrow_filesystem_example)
 
 if(ARROW_BUILD_BENCHMARKS)
   add_arrow_benchmark(localfs_benchmark
diff --git a/cpp/src/arrow/filesystem/filesystem.cc 
b/cpp/src/arrow/filesystem/filesystem.cc
index c96a5fd2cf..b79af08385 100644
--- a/cpp/src/arrow/filesystem/filesystem.cc
+++ b/cpp/src/arrow/filesystem/filesystem.cc
@@ -56,16 +56,13 @@
 #include "arrow/util/visibility.h"
 #include "arrow/util/windows_fixup.h"
 
-namespace arrow {
-
-using internal::checked_pointer_cast;
-using internal::TaskHints;
-using io::internal::SubmitIO;
-using util::Uri;
-
-namespace fs {
+namespace arrow::fs {
 
+using arrow::internal::checked_pointer_cast;
 using arrow::internal::GetEnvVar;
+using arrow::internal::TaskHints;
+using arrow::io::internal::SubmitIO;
+using arrow::util::Uri;
 using internal::ConcatAbstractPath;
 using internal::EnsureTrailingSlash;
 using internal::GetAbstractPathParent;
@@ -273,6 +270,11 @@ Result<std::string> FileSystem::PathFromUri(const 
std::string& uri_string) const
   return Status::NotImplemented("PathFromUri is not yet supported on this 
filesystem");
 }
 
+Result<std::string> FileSystem::MakeUri(std::string path) const {
+  return Status::NotImplemented("MakeUri is not yet supported for ", 
type_name(),
+                                " filesystems");
+}
+
 //////////////////////////////////////////////////////////////////////////
 // SubTreeFileSystem implementation
 
@@ -726,6 +728,10 @@ class FileSystemFactoryRegistry {
           main_registry->scheme_to_factory_.emplace(std::move(scheme), 
registered);
       if (success) continue;
 
+      if (it->second.ok()) {
+        if (registered->factory == it->second->factory) continue;
+      }
+
       duplicated_schemes.emplace_back(it->first);
     }
     scheme_to_factory_.clear();
@@ -852,18 +858,10 @@ Result<std::shared_ptr<FileSystem>> 
FileSystemFromUriReal(const Uri& uri,
         auto* factory,
         FileSystemFactoryRegistry::GetInstance()->FactoryForScheme(scheme));
     if (factory != nullptr) {
-      return (*factory)(uri, io_context, out_path);
+      return factory->function(uri, io_context, out_path);
     }
   }
 
-  if (scheme == "file") {
-    std::string path;
-    ARROW_ASSIGN_OR_RAISE(auto options, LocalFileSystemOptions::FromUri(uri, 
&path));
-    if (out_path != nullptr) {
-      *out_path = path;
-    }
-    return std::make_shared<LocalFileSystem>(options, io_context);
-  }
   if (scheme == "abfs" || scheme == "abfss") {
 #ifdef ARROW_AZURE
     ARROW_ASSIGN_OR_RAISE(auto options, AzureOptions::FromUri(uri, out_path));
@@ -969,5 +967,4 @@ Status Initialize(const FileSystemGlobalOptions& options) {
   return Status::OK();
 }
 
-}  // namespace fs
-}  // namespace arrow
+}  // namespace arrow::fs
diff --git a/cpp/src/arrow/filesystem/filesystem.h 
b/cpp/src/arrow/filesystem/filesystem.h
index 272e42256a..d4f62f86a7 100644
--- a/cpp/src/arrow/filesystem/filesystem.h
+++ b/cpp/src/arrow/filesystem/filesystem.h
@@ -197,6 +197,11 @@ class ARROW_EXPORT FileSystem
   /// \return The path inside the filesystem that is indicated by the URI.
   virtual Result<std::string> PathFromUri(const std::string& uri_string) const;
 
+  /// \brief Make a URI from which FileSystemFromUri produces an equivalent 
filesystem
+  /// \param path The path component to use in the resulting URI
+  /// \return A URI string, or an error if an equivalent URI cannot be produced
+  virtual Result<std::string> MakeUri(std::string path) const;
+
   virtual bool Equals(const FileSystem& other) const = 0;
 
   virtual bool Equals(const std::shared_ptr<FileSystem>& other) const {
@@ -352,8 +357,23 @@ class ARROW_EXPORT FileSystem
   bool default_async_is_sync_ = true;
 };
 
-using FileSystemFactory = std::function<Result<std::shared_ptr<FileSystem>>(
-    const Uri& uri, const io::IOContext& io_context, std::string* out_path)>;
+struct FileSystemFactory {
+  std::function<Result<std::shared_ptr<FileSystem>>(
+      const Uri& uri, const io::IOContext& io_context, std::string* out_path)>
+      function;
+  std::string_view file;
+  int line;
+
+  bool operator==(const FileSystemFactory& other) const {
+    // In the case where libarrow is linked statically both to the executable 
and to a
+    // dynamically loaded filesystem implementation library, the library 
contains a
+    // duplicate definition of the registry and duplicate definitions of any
+    // FileSystemRegistrars which are statically linked to libarrow. When 
retrieving
+    // factories from the filesystem implementation library, we use the file 
and line
+    // of the registrar's definition to determine equivalence of the duplicate 
factories.
+    return file == other.file && line == other.line;
+  }
+};
 
 /// \brief A FileSystem implementation that delegates to another
 /// implementation after prepending a fixed base path.
@@ -645,6 +665,12 @@ struct ARROW_EXPORT FileSystemRegistrar {
                       std::function<void()> finalizer = {});
 };
 
+#define ARROW_REGISTER_FILESYSTEM(scheme, factory_function, finalizer)         
   \
+  ::arrow::fs::FileSystemRegistrar {                                           
   \
+    scheme, ::arrow::fs::FileSystemFactory{factory_function, __FILE__, 
__LINE__}, \
+        finalizer                                                              
   \
+  }
+
 /// @}
 
 namespace internal {
diff --git a/cpp/src/arrow/filesystem/localfs.cc 
b/cpp/src/arrow/filesystem/localfs.cc
index fbb33fd008..25ac04b758 100644
--- a/cpp/src/arrow/filesystem/localfs.cc
+++ b/cpp/src/arrow/filesystem/localfs.cc
@@ -39,6 +39,7 @@
 #include "arrow/io/type_fwd.h"
 #include "arrow/util/async_generator.h"
 #include "arrow/util/io_util.h"
+#include "arrow/util/string.h"
 #include "arrow/util/uri.h"
 #include "arrow/util/windows_fixup.h"
 
@@ -246,8 +247,20 @@ Result<LocalFileSystemOptions> 
LocalFileSystemOptions::FromUri(
         std::string(internal::RemoveTrailingSlash(uri.path(), 
/*preserve_root=*/true));
   }
 
-  // TODO handle use_mmap option
-  return LocalFileSystemOptions();
+  LocalFileSystemOptions options;
+  ARROW_ASSIGN_OR_RAISE(auto params, uri.query_items());
+  for (const auto& [key, value] : params) {
+    if (key == "use_mmap") {
+      if (value.empty()) {
+        options.use_mmap = true;
+        continue;
+      } else {
+        ARROW_ASSIGN_OR_RAISE(options.use_mmap, 
::arrow::internal::ParseBoolean(value));
+      }
+      break;
+    }
+  }
+  return options;
 }
 
 LocalFileSystem::LocalFileSystem(const io::IOContext& io_context)
@@ -273,6 +286,11 @@ Result<std::string> LocalFileSystem::PathFromUri(const 
std::string& uri_string)
                                      authority_handling);
 }
 
+Result<std::string> LocalFileSystem::MakeUri(std::string path) const {
+  ARROW_ASSIGN_OR_RAISE(path, DoNormalizePath(std::move(path)));
+  return "file://" + path + (options_.use_mmap ? "?use_mmap" : "");
+}
+
 bool LocalFileSystem::Equals(const FileSystem& other) const {
   if (other.type_name() != type_name()) {
     return false;
@@ -686,4 +704,19 @@ Result<std::shared_ptr<io::OutputStream>> 
LocalFileSystem::OpenAppendStream(
   return OpenOutputStreamGeneric(path, truncate, append);
 }
 
+static Result<std::shared_ptr<fs::FileSystem>> LocalFileSystemFactory(
+    const arrow::util::Uri& uri, const io::IOContext& io_context, std::string* 
out_path) {
+  std::string path;
+  ARROW_ASSIGN_OR_RAISE(auto options, LocalFileSystemOptions::FromUri(uri, 
&path));
+  if (out_path != nullptr) {
+    *out_path = std::move(path);
+  }
+  return std::make_shared<LocalFileSystem>(options, io_context);
+}
+
+FileSystemRegistrar kLocalFileSystemModule[]{
+    ARROW_REGISTER_FILESYSTEM("file", LocalFileSystemFactory, {}),
+    ARROW_REGISTER_FILESYSTEM("local", LocalFileSystemFactory, {}),
+};
+
 }  // namespace arrow::fs
diff --git a/cpp/src/arrow/filesystem/localfs.h 
b/cpp/src/arrow/filesystem/localfs.h
index 45a3da317f..d72e8f7d74 100644
--- a/cpp/src/arrow/filesystem/localfs.h
+++ b/cpp/src/arrow/filesystem/localfs.h
@@ -83,6 +83,7 @@ class ARROW_EXPORT LocalFileSystem : public FileSystem {
 
   Result<std::string> NormalizePath(std::string path) override;
   Result<std::string> PathFromUri(const std::string& uri_string) const 
override;
+  Result<std::string> MakeUri(std::string path) const override;
 
   bool Equals(const FileSystem& other) const override;
 
diff --git a/cpp/src/arrow/filesystem/localfs_test.cc 
b/cpp/src/arrow/filesystem/localfs_test.cc
index b76c7ebad4..1a20e44bc3 100644
--- a/cpp/src/arrow/filesystem/localfs_test.cc
+++ b/cpp/src/arrow/filesystem/localfs_test.cc
@@ -15,8 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#include <cerrno>
-#include <chrono>
 #include <memory>
 #include <sstream>
 #include <string>
@@ -113,10 +111,8 @@ Result<std::shared_ptr<FileSystem>> 
SlowFileSystemFactory(const Uri& uri,
   }
   return std::make_shared<SlowFileSystemPublicProps>(base_fs, average_latency, 
seed);
 }
-FileSystemRegistrar kSlowFileSystemModule{
-    "slowfile",
-    SlowFileSystemFactory,
-};
+auto kSlowFileSystemModule =
+    ARROW_REGISTER_FILESYSTEM("slowfile", SlowFileSystemFactory, {});
 
 TEST(FileSystemFromUri, LinkedRegisteredFactory) {
   // Since the registrar's definition is in this translation unit (which is 
linked to the
@@ -158,23 +154,24 @@ TEST(FileSystemFromUri, RuntimeRegisteredFactory) {
   EXPECT_THAT(FileSystemFromUri("slowfile2:///hey/yo", &path),
               Raises(StatusCode::Invalid));
 
-  EXPECT_THAT(RegisterFileSystemFactory("slowfile2", SlowFileSystemFactory), 
Ok());
+  EXPECT_THAT(RegisterFileSystemFactory("slowfile2", {SlowFileSystemFactory, 
"", 0}),
+              Ok());
 
   ASSERT_OK_AND_ASSIGN(auto fs, FileSystemFromUri("slowfile2:///hey/yo", 
&path));
   EXPECT_EQ(path, "/hey/yo");
   EXPECT_EQ(fs->type_name(), "slow");
 
   EXPECT_THAT(
-      RegisterFileSystemFactory("slowfile2", SlowFileSystemFactory),
+      RegisterFileSystemFactory("slowfile2", {SlowFileSystemFactory, "", 0}),
       Raises(StatusCode::KeyError,
              testing::HasSubstr("Attempted to register factory for scheme 
'slowfile2' "
                                 "but that scheme is already registered")));
 }
 
 FileSystemRegistrar kSegfaultFileSystemModule[]{
-    {"segfault", nullptr},
-    {"segfault", nullptr},
-    {"segfault", nullptr},
+    ARROW_REGISTER_FILESYSTEM("segfault", nullptr, {}),
+    ARROW_REGISTER_FILESYSTEM("segfault", nullptr, {}),
+    ARROW_REGISTER_FILESYSTEM("segfault", nullptr, {}),
 };
 TEST(FileSystemFromUri, LinkedRegisteredFactoryNameCollision) {
   // Since multiple registrars are defined in this translation unit which all
@@ -312,6 +309,7 @@ class TestLocalFS : public LocalFSTestMixin {
     std::string path;
     ASSERT_OK_AND_ASSIGN(fs_, fs_from_uri(uri, &path));
     ASSERT_EQ(fs_->type_name(), "local");
+    local_fs_ = ::arrow::internal::checked_pointer_cast<LocalFileSystem>(fs_);
     ASSERT_EQ(path, expected_path);
     ASSERT_OK_AND_ASSIGN(path, fs_->PathFromUri(uri));
     ASSERT_EQ(path, expected_path);
@@ -423,8 +421,17 @@ TYPED_TEST(TestLocalFS, FileSystemFromUriFile) {
 
   // Variations
   this->TestLocalUri("file:/foo/bar", "/foo/bar");
+  ASSERT_FALSE(this->local_fs_->options().use_mmap);
   this->TestLocalUri("file:///foo/bar", "/foo/bar");
   this->TestLocalUri("file:///some%20path/%25percent", "/some path/%percent");
+
+  this->TestLocalUri("file:///_?use_mmap", "/_");
+  if (this->path_formatter_.supports_uri()) {
+    ASSERT_TRUE(this->local_fs_->options().use_mmap);
+    ASSERT_OK_AND_ASSIGN(auto uri, this->fs_->MakeUri("/_"));
+    EXPECT_EQ(uri, "file:///_?use_mmap");
+  }
+
 #ifdef _WIN32
   this->TestLocalUri("file:/C:/foo/bar", "C:/foo/bar");
   this->TestLocalUri("file:///C:/foo/bar", "C:/foo/bar");
diff --git a/cpp/src/arrow/testing/examplefs.cc 
b/cpp/src/arrow/testing/examplefs.cc
index d3e7e3b03f..5c9d5f9d90 100644
--- a/cpp/src/arrow/testing/examplefs.cc
+++ b/cpp/src/arrow/testing/examplefs.cc
@@ -24,7 +24,7 @@
 
 namespace arrow::fs {
 
-FileSystemRegistrar kExampleFileSystemModule{
+auto kExampleFileSystemModule = ARROW_REGISTER_FILESYSTEM(
     "example",
     [](const Uri& uri, const io::IOContext& io_context,
        std::string* out_path) -> Result<std::shared_ptr<FileSystem>> {
@@ -33,6 +33,6 @@ FileSystemRegistrar kExampleFileSystemModule{
       auto local_uri = "file" + uri.ToString().substr(kScheme.size());
       return FileSystemFromUri(local_uri, io_context, out_path);
     },
-};
+    {});
 
 }  // namespace arrow::fs
diff --git a/docs/source/cpp/io.rst b/docs/source/cpp/io.rst
index 2a05473852..2312132b1a 100644
--- a/docs/source/cpp/io.rst
+++ b/docs/source/cpp/io.rst
@@ -116,15 +116,15 @@ scope, which will register a factory whenever the 
instance is loaded:
 
 .. code-block:: cpp
 
-    arrow::fs::FileSystemRegistrar kExampleFileSystemModule{
+    auto kExampleFileSystemModule = ARROW_REGISTER_FILESYSTEM(
       "example",
       [](const Uri& uri, const io::IOContext& io_context,
           std::string* out_path) -> 
Result<std::shared_ptr<arrow::fs::FileSystem>> {
         EnsureExampleFileSystemInitialized();
         return std::make_shared<ExampleFileSystem>();
       },
-      &EnsureExampleFileSystemFinalized,
-    };
+      &EnsureExampleFileSystemFinalized
+    );
 
 If a filesystem implementation requires initialization before any instances
 may be constructed, this should be included in the corresponding factory or
@@ -144,4 +144,3 @@ should have exactly one of its sources
 ``#include "arrow/filesystem/filesystem_library.h"``
 in order to ensure the presence of the symbol on which
 :func:`~arrow::fs::LoadFileSystemFactories` depends.
-
diff --git a/python/pyarrow/_fs.pxd b/python/pyarrow/_fs.pxd
index 4504b78b83..0df75530bb 100644
--- a/python/pyarrow/_fs.pxd
+++ b/python/pyarrow/_fs.pxd
@@ -67,9 +67,6 @@ cdef class FileSystem(_Weakrefable):
 
 
 cdef class LocalFileSystem(FileSystem):
-    cdef:
-        CLocalFileSystem* localfs
-
     cdef init(self, const shared_ptr[CFileSystem]& wrapped)
 
 
diff --git a/python/pyarrow/_fs.pyx b/python/pyarrow/_fs.pyx
index 86cf39e993..0e635b2c8a 100644
--- a/python/pyarrow/_fs.pyx
+++ b/python/pyarrow/_fs.pyx
@@ -18,7 +18,6 @@
 # cython: language_level = 3
 
 from cpython.datetime cimport datetime, PyDateTime_DateTime
-from cython cimport binding
 
 from pyarrow.includes.common cimport *
 from pyarrow.includes.libarrow_python cimport PyDateTime_to_TimePoint
@@ -421,6 +420,11 @@ cdef class FileSystem(_Weakrefable):
                         "the subclasses instead: LocalFileSystem or "
                         "SubTreeFileSystem")
 
+    @staticmethod
+    def _from_uri(uri):
+        fs, _path = FileSystem.from_uri(uri)
+        return fs
+
     @staticmethod
     def from_uri(uri):
         """
@@ -1097,30 +1101,18 @@ cdef class LocalFileSystem(FileSystem):
 
     def __init__(self, *, use_mmap=False):
         cdef:
-            CLocalFileSystemOptions opts
-            shared_ptr[CLocalFileSystem] fs
-
-        opts = CLocalFileSystemOptions.Defaults()
-        opts.use_mmap = use_mmap
+            shared_ptr[CFileSystem] fs
+            c_string c_uri
 
-        fs = make_shared[CLocalFileSystem](opts)
+        # from_uri needs a non-empty path, so just use a placeholder of /_
+        c_uri = tobytes(f"file:///_?use_mmap={int(use_mmap)}")
+        with nogil:
+            fs = GetResultValue(CFileSystemFromUri(c_uri))
         self.init(<shared_ptr[CFileSystem]> fs)
 
-    cdef init(self, const shared_ptr[CFileSystem]& c_fs):
-        FileSystem.init(self, c_fs)
-        self.localfs = <CLocalFileSystem*> c_fs.get()
-
-    @staticmethod
-    @binding(True)  # Required for cython < 3
-    def _reconstruct(kwargs):
-        # __reduce__ doesn't allow passing named arguments directly to the
-        # reconstructor, hence this wrapper.
-        return LocalFileSystem(**kwargs)
-
     def __reduce__(self):
-        cdef CLocalFileSystemOptions opts = self.localfs.options()
-        return LocalFileSystem._reconstruct, (dict(
-            use_mmap=opts.use_mmap),)
+        uri = frombytes(GetResultValue(self.fs.MakeUri(b"/_")))
+        return FileSystem._from_uri, (uri,)
 
 
 cdef class SubTreeFileSystem(FileSystem):
diff --git a/python/pyarrow/includes/libarrow_fs.pxd 
b/python/pyarrow/includes/libarrow_fs.pxd
index 328b426a49..f1f2985f65 100644
--- a/python/pyarrow/includes/libarrow_fs.pxd
+++ b/python/pyarrow/includes/libarrow_fs.pxd
@@ -61,6 +61,7 @@ cdef extern from "arrow/filesystem/api.h" namespace 
"arrow::fs" nogil:
         shared_ptr[CFileSystem] shared_from_this()
         c_string type_name() const
         CResult[c_string] NormalizePath(c_string path)
+        CResult[c_string] MakeUri(c_string path)
         CResult[CFileInfo] GetFileInfo(const c_string& path)
         CResult[vector[CFileInfo]] GetFileInfo(
             const vector[c_string]& paths)
@@ -84,6 +85,8 @@ cdef extern from "arrow/filesystem/api.h" namespace 
"arrow::fs" nogil:
         c_bool Equals(const CFileSystem& other)
         c_bool Equals(shared_ptr[CFileSystem] other)
 
+    CResult[shared_ptr[CFileSystem]] CFileSystemFromUri \
+        "arrow::fs::FileSystemFromUri"(const c_string& uri)
     CResult[shared_ptr[CFileSystem]] CFileSystemFromUri \
         "arrow::fs::FileSystemFromUri"(const c_string& uri, c_string* out_path)
     CResult[shared_ptr[CFileSystem]] CFileSystemFromUriOrPath \
@@ -98,19 +101,6 @@ cdef extern from "arrow/filesystem/api.h" namespace 
"arrow::fs" nogil:
     CStatus CFileSystemsInitialize "arrow::fs::Initialize" \
         (const CFileSystemGlobalOptions& options)
 
-    cdef cppclass CLocalFileSystemOptions "arrow::fs::LocalFileSystemOptions":
-        c_bool use_mmap
-
-        @staticmethod
-        CLocalFileSystemOptions Defaults()
-
-        c_bool Equals(const CLocalFileSystemOptions& other)
-
-    cdef cppclass CLocalFileSystem "arrow::fs::LocalFileSystem"(CFileSystem):
-        CLocalFileSystem()
-        CLocalFileSystem(CLocalFileSystemOptions)
-        CLocalFileSystemOptions options()
-
     cdef cppclass CSubTreeFileSystem \
             "arrow::fs::SubTreeFileSystem"(CFileSystem):
         CSubTreeFileSystem(const c_string& base_path,
diff --git a/r/R/arrowExports.R b/r/R/arrowExports.R
index 967caba727..752d3a266b 100644
--- a/r/R/arrowExports.R
+++ b/r/R/arrowExports.R
@@ -1352,10 +1352,6 @@ fs___FileSystem__type_name <- function(file_system) {
   .Call(`_arrow_fs___FileSystem__type_name`, file_system)
 }
 
-fs___LocalFileSystem__create <- function() {
-  .Call(`_arrow_fs___LocalFileSystem__create`)
-}
-
 fs___SubTreeFileSystem__create <- function(base_path, base_fs) {
   .Call(`_arrow_fs___SubTreeFileSystem__create`, base_path, base_fs)
 }
diff --git a/r/R/filesystem.R b/r/R/filesystem.R
index 0e4484d1b5..0176cdf846 100644
--- a/r/R/filesystem.R
+++ b/r/R/filesystem.R
@@ -390,7 +390,8 @@ are_urls <- function(x) if (!is.character(x)) FALSE else 
grepl("://", x)
 #' @export
 LocalFileSystem <- R6Class("LocalFileSystem", inherit = FileSystem)
 LocalFileSystem$create <- function() {
-  fs___LocalFileSystem__create()
+  # from_uri needs a non-empty path, so just use a placeholder of /_
+  FileSystem$from_uri("file:///_")$fs
 }
 
 #' @usage NULL
diff --git a/r/src/arrowExports.cpp b/r/src/arrowExports.cpp
index 5031c79f20..a4c4b614d6 100644
--- a/r/src/arrowExports.cpp
+++ b/r/src/arrowExports.cpp
@@ -3472,13 +3472,6 @@ BEGIN_CPP11
 END_CPP11
 }
 // filesystem.cpp
-std::shared_ptr<fs::LocalFileSystem> fs___LocalFileSystem__create();
-extern "C" SEXP _arrow_fs___LocalFileSystem__create(){
-BEGIN_CPP11
-       return cpp11::as_sexp(fs___LocalFileSystem__create());
-END_CPP11
-}
-// filesystem.cpp
 std::shared_ptr<fs::SubTreeFileSystem> fs___SubTreeFileSystem__create(const 
std::string& base_path, const std::shared_ptr<fs::FileSystem>& base_fs);
 extern "C" SEXP _arrow_fs___SubTreeFileSystem__create(SEXP base_path_sexp, 
SEXP base_fs_sexp){
 BEGIN_CPP11
@@ -6014,7 +6007,6 @@ static const R_CallMethodDef CallEntries[] = {
                { "_arrow_fs___FileSystem__OpenOutputStream", (DL_FUNC) 
&_arrow_fs___FileSystem__OpenOutputStream, 2}, 
                { "_arrow_fs___FileSystem__OpenAppendStream", (DL_FUNC) 
&_arrow_fs___FileSystem__OpenAppendStream, 2}, 
                { "_arrow_fs___FileSystem__type_name", (DL_FUNC) 
&_arrow_fs___FileSystem__type_name, 1}, 
-               { "_arrow_fs___LocalFileSystem__create", (DL_FUNC) 
&_arrow_fs___LocalFileSystem__create, 0}, 
                { "_arrow_fs___SubTreeFileSystem__create", (DL_FUNC) 
&_arrow_fs___SubTreeFileSystem__create, 2}, 
                { "_arrow_fs___SubTreeFileSystem__base_fs", (DL_FUNC) 
&_arrow_fs___SubTreeFileSystem__base_fs, 1}, 
                { "_arrow_fs___SubTreeFileSystem__base_path", (DL_FUNC) 
&_arrow_fs___SubTreeFileSystem__base_path, 1}, 
diff --git a/r/src/filesystem.cpp b/r/src/filesystem.cpp
index 23bcb81e8f..2274a3d7ff 100644
--- a/r/src/filesystem.cpp
+++ b/r/src/filesystem.cpp
@@ -238,13 +238,6 @@ std::string fs___FileSystem__type_name(
   return file_system->type_name();
 }
 
-// [[arrow::export]]
-std::shared_ptr<fs::LocalFileSystem> fs___LocalFileSystem__create() {
-  // Affects OpenInputFile/OpenInputStream
-  auto io_context = MainRThread::GetInstance().CancellableIOContext();
-  return std::make_shared<fs::LocalFileSystem>(io_context);
-}
-
 // [[arrow::export]]
 std::shared_ptr<fs::SubTreeFileSystem> fs___SubTreeFileSystem__create(
     const std::string& base_path, const std::shared_ptr<fs::FileSystem>& 
base_fs) {
@@ -268,9 +261,10 @@ cpp11::writable::list fs___FileSystemFromUri(const 
std::string& path) {
   using cpp11::literals::operator"" _nm;
 
   std::string out_path;
-  return cpp11::writable::list(
-      {"fs"_nm = cpp11::to_r6(ValueOrStop(fs::FileSystemFromUri(path, 
&out_path))),
-       "path"_nm = out_path});
+  auto io_context = MainRThread::GetInstance().CancellableIOContext();
+  return cpp11::writable::list({"fs"_nm = cpp11::to_r6(ValueOrStop(
+                                    fs::FileSystemFromUri(path, io_context, 
&out_path))),
+                                "path"_nm = out_path});
 }
 
 // [[arrow::export]]

Reply via email to