Skip to content

Commit d531726

Browse files
authored
[SC-67303] Add modification_time field to dbfs FileInfo Object (#360)
Add a new `modification_time` Long field to the `FileInfo` object, received from the DBFS API and exposed in the result of commands such as `dbfs ls -l <path>` or `databricks fs ls -l <path>`.
1 parent 736d693 commit d531726

3 files changed

Lines changed: 24 additions & 11 deletions

File tree

databricks_cli/dbfs/api.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,29 +45,37 @@ class ParseException(Exception):
4545

4646

4747
class FileInfo(object):
48-
def __init__(self, dbfs_path, is_dir, file_size):
48+
def __init__(self, dbfs_path, is_dir, file_size, modification_time):
4949
self.dbfs_path = dbfs_path
5050
self.is_dir = is_dir
5151
self.file_size = file_size
52+
self.modification_time = modification_time
5253

5354
def to_row(self, is_long_form, is_absolute):
5455
path = self.dbfs_path.absolute_path if is_absolute else self.dbfs_path.basename
5556
stylized_path = click.style(path, 'cyan') if self.is_dir else path
5657
if is_long_form:
5758
filetype = 'dir' if self.is_dir else 'file'
58-
return [filetype, self.file_size, stylized_path]
59+
row = [filetype, self.file_size, stylized_path]
60+
# Add modification time if it is available.
61+
if self.modification_time is not None:
62+
row.append(self.modification_time)
63+
return row
5964
return [stylized_path]
6065

6166
@classmethod
6267
def from_json(cls, json):
6368
dbfs_path = DbfsPath.from_api_path(json['path'])
64-
return cls(dbfs_path, json['is_dir'], json['file_size'])
69+
# If JSON doesn't include modification_time data, replace it with None.
70+
modification_time = json['modification_time'] if 'modification_time' in json else None
71+
return cls(dbfs_path, json['is_dir'], json['file_size'], modification_time)
6572

6673
def __eq__(self, other):
6774
if isinstance(other, self.__class__):
6875
return self.dbfs_path == other.dbfs_path and \
6976
self.is_dir == other.is_dir and \
70-
self.file_size == other.file_size
77+
self.file_size == other.file_size and \
78+
self.modification_time == other.modification_time
7179
return False
7280

7381

databricks_cli/dbfs/cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
@click.option('--absolute', is_flag=True, default=False,
3737
help='Displays absolute paths.')
3838
@click.option('-l', is_flag=True, default=False,
39-
help='Displays full information including size and file type.')
39+
help="""Displays full information including size, file type
40+
and modification time since Epoch in milliseconds.""")
4041
@click.argument('dbfs_path', nargs=-1, type=DbfsPathClickType())
4142
@debug_option
4243
@profile_option

tests/dbfs/test_api.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from base64 import b64encode
2626

2727
import os
28+
2829
import requests
2930
import mock
3031
import pytest
@@ -34,12 +35,14 @@
3435
from databricks_cli.dbfs.exceptions import LocalFileExistsException
3536

3637
TEST_DBFS_PATH = DbfsPath('dbfs:/test')
38+
DUMMY_TIME = 1613158406000
3739
TEST_FILE_JSON = {
3840
'path': '/test',
3941
'is_dir': False,
40-
'file_size': 1
42+
'file_size': 1,
43+
'modification_time': DUMMY_TIME
4144
}
42-
TEST_FILE_INFO = api.FileInfo(TEST_DBFS_PATH, False, 1)
45+
TEST_FILE_INFO = api.FileInfo(TEST_DBFS_PATH, False, 1, DUMMY_TIME)
4346

4447

4548
def get_resource_does_not_exist_exception():
@@ -57,15 +60,15 @@ def get_partial_delete_exception(message="[...] operation has deleted 10 files [
5760

5861
class TestFileInfo(object):
5962
def test_to_row_not_long_form_not_absolute(self):
60-
file_info = api.FileInfo(TEST_DBFS_PATH, False, 1)
63+
file_info = api.FileInfo(TEST_DBFS_PATH, False, 1, DUMMY_TIME)
6164
row = file_info.to_row(is_long_form=False, is_absolute=False)
6265
assert len(row) == 1
6366
assert TEST_DBFS_PATH.basename == row[0]
6467

6568
def test_to_row_long_form_not_absolute(self):
66-
file_info = api.FileInfo(TEST_DBFS_PATH, False, 1)
69+
file_info = api.FileInfo(TEST_DBFS_PATH, False, 1, DUMMY_TIME)
6770
row = file_info.to_row(is_long_form=True, is_absolute=False)
68-
assert len(row) == 3
71+
assert len(row) == 4
6972
assert row[0] == 'file'
7073
assert row[1] == 1
7174
assert TEST_DBFS_PATH.basename == row[2]
@@ -163,7 +166,8 @@ def test_cat(self, dbfs_api):
163166
dbfs_api.client.get_status.return_value = {
164167
'path': '/test',
165168
'is_dir': False,
166-
'file_size': 1
169+
'file_size': 1,
170+
'modification_time': DUMMY_TIME
167171
}
168172
dbfs_api.client.read.return_value = {
169173
'bytes_read': 1,

0 commit comments

Comments
 (0)