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

Commitbc0495d

Browse files
author
Jesse Whitehouse
committed
Black all files changed in this PR
Signed-off-by: Jesse Whitehouse <jesse.whitehouse@databricks.com>
1 parent77221c2 commitbc0495d

File tree

4 files changed

+38
-42
lines changed

4 files changed

+38
-42
lines changed

‎src/databricks/sqlalchemy/__init__.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class DatabricksDialect(default.DefaultDialect):
5151
colspecs= {
5252
sqlalchemy.types.DateTime:dialect_type_impl.DatabricksDateTimeNoTimezoneType,
5353
sqlalchemy.types.Time:dialect_type_impl.DatabricksTimeType,
54-
sqlalchemy.types.String:dialect_type_impl.DatabricksStringType
54+
sqlalchemy.types.String:dialect_type_impl.DatabricksStringType,
5555
}
5656

5757
@classmethod
@@ -136,7 +136,6 @@ def get_columns(self, connection, table_name, schema=None, **kwargs):
136136
columns= []
137137

138138
forcolinresp:
139-
140139
# Taken from PyHive. This removes added type info from decimals and maps
141140
_col_type=re.search(r"^\w+",col.TYPE_NAME).group(0)
142141
this_column= {

‎src/databricks/sqlalchemy/_types.py‎

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
fromdatabricks.sql.utilsimportParamEscaper
1010

11+
1112
@compiles(sqlalchemy.types.Enum,"databricks")
1213
@compiles(sqlalchemy.types.String,"databricks")
1314
@compiles(sqlalchemy.types.Text,"databricks")
@@ -88,11 +89,11 @@ def compile_array_databricks(type_, compiler, **kw):
8889

8990
classDatabricksDateTimeNoTimezoneType(sqlalchemy.types.TypeDecorator):
9091
"""The decimal that pysql creates when it receives the contents of a TIMESTAMP_NTZ
91-
includes a timezone of 'Etc/UTC'. But since SQLAlchemy's test suite assumes that
92-
the sqlalchemy.types.DateTime type will return a datetime.datetime _without_ any
93-
timezone set, we need to strip the timezone off the value received from pysql.
92+
includes a timezone of 'Etc/UTC'. But since SQLAlchemy's test suite assumes that
93+
the sqlalchemy.types.DateTime type will return a datetime.datetime _without_ any
94+
timezone set, we need to strip the timezone off the value received from pysql.
9495
95-
It's not clear if DBR sends a timezone to pysql or if pysql is adding it. This could be a bug.
96+
It's not clear if DBR sends a timezone to pysql or if pysql is adding it. This could be a bug.
9697
"""
9798

9899
impl=sqlalchemy.types.DateTime
@@ -103,10 +104,10 @@ def process_result_value(self, value: Union[None, datetime], dialect):
103104
ifvalueisNone:
104105
returnNone
105106
returnvalue.replace(tzinfo=None)
106-
107+
108+
107109
classDatabricksTimeType(sqlalchemy.types.TypeDecorator):
108-
"""Databricks has no native TIME type. So we store it as a string.
109-
"""
110+
"""Databricks has no native TIME type. So we store it as a string."""
110111

111112
impl=sqlalchemy.types.Time
112113
cache_ok=True
@@ -115,12 +116,11 @@ class DatabricksTimeType(sqlalchemy.types.TypeDecorator):
115116
TIME_NO_MICROSECONDS_FMT="%H:%M:%S"
116117

117118
defprocess_bind_param(self,value:Union[datetime.time,None],dialect)->str:
118-
"""Values sent to the database are converted to %:H:%M:%S strings.
119-
"""
119+
"""Values sent to the database are converted to %:H:%M:%S strings."""
120120
ifvalueisNone:
121121
returnNone
122122
returnvalue.strftime(self.TIME_WITH_MICROSECONDS_FMT)
123-
123+
124124
defprocess_literal_param(self,value,dialect)->datetime.time:
125125
"""It's not clear to me why this is necessary. Without it, SQLAlchemy's Timetest:test_literal fails
126126
because the string literal renderer receives a str() object and calls .isoformat() on it.
@@ -136,21 +136,22 @@ def process_literal_param(self, value, dialect) -> datetime.time:
136136
"""
137137
returnvalue
138138

139-
140-
defprocess_result_value(self,value:Union[None,str],dialect)->Union[datetime.time,None]:
141-
"""Values received from the database are parsed intodatetime.time() objects
142-
"""
139+
defprocess_result_value(
140+
self,value:Union[None,str],dialect
141+
)->Union[datetime.time,None]:
142+
"""Values received from the database are parsed into datetime.time() objects"""
143143
ifvalueisNone:
144144
returnNone
145-
145+
146146
try:
147147
_parsed=datetime.strptime(value,self.TIME_WITH_MICROSECONDS_FMT)
148148
exceptValueError:
149149
# If the string doesn't have microseconds, try parsing it without them
150150
_parsed=datetime.strptime(value,self.TIME_NO_MICROSECONDS_FMT)
151-
151+
152152
return_parsed.time()
153-
153+
154+
154155
classDatabricksStringType(sqlalchemy.types.TypeDecorator):
155156
"""We have to implement our own String() type because SQLAlchemy's default implementation
156157
wants to escape single-quotes with a doubled single-quote. Databricks uses a backslash for
@@ -160,18 +161,18 @@ class DatabricksStringType(sqlalchemy.types.TypeDecorator):
160161
impl=sqlalchemy.types.String
161162
cache_ok=True
162163
pe=ParamEscaper()
163-
164+
164165
defprocess_literal_param(self,value,dialect)->str:
165166
"""SQLAlchemy's default string escaping for backslashes doesn't work for databricks. The logic here
166167
implements the same logic as our legacy inline escaping logic.
167168
"""
168169

169170
returnself.pe.escape_string(value)
170-
171+
171172
defliteral_processor(self,dialect):
172173
"""We manually override this method to prevent further processing of the string literal beyond
173174
what happens in the process_literal_param() method.
174-
175+
175176
The SQLAlchemy docs _specifically_ say to not override this method.
176177
177178
It appears that any processing that happens from TypeEngine.process_literal_param happens _before_
@@ -180,7 +181,7 @@ def literal_processor(self, dialect):
180181
error in Databricks. And it's not necessary because ParamEscaper() already implements all the escaping we need.
181182
182183
We should consider opening an issue on the SQLAlchemy project to see if I'm using it wrong.
183-
184+
184185
See type_api.py::TypeEngine.literal_processor:
185186
186187
```python
@@ -192,9 +193,10 @@ def process(value: Any) -> str:
192193
193194
That call to fixed_impl_processor wraps the result of fixed_process_literal_param (which is the
194195
process_literal_param defined in our Databricks dialect)
195-
196+
196197
https://docs.sqlalchemy.org/en/20/core/custom_types.html#sqlalchemy.types.TypeDecorator.literal_processor
197198
"""
199+
198200
defprocess(value):
199201
"""This is a copy of the default String.literal_processor() method but stripping away
200202
its double-escaping behaviour for single-quotes.
@@ -208,4 +210,4 @@ def process(value):
208210

209211
return"%s"%_step2
210212

211-
returnprocess
213+
returnprocess

‎src/databricks/sqlalchemy/requirements.py‎

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,20 @@ def __some_example_requirement(self):
3131

3232

3333
classRequirements(sqlalchemy.testing.requirements.SuiteRequirements):
34-
3534
@property
3635
defdate_historic(self):
3736
"""target dialect supports representation of Python
3837
datetime.datetime() objects with historic (pre 1970) values."""
3938

4039
returnsqlalchemy.testing.exclusions.open()
41-
40+
4241
@property
4342
defdatetime_historic(self):
4443
"""target dialect supports representation of Python
4544
datetime.datetime() objects with historic (pre 1970) values."""
4645

4746
returnsqlalchemy.testing.exclusions.open()
48-
47+
4948
@property
5049
defdatetime_literals(self):
5150
"""target dialect supports rendering of a date, time, or datetime as a
@@ -54,30 +53,30 @@ def datetime_literals(self):
5453
"""
5554

5655
returnsqlalchemy.testing.exclusions.open()
57-
56+
5857
@property
5958
deftimestamp_microseconds(self):
6059
"""target dialect supports representation of Python
6160
datetime.datetime() with microsecond objects but only
6261
if TIMESTAMP is used."""
6362

6463
returnsqlalchemy.testing.exclusions.open()
65-
64+
6665
@property
6766
deftime_microseconds(self):
6867
"""target dialect supports representation of Python
6968
datetime.time() with microsecond objects.
70-
69+
7170
This requirement declaration isn't needed but I've included it here for completeness.
7271
Since Databricks doesn't have a TIME type, SQLAlchemy will compile Time() columns
7372
as STRING Databricks data types. And we use a custom time type to render those strings
7473
between str() and time.time() representations. Therefore we can store _any_ precision
7574
that SQLAlchemy needs. The time_microseconds requirement defaults to ON for all dialects
76-
except mssql, mysql, mariadb, and oracle.
75+
except mssql, mysql, mariadb, and oracle.
7776
"""
7877

7978
returnsqlalchemy.testing.exclusions.open()
80-
79+
8180
@property
8281
defprecision_generic_float_type(self):
8382
"""target backend will return native floating point numbers with at
@@ -86,7 +85,7 @@ def precision_generic_float_type(self):
8685
Databricks sometimes only returns six digits of precision for the generic Float type
8786
"""
8887
returnsqlalchemy.testing.exclusions.closed()
89-
88+
9089
@property
9190
defliteral_float_coercion(self):
9291
"""target backend will return the exact float value 15.7563
@@ -103,24 +102,24 @@ def literal_float_coercion(self):
103102
Will leave to a PM to decide if we should do so.
104103
"""
105104
returnsqlalchemy.testing.exclusions.closed()
106-
105+
107106
@property
108107
defprecision_numerics_enotation_large(self):
109108
"""target backend supports Decimal() objects using E notation
110109
to represent very large values.
111-
110+
112111
Databricks supports E notation for FLOAT data types but not for DECIMAL types,
113112
which is the underlying data type SQLAlchemy uses for Numeric() types.
114113
115114
"""
116115
returnsqlalchemy.testing.exclusions.closed()
117-
116+
118117
@property
119118
definfinity_floats(self):
120119
"""The Float type can persist and load float('inf'), float('-inf')."""
121120

122121
returnsqlalchemy.testing.exclusions.open()
123-
122+
124123
@property
125124
defprecision_numerics_retains_significant_digits(self):
126125
"""A precision numeric type will return empty significant digits,

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,6 @@ def test_long_convention_name(self):
151151
"""
152152

153153

154-
155-
156154
classRowFetchTest(RowFetchTest):
157155
@pytest.mark.skip(
158156
reason="Date type implementation needs work. Timezone information not preserved."
@@ -164,7 +162,6 @@ def test_row_w_scalar_select(self):
164162
"""
165163

166164

167-
168165
classExceptionTest(ExceptionTest):
169166
@pytest.mark.skip(reason="Databricks may not support this method.")
170167
deftest_integrity_error(self):
@@ -298,7 +295,6 @@ def test_numeric_reflection(self):
298295
"""
299296

300297

301-
302298
classDifficultParametersTest(DifficultParametersTest):
303299
@pytest.mark.skip(reason="Error during execution. Requires investigation.")
304300
deftest_round_trip_same_named_column(self):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp