t-sql 2.1.1__tar.gz → 2.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. {t_sql-2.1.1 → t_sql-2.1.2}/PKG-INFO +1 -1
  2. {t_sql-2.1.1 → t_sql-2.1.2}/pyproject.toml +1 -1
  3. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_query_builder.py +26 -3
  4. {t_sql-2.1.1 → t_sql-2.1.2}/tsql/query_builder.py +75 -26
  5. t_sql-2.1.1/.beads/tsql.db +0 -0
  6. t_sql-2.1.1/.idea/.gitignore +0 -8
  7. t_sql-2.1.1/.idea/inspectionProfiles/Project_Default.xml +0 -24
  8. t_sql-2.1.1/.idea/inspectionProfiles/profiles_settings.xml +0 -6
  9. t_sql-2.1.1/.idea/misc.xml +0 -11
  10. t_sql-2.1.1/.idea/tsql.iml +0 -10
  11. t_sql-2.1.1/.idea/vcs.xml +0 -6
  12. t_sql-2.1.1/.idea/workspace.xml +0 -124
  13. {t_sql-2.1.1 → t_sql-2.1.2}/.dockerignore +0 -0
  14. {t_sql-2.1.1 → t_sql-2.1.2}/.github/workflows/publish.yml +0 -0
  15. {t_sql-2.1.1 → t_sql-2.1.2}/.github/workflows/test.yml +0 -0
  16. {t_sql-2.1.1 → t_sql-2.1.2}/.gitignore +0 -0
  17. {t_sql-2.1.1 → t_sql-2.1.2}/Dockerfile +0 -0
  18. {t_sql-2.1.1 → t_sql-2.1.2}/LICENSE +0 -0
  19. {t_sql-2.1.1 → t_sql-2.1.2}/README.md +0 -0
  20. {t_sql-2.1.1 → t_sql-2.1.2}/compose.yaml +0 -0
  21. {t_sql-2.1.1 → t_sql-2.1.2}/context7.json +0 -0
  22. {t_sql-2.1.1 → t_sql-2.1.2}/pytest.ini +0 -0
  23. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_alembic_integration.py +0 -0
  24. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_asyncpg_integration.py +0 -0
  25. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_different_object_types.py +0 -0
  26. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_escaped.py +0 -0
  27. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_escaped_binary_hex.py +0 -0
  28. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_helper_functions.py +0 -0
  29. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_injection_edge_cases.py +0 -0
  30. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_injection_protection_validation.py +0 -0
  31. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_injections_for_escaped.py +0 -0
  32. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_mysql_integration.py +0 -0
  33. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_sqlalchemy_integration.py +0 -0
  34. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_sqlite_integration.py +0 -0
  35. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_styles.py +0 -0
  36. {t_sql-2.1.1 → t_sql-2.1.2}/tests/test_tsql.py +0 -0
  37. {t_sql-2.1.1 → t_sql-2.1.2}/tsql/__init__.py +0 -0
  38. {t_sql-2.1.1 → t_sql-2.1.2}/tsql/styles.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: t-sql
3
- Version: 2.1.1
3
+ Version: 2.1.2
4
4
  Summary: Safe SQL. SQL queries for python t-strings (PEP 750)
5
5
  Project-URL: Homepage, https://github.com/nhumrich/t-sql
6
6
  License-File: LICENSE
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "t-sql"
7
- version = "2.1.1"
7
+ version = "2.1.2"
8
8
  description = "Safe SQL. SQL queries for python t-strings (PEP 750)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14"
@@ -31,6 +31,29 @@ def test_table_creation():
31
31
  assert Users.username.column_name == 'username'
32
32
 
33
33
 
34
+ def test_column_name_remapping():
35
+ """Test that Column(column_name=...) allows remapping Python attribute to DB column name"""
36
+ class MyTable(Table, table_name='my_table'):
37
+ id: Column
38
+ system_var: Column = Column(column_name='systemvar')
39
+
40
+ # Verify that the Python attribute name is 'system_var'
41
+ assert isinstance(MyTable.system_var, Column)
42
+ assert MyTable.system_var.table_name == 'my_table'
43
+
44
+ # But the DB column name is 'systemvar'
45
+ assert MyTable.system_var.column_name == 'systemvar'
46
+
47
+ # Verify it works in queries
48
+ query = MyTable.select(MyTable.system_var).where(MyTable.system_var == 'test')
49
+ sql, params = query.render()
50
+
51
+ # The SQL should use 'systemvar', not 'system_var'
52
+ assert 'my_table.systemvar' in sql
53
+ assert 'system_var' not in sql
54
+ assert params == ['test']
55
+
56
+
34
57
  def test_column_equality():
35
58
  """Test Column equality operator"""
36
59
  condition = Users.id == 5
@@ -256,7 +279,7 @@ def test_column_to_column_comparison():
256
279
 
257
280
 
258
281
  def test_to_tsql_returns_tsql_object():
259
- """Test that QueryBuilder.to_tsql() returns a TSQL object"""
282
+ """Test that SelectQueryBuilder.to_tsql() returns a TSQL object"""
260
283
  query = Users.select(Users.id).where(Users.id > 5)
261
284
  tsql_obj = query.to_tsql()
262
285
 
@@ -913,7 +936,7 @@ def test_where_with_not_ilike():
913
936
 
914
937
 
915
938
  def test_in_with_subquery():
916
- """Test IN with a subquery (QueryBuilder)"""
939
+ """Test IN with a subquery (SelectQueryBuilder)"""
917
940
  subquery = Users.select(Users.id).where(Users.username.like('%admin%'))
918
941
  query = Posts.select().where(Posts.user_id.in_(subquery))
919
942
  sql, params = query.render()
@@ -924,7 +947,7 @@ def test_in_with_subquery():
924
947
 
925
948
 
926
949
  def test_not_in_with_subquery():
927
- """Test NOT IN with a subquery (QueryBuilder)"""
950
+ """Test NOT IN with a subquery (SelectQueryBuilder)"""
928
951
  subquery = Users.select(Users.id).where(Users.username.like('%banned%'))
929
952
  query = Posts.select().where(Posts.user_id.not_in(subquery))
930
953
  sql, params = query.render()
@@ -1,6 +1,7 @@
1
1
  from typing import Any, List, Optional, Union, ClassVar
2
2
  from string.templatelib import Template
3
3
  from datetime import datetime
4
+ from abc import ABC, abstractmethod
4
5
 
5
6
  from tsql import TSQL, t_join
6
7
 
@@ -18,7 +19,7 @@ except ImportError:
18
19
  class Column:
19
20
  """Represents a bound column (table + column name) for building queries"""
20
21
 
21
- def __init__(self, table_name: str, column_name: str, python_type: type = None, alias: str = None, schema: str = None):
22
+ def __init__(self, table_name: str = None, column_name: str = None, python_type: type = None, alias: str = None, schema: str = None):
22
23
  self.table_name = table_name
23
24
  self.column_name = column_name
24
25
  self.python_type = python_type
@@ -75,21 +76,21 @@ class Column:
75
76
  def __ge__(self, other) -> 'Condition':
76
77
  return Condition(self, '>=', other)
77
78
 
78
- def in_(self, values: Union[list, tuple, 'Column', Template, 'QueryBuilder']) -> 'Condition':
79
+ def in_(self, values: Union[list, tuple, 'Column', Template, 'SelectQueryBuilder']) -> 'Condition':
79
80
  """Create an IN condition
80
81
 
81
82
  Args:
82
- values: List/tuple of values, a Column, a Template (t-string), or a QueryBuilder for subqueries
83
+ values: List/tuple of values, a Column, a Template (t-string), or a SelectQueryBuilder for subqueries
83
84
  """
84
85
  if isinstance(values, (list, tuple)):
