Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita56b083

Browse files
author
Jesse Whitehouse
committed
Stop skipping TimeMicrosecondsTest
I had to update our custom Time() override to cope with both non-microsecondstimestrings and microseconds time strings. So I reran the TimeTest() as wellto confirm both types still work.test_suite.py::TimeMicrosecondsTest_databricks+databricks::test_literal PASSEDtest_suite.py::TimeMicrosecondsTest_databricks+databricks::test_null PASSEDtest_suite.py::TimeMicrosecondsTest_databricks+databricks::test_null_bound_comparison PASSEDtest_suite.py::TimeMicrosecondsTest_databricks+databricks::test_round_trip PASSEDtest_suite.py::TimeMicrosecondsTest_databricks+databricks::test_round_trip_decorated PASSEDtest_suite.py::TimeMicrosecondsTest_databricks+databricks::test_select_direct PASSEDSigned-off-by: Jesse Whitehouse <jesse.whitehouse@databricks.com>
1 parent53eef60 commita56b083

File tree

3 files changed

+32
-52
lines changed

3 files changed

+32
-52
lines changed

‎src/databricks/sqlalchemy/_types.py‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,28 @@ class DatabricksTimeType(sqlalchemy.types.TypeDecorator):
111111
impl=sqlalchemy.types.Time
112112
cache_ok=True
113113

114+
TIME_WITH_MICROSECONDS_FMT="%H:%M:%S.%f"
115+
TIME_NO_MICROSECONDS_FMT="%H:%M:%S"
114116

115117
defprocess_bind_param(self,value:Union[datetime.time,None],dialect)->str:
116118
"""Values sent to the database are converted to %:H:%M:%S strings.
117119
"""
118120
ifvalueisNone:
119121
returnNone
120-
returnvalue.strftime("%H:%M:%S")
122+
returnvalue.strftime(self.TIME_WITH_MICROSECONDS_FMT)
121123

122124
defprocess_literal_param(self,value,dialect)->datetime.time:
123125
"""It's not clear to me why this is necessary. Without it, SQLAlchemy's Timetest:test_literal fails
124126
because the string literal renderer receives a str() object and calls .isoformat() on it.
125127
126128
Whereas this method receives a datetime.time() object which is subsequently passed to that
127129
same renderer. And that works.
130+
131+
UPDATE: After coping with the literal_processor override in DatabricksStringType, I suspect a similar
132+
mechanism is at play. Two different processors are are called in sequence. This is likely a byproduct
133+
of Databricks not having a true TIME type. I think the string representation of Time() types is
134+
somehow affecting the literal rendering process. But as long as this passes the tests, I'm not
135+
worried about it.
128136
"""
129137
returnvalue
130138

@@ -134,7 +142,14 @@ def process_result_value(self, value: Union[None, str], dialect) -> Union[dateti
134142
"""
135143
ifvalueisNone:
136144
returnNone
137-
returndatetime.strptime(value,"%H:%M:%S").time()
145+
146+
try:
147+
_parsed=datetime.strptime(value,self.TIME_WITH_MICROSECONDS_FMT)
148+
exceptValueError:
149+
# If the string doesn't have microseconds, try parsing it without them
150+
_parsed=datetime.strptime(value,self.TIME_NO_MICROSECONDS_FMT)
151+
152+
return_parsed.time()
138153

139154
classDatabricksStringType(sqlalchemy.types.TypeDecorator):
140155
"""We have to implement our own String() type because SQLAlchemy's default implementation

‎src/databricks/sqlalchemy/requirements.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,20 @@ def timestamp_microseconds(self):
6262
if TIMESTAMP is used."""
6363

6464
returnsqlalchemy.testing.exclusions.open()
65+
66+
@property
67+
deftime_microseconds(self):
68+
"""target dialect supports representation of Python
69+
datetime.time() with microsecond objects.
70+
71+
This requirement declaration isn't needed but I've included it here for completeness.
72+
Since Databricks doesn't have a TIME type, SQLAlchemy will compile Time() columns
73+
as STRING Databricks data types. And we use a custom time type to render those strings
74+
between str() and time.time() representations. Therefore we can store _any_ precision
75+
that SQLAlchemy needs. The time_microseconds requirement defaults to ON for all dialects
76+
except mssql, mysql, mariadb, and oracle.
77+
"""
78+
79+
returnsqlalchemy.testing.exclusions.open()
6580

6681

‎src/databricks/sqlalchemy/test/test_suite.py‎

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -237,56 +237,6 @@ def test_row_w_scalar_select(self):
237237

238238

239239

240-
classTimeMicrosecondsTest(TimeMicrosecondsTest):
241-
@pytest.mark.skip(
242-
reason="Time type implementation needs work. Microseconds are not handled at all."
243-
)
244-
deftest_literal(self):
245-
"""
246-
Exception:
247-
sqlalchemy.exc.CompileError: No literal value renderer is available for literal value "datetime.time(12, 57, 18, 396)" with datatype TIME
248-
"""
249-
250-
@pytest.mark.skip(
251-
reason="Time type implementation needs work. Microseconds are not handled at all."
252-
)
253-
deftest_null_bound_comparison(self):
254-
"""
255-
Exception:
256-
sqlalchemy.exc.ProgrammingError: (databricks.sql.exc.ProgrammingError) Unsupported object 12:57:18.000396
257-
"""
258-
259-
@pytest.mark.skip(
260-
reason="Time type implementation needs work. Microseconds are not handled at all."
261-
)
262-
deftest_round_trip(self):
263-
"""
264-
Exception:
265-
sqlalchemy.exc.ProgrammingError: (databricks.sql.exc.ProgrammingError) Unsupported object 12:57:18.000396
266-
"""
267-
268-
@pytest.mark.skip(
269-
reason="Time type implementation needs work. Microseconds are not handled at all."
270-
)
271-
deftest_round_trip_decorated(self):
272-
"""
273-
Exception:
274-
sqlalchemy.exc.ProgrammingError: (databricks.sql.exc.ProgrammingError) Unsupported object 12:57:18.000396
275-
"""
276-
277-
@pytest.mark.skip(
278-
reason="Time type implementation needs work. Microseconds are not handled at all."
279-
)
280-
deftest_select_direct(self):
281-
"""
282-
Exception:
283-
sqlalchemy.exc.ProgrammingError: (databricks.sql.exc.ProgrammingError) Unsupported object 12:57:18.000396
284-
"""
285-
286-
287-
288-
289-
290240
classExceptionTest(ExceptionTest):
291241
@pytest.mark.skip(reason="Databricks may not support this method.")
292242
deftest_integrity_error(self):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp