From 1dca4d223c3c3adcc0a9daa3832824d5d6eb1d18 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 10:31:31 +0200 Subject: [PATCH 01/29] support "bool[pyarrow]" columns --- bcpandas/main.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/bcpandas/main.py b/bcpandas/main.py index 4b94801..7ef858a 100644 --- a/bcpandas/main.py +++ b/bcpandas/main.py @@ -441,7 +441,16 @@ def to_sql( # save to temp path csv_file_path = get_temp_file(work_directory) # replace bools with 1 or 0, this is what pandas native does when writing to SQL Server - df.replace({True: 1, False: 0}).to_csv( + df_out = df.assign( + **{ + col: lambda df: df[col].map({True: 1, False: 0}).astype(pd.Int8Dtype()) + for col, dtype in df.dtypes[ + (df.dtypes == "bool[pyarrow]") | (df.dtypes == "bool") + ].items() + } + ) + # write to CSV + df_out.replace({True: 1, False: 0}).to_csv( path_or_buf=csv_file_path, sep=delim, header=False, From 4dd6c9697ebcb381e1342bf600782a311d30f586 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 10:37:59 +0200 Subject: [PATCH 02/29] fix pre-commit --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4e33fa2..4823226 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,6 +6,6 @@ version: 2 updates: - package-ecosystem: "uv" - directory: "/" # Location of package manifests + directory: "/" # Location of package manifests schedule: interval: "weekly" From bb7d658e55ac0afa51d1622780dcdf156d355fef Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 10:41:43 +0200 Subject: [PATCH 03/29] upgrade ubuntu version --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 109e6fb..04fdafc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ concurrency: jobs: test: name: Tests - Python ${{ matrix.python-version }} - Resolution Strat ${{ matrix.uv-resolution-strategy }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: fail-fast: true matrix: From 81b9e20059e32d303d19d685c7a222e1db14539c Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 11:15:00 +0200 Subject: [PATCH 04/29] The nullable bool is called boolean. Unfortunately the dtype magic cannot compare all boolean types with one comparison. --- bcpandas/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bcpandas/main.py b/bcpandas/main.py index 7ef858a..785bb5e 100644 --- a/bcpandas/main.py +++ b/bcpandas/main.py @@ -445,7 +445,7 @@ def to_sql( **{ col: lambda df: df[col].map({True: 1, False: 0}).astype(pd.Int8Dtype()) for col, dtype in df.dtypes[ - (df.dtypes == "bool[pyarrow]") | (df.dtypes == "bool") + (df.dtypes == "bool[pyarrow]") | (df.dtypes == "bool") | (df.dtypes == "boolean") ].items() } ) From 04c86e657ad6171aff2f0819a7735833409e7d00 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 11:17:36 +0200 Subject: [PATCH 05/29] Debug CI problem with bcp installation --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04fdafc..4a755d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,9 @@ jobs: curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list sudo apt-get update sudo apt-get install mssql-tools unixodbc-dev + ls /opt + ls /opt/mssql-tools + ls /opt/mssql-tools/bin echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc source ~/.bashrc From 925204e024b7076f75342cbbfe00defc17ab4d51 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 11:20:52 +0200 Subject: [PATCH 06/29] Debug CI --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a755d2..5946780 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,7 +53,7 @@ jobs: run: | # https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup-tools?view=sql-server-ver15#ubuntu curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - - curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list + curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list sudo apt-get update sudo apt-get install mssql-tools unixodbc-dev ls /opt @@ -61,6 +61,11 @@ jobs: ls /opt/mssql-tools/bin echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc source ~/.bashrc + echo test bcp + which bcp + /opt/mssql-tools/bin/bcp -v + echo __ bashrc __ + cat ~/.bashrc - name: Test BCP run: bcp -v From 2831393a498bdc0d75e4b2b5d9cce1b55ffb43c2 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 11:24:50 +0200 Subject: [PATCH 07/29] Debug CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5946780..e693d78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list sudo apt-get update - sudo apt-get install mssql-tools unixodbc-dev + sudo apt-get install mssql-tools18 unixodbc-dev ls /opt ls /opt/mssql-tools ls /opt/mssql-tools/bin From 9a2b436fb800fc8e809c9c8eb9005994c42a2798 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 11:26:27 +0200 Subject: [PATCH 08/29] Debug CI --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e693d78..b329fe3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,13 +57,13 @@ jobs: sudo apt-get update sudo apt-get install mssql-tools18 unixodbc-dev ls /opt - ls /opt/mssql-tools - ls /opt/mssql-tools/bin - echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc + ls /opt/mssql-tools18 + ls /opt/mssql-tools18/bin + echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc source ~/.bashrc echo test bcp which bcp - /opt/mssql-tools/bin/bcp -v + /opt/mssql-tools19/bin/bcp -v echo __ bashrc __ cat ~/.bashrc From 3e284cac2aa5d3ac9d65ab9d1c0b04dde59ddd9d Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 11:29:33 +0200 Subject: [PATCH 09/29] Debug CI --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b329fe3..daca981 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,16 +56,16 @@ jobs: curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list sudo apt-get update sudo apt-get install mssql-tools18 unixodbc-dev - ls /opt - ls /opt/mssql-tools18 + echo ls /opt/mssql-tools18/bin ls /opt/mssql-tools18/bin + echo echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc source ~/.bashrc echo test bcp which bcp - /opt/mssql-tools19/bin/bcp -v echo __ bashrc __ cat ~/.bashrc + /opt/mssql-tools18/bin/bcp -v - name: Test BCP run: bcp -v From ee2b48db5b38d01740362cc330048fdc2654673f Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 12:23:21 +0200 Subject: [PATCH 10/29] Debug CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index daca981..730cfb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,10 +62,10 @@ jobs: echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc source ~/.bashrc echo test bcp - which bcp echo __ bashrc __ cat ~/.bashrc /opt/mssql-tools18/bin/bcp -v + which bcp - name: Test BCP run: bcp -v From 4b6c6a609833df9314103b04a4531f457c585c3e Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 13:12:46 +0200 Subject: [PATCH 11/29] Debug CI --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 730cfb6..4f6ac3f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,7 @@ jobs: echo echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc source ~/.bashrc + echo $PATH echo test bcp echo __ bashrc __ cat ~/.bashrc From 3c77ad4fac3edc2a8af3bc6dd580777e7718408c Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 13:13:14 +0200 Subject: [PATCH 12/29] Debug CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f6ac3f..3236906 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list sudo apt-get update sudo apt-get install mssql-tools18 unixodbc-dev - echo ls /opt/mssql-tools18/bin + echo ls -l /opt/mssql-tools18/bin ls /opt/mssql-tools18/bin echo echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc From a5df3eb51ebcdbd31c6278555e51cf0d1b07770e Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 13:56:04 +0200 Subject: [PATCH 13/29] Debug CI --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3236906..61acba8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,11 +57,13 @@ jobs: sudo apt-get update sudo apt-get install mssql-tools18 unixodbc-dev echo ls -l /opt/mssql-tools18/bin - ls /opt/mssql-tools18/bin + ls -l /opt/mssql-tools18/bin echo echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc - source ~/.bashrc + . ~/.bashrc echo $PATH + # somehow sourcing ~/.bashrc does not work + export PATH="$PATH:/opt/mssql-tools18/bin" echo test bcp echo __ bashrc __ cat ~/.bashrc From bb0b286a9ae7d3d3fc42f262d5691e3ddaca9e6e Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 15:31:46 +0200 Subject: [PATCH 14/29] Debug CI --- .github/workflows/ci.yml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61acba8..3ffdd8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,19 +56,8 @@ jobs: curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list sudo apt-get update sudo apt-get install mssql-tools18 unixodbc-dev - echo ls -l /opt/mssql-tools18/bin ls -l /opt/mssql-tools18/bin - echo - echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc - . ~/.bashrc - echo $PATH - # somehow sourcing ~/.bashrc does not work - export PATH="$PATH:/opt/mssql-tools18/bin" - echo test bcp - echo __ bashrc __ - cat ~/.bashrc - /opt/mssql-tools18/bin/bcp -v - which bcp + echo /opt/mssql-tools18/bin >> $GITHUB_PATH - name: Test BCP run: bcp -v From e3acb2ed88522d851416f2f7559854b8146e8702 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 15:38:48 +0200 Subject: [PATCH 15/29] Debug CI --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ffdd8c..8d9bede 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,6 +58,11 @@ jobs: sudo apt-get install mssql-tools18 unixodbc-dev ls -l /opt/mssql-tools18/bin echo /opt/mssql-tools18/bin >> $GITHUB_PATH + ls -l /opt/ + find /opt -iname odbcinst + find /etc -iname odbcinst.ini + which odbcinst + odbcinst -j - name: Test BCP run: bcp -v From e5f0e398ca06d1540afbf3d8e95d9869fab83440 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 15:42:45 +0200 Subject: [PATCH 16/29] Debug CI --- .github/workflows/ci.yml | 3 ++- README.md | 8 ++++---- benchmarks/read_sql/conftest.py | 2 +- tests/conftest.py | 2 +- tests/utils.py | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d9bede..fedb17b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,12 +55,13 @@ jobs: curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list sudo apt-get update - sudo apt-get install mssql-tools18 unixodbc-dev + sudo apt-get install mssql-tools18 unixodbc-dev odbcinst ls -l /opt/mssql-tools18/bin echo /opt/mssql-tools18/bin >> $GITHUB_PATH ls -l /opt/ find /opt -iname odbcinst find /etc -iname odbcinst.ini + cat /etc/odbcinst.ini which odbcinst odbcinst -j diff --git a/README.md b/README.md index d212717..991ac9e 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ The user has 2 options when constructing it. In [2]: creds = SqlCreds('my_server', 'my_db', 'my_username', 'my_password') In [3]: creds.engine - Out[3]: Engine(mssql+pyodbc:///?odbc_connect=Driver={ODBC Driver 17 for SQL Server};Server=tcp:my_server,1433;Database=my_db;UID=my_username;PWD=my_password) + Out[3]: Engine(mssql+pyodbc:///?odbc_connect=Driver={ODBC Driver 18 for SQL Server};Server=tcp:my_server,1433;Database=my_db;UID=my_username;PWD=my_password) ``` @@ -210,10 +210,10 @@ The user has 2 options when constructing it. In [4]: creds2 = SqlCreds.from_engine(creds.engine) In [5]: creds2.engine - Out[5]: Engine(mssql+pyodbc:///?odbc_connect=Driver={ODBC Driver 17 for SQL Server};Server=tcp:my_server,1433;Database=my_db;UID=my_username;PWD=my_password) + Out[5]: Engine(mssql+pyodbc:///?odbc_connect=Driver={ODBC Driver 18 for SQL Server};Server=tcp:my_server,1433;Database=my_db;UID=my_username;PWD=my_password) In [6]: creds2 - Out[6]: SqlCreds(server='my_server', database='my_db', username='my_username', with_krb_auth=False, engine=Engine(mssql+pyodbc:///?odbc_connect=Driver={ODBC Driver 17 for SQL Server};Server=tcp:my_server,1433;Database=my_db;UID=my_username;PWD=my_password), password=[REDACTED]) + Out[6]: SqlCreds(server='my_server', database='my_db', username='my_username', with_krb_auth=False, engine=Engine(mssql+pyodbc:///?odbc_connect=Driver={ODBC Driver 18 for SQL Server};Server=tcp:my_server,1433;Database=my_db;UID=my_username;PWD=my_password), password=[REDACTED]) ``` ### Recommended Usage @@ -293,7 +293,7 @@ my_df['some_text_column'].str.contains('\|').sum() If you get this error message when writing to the database: ``` -Error = [Microsoft][ODBC Driver 17 for SQL Server]Incorrect host-column number found in BCP format-file +Error = [Microsoft][ODBC Driver 18 for SQL Server]Incorrect host-column number found in BCP format-file ``` Try replacing any space characters in your column names, with a command like `my_df.columns = my_df.columns.str.replace(' ','_')` ([source](https://github.com/yehoshuadimarsky/bcpandas/issues/30)). diff --git a/benchmarks/read_sql/conftest.py b/benchmarks/read_sql/conftest.py index 6ca5025..aae297e 100644 --- a/benchmarks/read_sql/conftest.py +++ b/benchmarks/read_sql/conftest.py @@ -61,7 +61,7 @@ def sql_creds(): @pytest.fixture(scope="session") def pyodbc_creds(database): db_url = ( - "Driver={ODBC Driver 17 for SQL Server};" + "Driver={ODBC Driver 18 for SQL Server};" + f"Server={docker_db_obj.address};" + f"Database={_db_name};UID=sa;PWD={docker_db_obj.sa_sql_password};" ) diff --git a/tests/conftest.py b/tests/conftest.py index 59f0230..b3adc8a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -64,7 +64,7 @@ def sql_creds(): @pytest.fixture(scope="session") def pyodbc_creds(database): db_url = ( - "Driver={ODBC Driver 17 for SQL Server};" + "Driver={ODBC Driver 18 for SQL Server};" + f"Server={docker_db_obj.address};" + f"Database={_db_name};UID=sa;PWD={docker_db_obj.sa_sql_password};" ) diff --git a/tests/utils.py b/tests/utils.py index df1c38d..4cabc95 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -161,7 +161,7 @@ def remove(self): def create_engine(self, db_name="master") -> sa.engine.Engine: """Creates SQLAlchemy pyodbc engine for connecting to specified database (default master) as SA user""" db_url = ( - "Driver={ODBC Driver 17 for SQL Server};" + "Driver={ODBC Driver 18 for SQL Server};" + f"Server={self.address};Database={db_name};UID=sa;PWD={self.sa_sql_password};" ) return sa.engine.create_engine( From 1c1b8dbb7ba8c6cf52f80ede28fa2ac9db674ec3 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 16:49:43 +0200 Subject: [PATCH 17/29] Debug CI --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fedb17b..8362cd4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,9 +61,10 @@ jobs: ls -l /opt/ find /opt -iname odbcinst find /etc -iname odbcinst.ini - cat /etc/odbcinst.ini - which odbcinst - odbcinst -j + echo + find / -iname "*odbcinst*" + sudo cat /etc/odbcinst.ini + sudo odbcinst -j - name: Test BCP run: bcp -v From d3b6efc250154e8fc4d37dc66822d6ccfa080374 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 17:12:20 +0200 Subject: [PATCH 18/29] Debug CI --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8362cd4..3152af6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,6 +51,7 @@ jobs: - name: Install BCP Utility run: | + set -x # https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup-tools?view=sql-server-ver15#ubuntu curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - curl https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list @@ -63,8 +64,8 @@ jobs: find /etc -iname odbcinst.ini echo find / -iname "*odbcinst*" - sudo cat /etc/odbcinst.ini - sudo odbcinst -j +# sudo cat /etc/odbcinst.ini +# sudo odbcinst -j - name: Test BCP run: bcp -v From 37e0edb35cf127a06cced5a1aa0d36d47ed5e493 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 17:26:32 +0200 Subject: [PATCH 19/29] Debug CI --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3152af6..f50b790 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,8 +62,7 @@ jobs: ls -l /opt/ find /opt -iname odbcinst find /etc -iname odbcinst.ini - echo - find / -iname "*odbcinst*" + find /usr -iname "*odbcinst*" # sudo cat /etc/odbcinst.ini # sudo odbcinst -j From 9993a4212fec89b93707a4ba9c125163e887f54f Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 17:55:14 +0200 Subject: [PATCH 20/29] Debug CI --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f50b790..06972ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,7 +62,8 @@ jobs: ls -l /opt/ find /opt -iname odbcinst find /etc -iname odbcinst.ini - find /usr -iname "*odbcinst*" + cat /etc/odbcinst.ini +# find /usr -iname "*odbcinst*" # sudo cat /etc/odbcinst.ini # sudo odbcinst -j From 33112f0a2572783536d2f6b1b798acea09d7918f Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 19:04:47 +0200 Subject: [PATCH 21/29] Debug CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 06972ef..6814c6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,7 +62,7 @@ jobs: ls -l /opt/ find /opt -iname odbcinst find /etc -iname odbcinst.ini - cat /etc/odbcinst.ini +# cat /etc/odbcinst.ini # find /usr -iname "*odbcinst*" # sudo cat /etc/odbcinst.ini # sudo odbcinst -j From a4a028944a2e19a867482a9530b5f9d201be36f8 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 19:36:15 +0200 Subject: [PATCH 22/29] Debug CI --- .github/workflows/ci.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6814c6f..685e886 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,8 +28,10 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] - uv-resolution-strategy: ["lowest-direct", "highest"] + python-version: ["3.12"] + uv-resolution-strategy: ["highest"] + # python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + # uv-resolution-strategy: ["lowest-direct", "highest"] steps: - name: Checkout uses: actions/checkout@v3 @@ -60,9 +62,9 @@ jobs: ls -l /opt/mssql-tools18/bin echo /opt/mssql-tools18/bin >> $GITHUB_PATH ls -l /opt/ - find /opt -iname odbcinst - find /etc -iname odbcinst.ini -# cat /etc/odbcinst.ini + cat /etc/odbcinst.ini +# find /opt -iname odbcinst +# find /etc -iname odbcinst.ini # find /usr -iname "*odbcinst*" # sudo cat /etc/odbcinst.ini # sudo odbcinst -j From 39aa72a8696c98126485b3002506c2fe8d6d1055 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Thu, 19 Jun 2025 22:39:33 +0200 Subject: [PATCH 23/29] Fix CI. The mssql container by default comes with self-signed certificate. So encrypt=no helps to establish connection still. --- .github/workflows/ci.yml | 5 ----- tests/conftest.py | 3 ++- tests/test_sqlcreds.py | 1 + tests/utils.py | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 685e886..18df29e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,11 +63,6 @@ jobs: echo /opt/mssql-tools18/bin >> $GITHUB_PATH ls -l /opt/ cat /etc/odbcinst.ini -# find /opt -iname odbcinst -# find /etc -iname odbcinst.ini -# find /usr -iname "*odbcinst*" -# sudo cat /etc/odbcinst.ini -# sudo odbcinst -j - name: Test BCP run: bcp -v diff --git a/tests/conftest.py b/tests/conftest.py index b3adc8a..f29743c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -57,6 +57,7 @@ def sql_creds(): database=_db_name, username="sa", password=docker_db_obj.sa_sql_password, + odbc_kwargs=dict(encrypt="no"), ) return creds @@ -66,7 +67,7 @@ def pyodbc_creds(database): db_url = ( "Driver={ODBC Driver 18 for SQL Server};" + f"Server={docker_db_obj.address};" - + f"Database={_db_name};UID=sa;PWD={docker_db_obj.sa_sql_password};" + + f"Database={_db_name};UID=sa;PWD={docker_db_obj.sa_sql_password};encrypt=no" ) engine = sa.engine.create_engine( f"mssql+pyodbc:///?odbc_connect={urllib.parse.quote_plus(db_url)}" diff --git a/tests/test_sqlcreds.py b/tests/test_sqlcreds.py index 6cbaf03..a5875ed 100644 --- a/tests/test_sqlcreds.py +++ b/tests/test_sqlcreds.py @@ -438,6 +438,7 @@ def test_sqlcreds_connection_from_sqlalchemy(sql_creds): f"Database={sql_creds.database};" f"UID={sql_creds.username};" f"PWD={sql_creds.password};" + f"encrypt={sql_creds.odbc_kwargs.get('encrypt', 'no')};" ) params = quote_plus(conn_str) diff --git a/tests/utils.py b/tests/utils.py index 4cabc95..31db9bf 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -162,7 +162,7 @@ def create_engine(self, db_name="master") -> sa.engine.Engine: """Creates SQLAlchemy pyodbc engine for connecting to specified database (default master) as SA user""" db_url = ( "Driver={ODBC Driver 18 for SQL Server};" - + f"Server={self.address};Database={db_name};UID=sa;PWD={self.sa_sql_password};" + + f"Server={self.address};Database={db_name};UID=sa;PWD={self.sa_sql_password};encrypt=no" ) return sa.engine.create_engine( f"mssql+pyodbc:///?odbc_connect={urllib.parse.quote_plus(db_url)}" From 344be436b22f93a0e1962854429a47b9ec6c9267 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Fri, 20 Jun 2025 09:33:37 +0200 Subject: [PATCH 24/29] Fix CI. One more encrypt=no. --- tests/test_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_utils.py b/tests/test_utils.py index 1ef63a6..e784a2e 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -202,6 +202,7 @@ def test_bcp_login_failure(sql_creds: SqlCreds): database=sql_creds.database, username=sql_creds.username, password="mywrongpassword", + odbc_kwargs=dict(encrypt="no"), ) df = pd.DataFrame([{"col1": "value"}]) with tempfile.TemporaryDirectory() as tmpdir: From 09bcc1f232ba88e6f7082396d3c26ac25c69e8fc Mon Sep 17 00:00:00 2001 From: windiana42 Date: Fri, 20 Jun 2025 09:50:19 +0200 Subject: [PATCH 25/29] Expand CI again. --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18df29e..3b67c15 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,10 +28,8 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.12"] - uv-resolution-strategy: ["highest"] - # python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] - # uv-resolution-strategy: ["lowest-direct", "highest"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + uv-resolution-strategy: ["lowest-direct", "highest"] steps: - name: Checkout uses: actions/checkout@v3 From 568d2ff5fab21c44dca136e0ff482a1cbc8540d6 Mon Sep 17 00:00:00 2001 From: windiana42 Date: Fri, 20 Jun 2025 17:18:02 +0200 Subject: [PATCH 26/29] Fix lambda binding bug. --- bcpandas/main.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bcpandas/main.py b/bcpandas/main.py index 785bb5e..bd2d50a 100644 --- a/bcpandas/main.py +++ b/bcpandas/main.py @@ -7,6 +7,7 @@ import csv import logging import os +from copy import copy from pathlib import Path from textwrap import dedent from typing import Dict, List, Optional, Union @@ -441,9 +442,13 @@ def to_sql( # save to temp path csv_file_path = get_temp_file(work_directory) # replace bools with 1 or 0, this is what pandas native does when writing to SQL Server + # attention: the `(lambda col: lambda...)(copy(col))` part looks odd but is + # needed to ensure loop iterations create lambdas working on different columns. df_out = df.assign( **{ - col: lambda df: df[col].map({True: 1, False: 0}).astype(pd.Int8Dtype()) + col: (lambda col: lambda df: df[col].map({True: 1, False: 0}).astype(pd.Int8Dtype()))( + copy(col) + ) for col, dtype in df.dtypes[ (df.dtypes == "bool[pyarrow]") | (df.dtypes == "bool") | (df.dtypes == "boolean") ].items() From 5dc4c25629a33eef69815fc775fcd27469e1fa09 Mon Sep 17 00:00:00 2001 From: windiana42 <61181806+windiana42@users.noreply.github.com> Date: Mon, 23 Jun 2025 17:08:14 +0200 Subject: [PATCH 27/29] Remove original boolean replacement in bcpandas/main.py --- bcpandas/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bcpandas/main.py b/bcpandas/main.py index bd2d50a..e4a3405 100644 --- a/bcpandas/main.py +++ b/bcpandas/main.py @@ -455,7 +455,7 @@ def to_sql( } ) # write to CSV - df_out.replace({True: 1, False: 0}).to_csv( + df_out.to_csv( path_or_buf=csv_file_path, sep=delim, header=False, From ae0cca8ae335d465984ac6337b0a874979e4a596 Mon Sep 17 00:00:00 2001 From: windiana42 <61181806+windiana42@users.noreply.github.com> Date: Mon, 23 Jun 2025 21:45:43 +0200 Subject: [PATCH 28/29] Implemented suggestion in bcpandas/main.py --- bcpandas/main.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bcpandas/main.py b/bcpandas/main.py index e4a3405..66c1ba0 100644 --- a/bcpandas/main.py +++ b/bcpandas/main.py @@ -446,9 +446,7 @@ def to_sql( # needed to ensure loop iterations create lambdas working on different columns. df_out = df.assign( **{ - col: (lambda col: lambda df: df[col].map({True: 1, False: 0}).astype(pd.Int8Dtype()))( - copy(col) - ) + col: lambda df, col=col: df[col].map({True: 1, False: 0}).astype(pd.Int8Dtype()) for col, dtype in df.dtypes[ (df.dtypes == "bool[pyarrow]") | (df.dtypes == "bool") | (df.dtypes == "boolean") ].items() From 31ab7b9e64230758ed1f3956d34ba9ca5fbf36cb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Jun 2025 19:45:53 +0000 Subject: [PATCH 29/29] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- bcpandas/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bcpandas/main.py b/bcpandas/main.py index 66c1ba0..af1b6c3 100644 --- a/bcpandas/main.py +++ b/bcpandas/main.py @@ -7,7 +7,6 @@ import csv import logging import os -from copy import copy from pathlib import Path from textwrap import dedent from typing import Dict, List, Optional, Union