85
86
  return Condition(self, 'IN', tuple(values))
86
87
  return Condition(self, 'IN', values)
87
88
 
88
- def not_in(self, values: Union[list, tuple, 'Column', Template, 'QueryBuilder']) -> 'Condition':
89
+ def not_in(self, values: Union[list, tuple, 'Column', Template, 'SelectQueryBuilder']) -> 'Condition':
89
90
  """Create a NOT IN condition
90
91
 
91
92
  Args:
92
- values: List/tuple of values, a Column, a Template (t-string), or a QueryBuilder for subqueries
93
+ values: List/tuple of values, a Column, a Template (t-string), or a SelectQueryBuilder for subqueries
93
94
  """
94
95
  if isinstance(values, (list, tuple)):
95
96
  return Condition(self, 'NOT IN', tuple(values))
@@ -186,7 +187,7 @@ class Table:
186
187
  'value': getattr(cls, field_name, None)
187
188
  }
188
189
 
189
- # Then, check for Ellipsis (...) assignments and SA Columns
190
+ # Then, check for Ellipsis (...) assignments, SA Columns, and Column instances
190
191
  for field_name in dir(cls):
191
192
  if field_name.startswith('_'):
192
193
  continue
@@ -206,6 +207,13 @@ class Table:
206
207
  'type': None,
207
208
  'value': field_value
208
209
  }
210
+ # Check for Column instances (for column_name remapping)
211
+ elif isinstance(field_value, Column):
212
+ if field_name not in all_fields:
213
+ all_fields[field_name] = {
214
+ 'type': None,
215
+ 'value': field_value
216
+ }
209
217
 
210
218
  # Process all fields
211
219
  for field_name, field_info in all_fields.items():
@@ -225,6 +233,23 @@ class Table:
225
233
  setattr(cls, field_name, ColumnDescriptor(field_name, field_type))
226
234
  continue
227
235
 
236
+ # Check if it's a Column instance (for column_name remapping)
237
+ if isinstance(field_value, Column):
238
+ # Extract the column_name from the Column instance
239
+ db_column_name = field_value.column_name
240
+ if db_column_name is None:
241
+ # No column_name specified, use field_name
242
+ db_column_name = field_name
243
+
244
+ # Create query builder ColumnDescriptor with the DB column name
245
+ setattr(cls, field_name, ColumnDescriptor(db_column_name, field_type))
246
+
247
+ # Create SQLAlchemy column if metadata provided
248
+ if metadata is not None and HAS_SQLALCHEMY:
249
+ sa_type = PYTHON_TO_SA.get(field_type, String)()
250
+ sa_columns.append(SAColumn(db_column_name, sa_type))
251
+ continue
252
+
228
253
  # Check if it's an Ellipsis (...) declaration
229
254
  if field_value is ...:
230
255
  # Create query builder ColumnDescriptor
@@ -249,9 +274,9 @@ class Table:
249
274
  cls._sa_table = SATable(cls.table_name, metadata, *sa_columns, schema=schema)
250
275
 
251
276
  @classmethod
252
- def select(cls, *columns: Union['Column', Template]) -> 'QueryBuilder':
277
+ def select(cls, *columns: Union['Column', Template]) -> 'SelectQueryBuilder':
253
278
  """Start building a SELECT query"""
254
- builder = QueryBuilder(cls)
279
+ builder = SelectQueryBuilder(cls)
255
280
  if columns:
256
281
  builder.select(*columns)
257
282
  return builder
@@ -390,7 +415,31 @@ class Join:
390
415
  return t'{join_type:unsafe} JOIN {table_name:literal} ON {condition_tsql}'
391
416
 
392
417
 
393
- class InsertBuilder:
418
+ class QueryBuilder(ABC):
419
+ """Abstract base class for all query builders.
420
+
421
+ All query builders (SELECT, INSERT, UPDATE, DELETE) implement this interface,
422
+ allowing middleware and query handlers to accept any builder type.
423
+ """
424
+
425
+ @abstractmethod
426
+ def to_tsql(self) -> TSQL:
427
+ """Build and return a TSQL object representing the query."""
428
+ ...
429
+
430
+ def render(self, style=None) -> tuple[str, list]:
431
+ """Convenience method to render the query directly.
432
+
433
+ Args:
434
+ style: Optional parameter style (e.g., QMARK, NUMERIC, etc.)
435
+
436
+ Returns:
437
+ Tuple of (sql_string, parameters)
438
+ """
439
+ return self.to_tsql().render(style)
440
+
441
+
442
+ class InsertBuilder(QueryBuilder):
394
443
  """Fluent interface for building INSERT queries"""
395
444
 
396
445
  def __init__(self, base_table: 'Table', values: dict[str, Any]):
@@ -572,7 +621,7 @@ class InsertBuilder:
572
621
  return f"InsertBuilder(<error rendering: {e}>)"
573
622
 
574
623
 
575
- class UpdateBuilder:
624
+ class UpdateBuilder(QueryBuilder):
576
625
  """Fluent interface for building UPDATE queries"""
577
626
 
578
627
  def __init__(self, base_table: 'Table', values: dict[str, Any]):
@@ -663,7 +712,7 @@ class UpdateBuilder:
663
712
  return f"UpdateBuilder(<error rendering: {e}>)"
664
713
 
665
714
 
666
- class DeleteBuilder:
715
+ class DeleteBuilder(QueryBuilder):
667
716
  """Fluent interface for building DELETE queries"""
668
717
 
669
718
  def __init__(self, base_table: 'Table'):
@@ -731,8 +780,8 @@ class DeleteBuilder:
731
780
  return f"DeleteBuilder(<error rendering: {e}>)"
732
781
 
733
782
 
734
- class QueryBuilder:
735
- """Fluent interface for building SQL queries"""
783
+ class SelectQueryBuilder(QueryBuilder):
784
+ """Fluent interface for building SQL SELECT queries"""
736
785
 
737
786
  def __init__(self, base_table: 'Table'):
738
787
  self.base_table = base_table
@@ -745,7 +794,7 @@ class QueryBuilder:
745
794
  self._limit_value: Optional[int] = None
746
795
  self._offset_value: Optional[int] = None
747
796
 
748
- def select(self, *columns: Union[Column, Template]) -> 'QueryBuilder':
797
+ def select(self, *columns: Union[Column, Template]) -> 'SelectQueryBuilder':
749
798
  """Specify columns to select
750
799
 
751
800
  Args:
@@ -764,7 +813,7 @@ class QueryBuilder:
764
813
  self._columns = list(columns) if columns else None
765
814
  return self
766
815
 
767
- def where(self, condition: Union[Condition, Template]) -> 'QueryBuilder':
816
+ def where(self, condition: Union[Condition, Template]) -> 'SelectQueryBuilder':
768
817
  """Add a WHERE condition (multiple calls are ANDed together)
769
818
 
770
819
  Accepts either Condition objects from query builder or raw t-string Templates
@@ -772,20 +821,20 @@ class QueryBuilder:
772
821
  self._conditions.append(condition)
773
822
  return self
774
823
 
775
- def join(self, table: 'Table', on: Condition, join_type: str = 'INNER') -> 'QueryBuilder':
824
+ def join(self, table: 'Table', on: Condition, join_type: str = 'INNER') -> 'SelectQueryBuilder':
776
825
  """Add a JOIN clause"""
777
826
  self._joins.append(Join(table, on, join_type))
778
827
  return self
779
828
 
780
- def left_join(self, table: 'Table', on: Condition) -> 'QueryBuilder':
829
+ def left_join(self, table: 'Table', on: Condition) -> 'SelectQueryBuilder':
781
830
  """Add a LEFT JOIN clause"""
782
831
  return self.join(table, on, 'LEFT')
783
832
 
784
- def right_join(self, table: 'Table', on: Condition) -> 'QueryBuilder':
833
+ def right_join(self, table: 'Table', on: Condition) -> 'SelectQueryBuilder':
785
834
  """Add a RIGHT JOIN clause"""
786
835
  return self.join(table, on, 'RIGHT')
787
836
 
788
- def order_by(self, *columns: Union[Column, tuple[Column, str]]) -> 'QueryBuilder':
837
+ def order_by(self, *columns: Union[Column, tuple[Column, str]]) -> 'SelectQueryBuilder':
789
838
  """Add ORDER BY clause. Pass (column, 'DESC') for descending"""
790
839
  for col in columns:
791
840
  if isinstance(col, tuple):
@@ -794,12 +843,12 @@ class QueryBuilder:
794
843
  self._order_by_columns.append((col, 'ASC'))
795
844
  return self
796
845
 
797
- def group_by(self, *columns: Column) -> 'QueryBuilder':
846
+ def group_by(self, *columns: Column) -> 'SelectQueryBuilder':
798
847
  """Add GROUP BY clause"""
799
848
  self._group_by_columns.extend(columns)
800
849
  return self
801
850
 
802
- def having(self, condition: Union[Condition, Template]) -> 'QueryBuilder':
851
+ def having(self, condition: Union[Condition, Template]) -> 'SelectQueryBuilder':
803
852
  """Add HAVING condition (multiple calls are ANDed together)
804
853
 
805
854
  Accepts either Condition objects from query builder or raw t-string Templates
@@ -807,12 +856,12 @@ class QueryBuilder:
807
856
  self._having_conditions.append(condition)
808
857
  return self
809
858
 
810
- def limit(self, n: int) -> 'QueryBuilder':
859
+ def limit(self, n: int) -> 'SelectQueryBuilder':
811
860
  """Add LIMIT clause"""
812
861
  self._limit_value = n
813
862
  return self
814
863
 
815
- def offset(self, n: int) -> 'QueryBuilder':
864
+ def offset(self, n: int) -> 'SelectQueryBuilder':
816
865
  """Add OFFSET clause"""
817
866
  self._offset_value = n
818
867
  return self
@@ -894,10 +943,10 @@ class QueryBuilder:
894
943
  try:
895
944
  query, params = self.to_tsql().render()
896
945
  if params:
897
- return f"QueryBuilder(\n SQL: {query}\n Params: {params}\n)"
898
- return f"QueryBuilder({query})"
946
+ return f"SelectQueryBuilder(\n SQL: {query}\n Params: {params}\n)"
947
+ return f"SelectQueryBuilder({query})"
899
948
  except Exception as e:
900
- return f"QueryBuilder(<error rendering: {e}>)"
949
+ return f"SelectQueryBuilder(<error rendering: {e}>)"
901
950
 
902
951
 
903
952
  # Python type to SQLAlchemy type mapping (for simple type annotations)
Binary file
@@ -1,8 +0,0 @@
1
- # Default ignored files
2
- /shelf/
3
- /workspace.xml
4
- # Editor-based HTTP Client requests
5
- /httpRequests/
6
- # Datasource local storage ignored files
7
- /dataSources/
8
- /dataSources.local.xml
@@ -1,24 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <profile version="1.0">
3
- <option name="myName" value="Project Default" />
4
- <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5
- <inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
6
- <option name="ourVersions">
7
- <value>
8
- <list size="3">
9
- <item index="0" class="java.lang.String" itemvalue="3.11" />
10
- <item index="1" class="java.lang.String" itemvalue="3.12" />
11
- <item index="2" class="java.lang.String" itemvalue="3.13" />
12
- </list>
13
- </value>
14
- </option>
15
- </inspection_tool>
16
- <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
17
- <option name="ignoredIdentifiers">
18
- <list>
19
- <option value="base64.binascii" />
20
- </list>
21
- </option>
22
- </inspection_tool>
23
- </profile>
24
- </component>
@@ -1,6 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <settings>
3
- <option name="USE_PROJECT_PROFILE" value="false" />
4
- <version value="1.0" />
5
- </settings>
6
- </component>
@@ -1,11 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="Black">
4
- <option name="sdkName" value="uv (tsql)" />
5
- </component>
6
- <component name="KubernetesApiPersistence">{}</component>
7
- <component name="KubernetesApiProvider"><![CDATA[{
8
- "isMigrated": true
9
- }]]></component>
10
- <component name="ProjectRootManager" version="2" project-jdk-name="uv (tsql)" project-jdk-type="Python SDK" />
11
- </project>
@@ -1,10 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module version="4">
3
- <component name="PyDocumentationSettings">
4
- <option name="format" value="PLAIN" />
5
- <option name="myDocStringFormat" value="Plain" />
6
- </component>
7
- <component name="TestRunnerService">
8
- <option name="PROJECT_TEST_RUNNER" value="py.test" />
9
- </component>
10
- </module>
t_sql-2.1.1/.idea/vcs.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="" vcs="Git" />
5
- </component>
6
- </project>
@@ -1,124 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="AutoImportSettings">
4
- <option name="autoReloadType" value="SELECTIVE" />
5
- </component>
6
- <component name="ChangeListManager">
7
- <list default="true" id="059146b3-62bd-4ad4-890d-4356cf237b89" name="Changes" comment="">
8
- <change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
9
- <change beforePath="$PROJECT_DIR$/tests/test_mysql_integration.py" beforeDir="false" afterPath="$PROJECT_DIR$/tests/test_mysql_integration.py" afterDir="false" />
10
- <change beforePath="$PROJECT_DIR$/tests/test_query_builder.py" beforeDir="false" afterPath="$PROJECT_DIR$/tests/test_query_builder.py" afterDir="false" />
11
- <change beforePath="$PROJECT_DIR$/tests/test_sqlalchemy_integration.py" beforeDir="false" afterPath="$PROJECT_DIR$/tests/test_sqlalchemy_integration.py" afterDir="false" />
12
- <change beforePath="$PROJECT_DIR$/tests/test_sqlite_integration.py" beforeDir="false" afterPath="$PROJECT_DIR$/tests/test_sqlite_integration.py" afterDir="false" />
13
- <change beforePath="$PROJECT_DIR$/tsql/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/tsql/__init__.py" afterDir="false" />
14
- <change beforePath="$PROJECT_DIR$/tsql/query_builder.py" beforeDir="false" afterPath="$PROJECT_DIR$/tsql/query_builder.py" afterDir="false" />
15
- </list>
16
- <option name="SHOW_DIALOG" value="false" />
17
- <option name="HIGHLIGHT_CONFLICTS" value="true" />
18
- <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
19
- <option name="LAST_RESOLUTION" value="IGNORE" />
20
- </component>
21
- <component name="Git.Settings">
22
- <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
23
- </component>
24
- <component name="GitHubPullRequestSearchHistory">{
25
- &quot;lastFilter&quot;: {
26
- &quot;state&quot;: &quot;OPEN&quot;,
27
- &quot;assignee&quot;: &quot;nhumrich&quot;
28
- }
29
- }</component>
30
- <component name="GithubPullRequestsUISettings">{
31
- &quot;selectedUrlAndAccountId&quot;: {
32
- &quot;url&quot;: &quot;git@github.com:nhumrich/tsql.git&quot;,
33
- &quot;accountId&quot;: &quot;f308fc0d-c429-47fb-8e52-74bdc95408d8&quot;
34
- }
35
- }</component>
36
- <component name="ProjectColorInfo">{
37
- &quot;associatedIndex&quot;: 2
38
- }</component>
39
- <component name="ProjectId" id="33DagtaPqCq8RWQhigWGQcgOtLh" />
40
- <component name="ProjectViewState">
41
- <option name="compactDirectories" value="true" />
42
- <option name="hideEmptyMiddlePackages" value="true" />
43
- <option name="showLibraryContents" value="true" />
44
- </component>
45
- <component name="PropertiesComponent">{
46
- &quot;keyToString&quot;: {
47
- &quot;ModuleVcsDetector.initialDetectionPerformed&quot;: &quot;true&quot;,
48
- &quot;Python tests.pytest in test_sqlalchemy_integration.py.executor&quot;: &quot;Debug&quot;,
49
- &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
50
- &quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252&quot;: &quot;true&quot;,
51
- &quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
52
- &quot;git-widget-placeholder&quot;: &quot;main&quot;,
53
- &quot;junie.onboarding.icon.badge.shown&quot;: &quot;true&quot;,
54
- &quot;last_opened_file_path&quot;: &quot;/home/nhumrich/personal/tsql&quot;,
55
- &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
56
- &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
57
- &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
58
- &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
59
- &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
60
- &quot;to.speed.mode.migration.done&quot;: &quot;true&quot;,
61
- &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
62
- }
63
- }</component>
64
- <component name="RunManager">
65
- <configuration name="pytest in test_sqlalchemy_integration.py" type="tests" factoryName="py.test" temporary="true" nameIsGenerated="true">
66
- <module name="tsql" />
67
- <option name="ENV_FILES" value="" />
68
- <option name="INTERPRETER_OPTIONS" value="" />
69
- <option name="PARENT_ENVS" value="true" />
70
- <option name="SDK_HOME" value="" />
71
- <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
72
- <option name="IS_MODULE_SDK" value="true" />
73
- <option name="ADD_CONTENT_ROOTS" value="true" />
74
- <option name="ADD_SOURCE_ROOTS" value="true" />
75
- <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
76
- <option name="_new_keywords" value="&quot;&quot;" />
77
- <option name="_new_parameters" value="&quot;&quot;" />
78
- <option name="_new_additionalArguments" value="&quot;&quot;" />
79
- <option name="_new_target" value="&quot;$PROJECT_DIR$/tests/test_sqlalchemy_integration.py&quot;" />
80
- <option name="_new_targetType" value="&quot;PATH&quot;" />
81
- <method v="2" />
82
- </configuration>
83
- <recent_temporary>
84
- <list>
85
- <item itemvalue="Python tests.pytest in test_sqlalchemy_integration.py" />
86
- </list>
87
- </recent_temporary>
88
- </component>
89
- <component name="SharedIndexes">
90
- <attachedChunks>
91
- <set>
92
- <option value="bundled-js-predefined-d6986cc7102b-3aa1da707db6-JavaScript-PY-252.26830.99" />
93
- <option value="bundled-python-sdk-164cda30dcd9-0af03a5fa574-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-252.26830.99" />
94
- </set>
95
- </attachedChunks>
96
- </component>
97
- <component name="TaskManager">
98
- <task active="true" id="Default" summary="Default task">
99
- <changelist id="059146b3-62bd-4ad4-890d-4356cf237b89" name="Changes" comment="" />
100
- <created>1758854212149</created>
101
- <option name="number" value="Default" />
102
- <option name="presentableId" value="Default" />
103
- <updated>1758854212149</updated>
104
- </task>
105
- <servers />
106
- </component>
107
- <component name="TypeScriptGeneratedFilesManager">
108
- <option name="version" value="3" />
109
- </component>
110
- <component name="Vcs.Log.Tabs.Properties">
111
- <option name="TAB_STATES">
112
- <map>
113
- <entry key="MAIN">
114
- <value>
115
- <State />
116
- </value>
117
- </entry>
118
- </map>
119
- </option>
120
- </component>
121
- <component name="com.intellij.coverage.CoverageDataManagerImpl">
122
- <SUITE FILE_PATH="coverage/tsql$pytest_in_test_sqlalchemy_integration_py.coverage" NAME="pytest in test_sqlalchemy_integration.py Coverage Results" MODIFIED="1760138305802" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
123
- </component>
124
- </project>
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes