Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.2.0 update #7

Merged
merged 28 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ae690f7
Add setup.py
sfc-gh-jfreeberg May 13, 2023
2021826
In progress: exploring testing when using @udf
sfc-gh-jfreeberg May 13, 2023
e00a84b
Consolidate modules and update import
sfc-gh-jfreeberg Aug 2, 2023
336d068
Update package imports
sfc-gh-jfreeberg Aug 2, 2023
0712ac2
wrong command
sfc-gh-jfreeberg Aug 2, 2023
9af0dba
pylint fixes
sfc-gh-jfreeberg Aug 2, 2023
ef23edf
Update requirements.txt
sfc-gh-jfreeberg Aug 2, 2023
71d8c19
Update test_app.py
sfc-gh-jfreeberg Aug 2, 2023
8ca4f91
Addressing PR feedback
sfc-gh-jfreeberg Aug 4, 2023
9761a62
Update requirements.txt
sfc-gh-jfreeberg Aug 4, 2023
726419a
Update test_app.py
sfc-gh-jfreeberg Aug 4, 2023
ed88933
Revert "Update requirements.txt"
sfc-gh-jfreeberg Aug 4, 2023
6486426
Revert "Update test_app.py"
sfc-gh-jfreeberg Aug 4, 2023
c2d8461
Update environment.yml
sfc-gh-jfreeberg Aug 7, 2023
1fa3463
Update build-and-deploy.yml
sfc-gh-jfreeberg Aug 7, 2023
d22e6e4
Update build-and-deploy.yml
sfc-gh-jfreeberg Aug 7, 2023
9f82c3e
Update pr-checks.yml
sfc-gh-jfreeberg Aug 7, 2023
8bf8c9a
Update pr-checks.yml
sfc-gh-jfreeberg Aug 8, 2023
b27ae06
Update pr-checks.yml
sfc-gh-jfreeberg Aug 8, 2023
a46945f
Update pr-checks.yml
sfc-gh-jfreeberg Aug 8, 2023
0fd5bcd
Update environment.yml
sfc-gh-jfreeberg Aug 8, 2023
018294f
Update pr-checks.yml
sfc-gh-jfreeberg Aug 8, 2023
cdec873
Update environment.yml
sfc-gh-jfreeberg Aug 8, 2023
4daaab9
Update pr-checks.yml
sfc-gh-jfreeberg Aug 8, 2023
fcf66ca
Update pr-checks.yml
sfc-gh-jfreeberg Aug 8, 2023
53c44bc
Update README.md
sfc-gh-jfreeberg Aug 8, 2023
60e0169
Update build-and-deploy.yml
sfc-gh-jfreeberg Aug 8, 2023
b8e7ecd
Add role to env vars and update test
sfc-gh-jfreeberg Aug 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 22 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ Set the following environment variables with your Snowflake account information:

```bash
# Linux/MacOS
set SNOWSQL_ACCOUNT=<replace with your account identifer>
set SNOWSQL_USER=<replace with your username>
set SNOWSQL_PWD=<replace with your password>
set SNOWSQL_DATABASE=<replace with your database>
set SNOWSQL_SCHEMA=<replace with your schema>
set SNOWSQL_WAREHOUSE=<replace with your warehouse>
export SNOWSQL_ACCOUNT=<replace with your account identifer>
export SNOWSQL_USER=<replace with your username>
export SNOWSQL_ROLE=<replace with your role>
export SNOWSQL_PWD=<replace with your password>
export SNOWSQL_DATABASE=<replace with your database>
export SNOWSQL_SCHEMA=<replace with your schema>
export SNOWSQL_WAREHOUSE=<replace with your warehouse>
sfc-gh-jfreeberg marked this conversation as resolved.
Show resolved Hide resolved
```

```powershell
# Windows/PowerShell
$env:SNOWSQL_ACCOUNT = "<replace with your account identifer>"
$env:SNOWSQL_USER = "<replace with your username>"
$env:SNOWSQL_ROLE = "<replace with your role>"
$env:SNOWSQL_PWD = "<replace with your password>"
$env:SNOWSQL_DATABASE = "<replace with your database>"
$env:SNOWSQL_SCHEMA = "<replace with your schema>"
Expand All @@ -31,38 +33,37 @@ using the System Properties menu (on Windows).

sfc-gh-jfreeberg marked this conversation as resolved.
Show resolved Hide resolved
### Install dependencies

Set up a virtual environment using [Anaconda](https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#creating-an-environment-with-commands) or [virtualenv](https://docs.python.org/3/library/venv.html).

#### Anaconda
Create and activate a conda environment using [Anaconda](https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#creating-an-environment-with-commands):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that before we had instructions for virtualenv wont we support that? Still a lot of users use virtualenv

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also torn between the prescriptivism of recommending just conda or also keeping in instructions for virtualenv, since we do have that mentioned in our docs.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the VS Code integration we went with just conda for simplicity of ensuring environment similarity.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also torn, my concern was that if someone wants to use a package from PyPi when they deploy to the Snowflake server, the package will come from Conda. So I figured it'll be good to get them on the Conda train sooner so their packages are consistent


```bash
conda env create -f environment.yml
conda env create --file environment.yml
conda activate snowpark
```

#### Virtualenv
### Configure IDE

```bash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
#### VS Code

Press `Ctrl`+`Shift`+`P` to open the command palette, then select **Python: Select Interpreter** and select the **snowpark** interpreter under the **Conda** list.

#### PyCharm

Go to **File** > **Settings** > **Project** > **Python Interpreter** and select the snowpark interpreter.

## Prereqs

To develop your applications locally, you will need

- A Snowflake account
- Python 3.8
- Python 3.8 or greater
- An IDE or code editor (VS Code, PyCharm, etc.)

## Usage

Once you've set your credentials and installed the packages, you can test your connection to Snowflake by executing the stored procedure in [`app.py`](src/procs/app.py):

```
cd src
python procs/app.py
```bash
python src/app.py
```

You should see the following output:
Expand All @@ -80,8 +81,7 @@ You should see the following output:

You can run the test suite locally from the project root:

```
pip install -r requirements-test.txt
```bash
python -m pytest
```

Expand All @@ -90,12 +90,6 @@ python -m pytest
The GitHub Actions [workflow file](.github/workflows/build-and-deploy.yml) allows you to continously deploy your objects to Snowflake. When you're ready,
create secrets in your GitHub repository with the same name and values as the environment variables you created earler (`SNOWSQL_PWD`, `SNOWSQL_ACCOUNT`, etc.). The workflow will create a stage, upload the Python source code, and create the stored procedure object. For more information, see [`resources.sql`](resources.sql).

## Project Structure

- [procs/](src/procs/): Directory for stored procedures
- [udf/](src/udf/): Directory for your user-defined functions
- [util/](src/util/): Directory for methods/classes shared between UDFs and procedures

## Docs

- [Snowpark Developer Guide for Python](https://docs.snowflake.com/en/developer-guide/snowpark/python/index)
Expand Down
1 change: 0 additions & 1 deletion app.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
snowsql_config_path = ""
snowsql_connection_name = ""

[dev]
database = ""
schema = ""
role = ""
Expand Down
9 changes: 4 additions & 5 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ name: snowpark
channels:
- snowflake
dependencies:
- python=3.8
- python=3.9
- openssl=3.0.9 # Addresses this issue with oscrypto: https://github.com/wbond/oscrypto/issues/75
- pip
- snowflake-snowpark-python
- toml
- tomli
- pip:
- "-r requirements-test.txt"
- "-r requirements.txt"
- "--editable ."
2 changes: 0 additions & 2 deletions requirements-test.txt

This file was deleted.

4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
snowflake-snowpark-python
snowflake-snowpark-python[pandas]
tomli
toml
pytest
snowflake-vcrpy @ git+https://github.com/Snowflake-Labs/[email protected]
6 changes: 3 additions & 3 deletions resources.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ CREATE STAGE IF NOT EXISTS artifacts;
PUT file://&artifact_name @artifacts AUTO_COMPRESS=FALSE OVERWRITE=TRUE;

CREATE OR REPLACE PROCEDURE HELLO_WORLD_PROC()
RETURNS integer
RETURNS TABLE()
LANGUAGE PYTHON
RUNTIME_VERSION = 3.8
IMPORTS = ('@artifacts/&artifact_name')
HANDLER = 'src.procs.app.run'
HANDLER = 'src.app.run'
PACKAGES = ('pytest','snowflake-snowpark-python','tomli','toml');

CREATE OR REPLACE FUNCTION COMBINE(a String, b String)
RETURNS String
LANGUAGE PYTHON
RUNTIME_VERSION = 3.8
IMPORTS = ('@artifacts/&artifact_name')
HANDLER = 'src.udf.functions.combine'
HANDLER = 'src.functions.combine'
PACKAGES = ('pytest','snowflake-snowpark-python','tomli','toml');
12 changes: 12 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""
Run `conda env create --file environment.yaml` to create an editable
install of this project
"""

from setuptools import setup, find_packages

setup(
name="Example Snowpark Python project",
version="0.1.0",
packages=find_packages()
)
sfc-gh-jfreeberg marked this conversation as resolved.
Show resolved Hide resolved
File renamed without changes.
48 changes: 48 additions & 0 deletions src/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""
An example stored procedure. __main__ provides an entrypoint for local development
and testing.
"""

from snowflake.snowpark.session import Session
from snowflake.snowpark.dataframe import col, DataFrame
from snowflake.snowpark.functions import udf
from src import functions

def run(snowpark_session: Session) -> DataFrame:
"""
A sample stored procedure which creates a small DataFrame, prints it to the
console, and returns the number of rows in the table.
"""

combine_udf = udf(functions.combine)

schema = ["col_1", "col_2"]

data = [
("Welcome to ", "Snowflake!"),
("Learn more: ", "https://www.snowflake.com/snowpark/"),
]

df = snowpark_session.create_dataframe(data, schema)

df2 = df.select(combine_udf(col("col_1"), col("col_2")).as_("hello_world")).sort(
"hello_world", ascending=False
)

return df2


if __name__ == "__main__":
# This entrypoint is used for local development (`$ python src/procs/app.py`)

from src.util.local import get_env_var_config

print("Creating session...")
session = Session.builder.configs(get_env_var_config()).create()
session.add_import(functions.__file__, 'src.functions')

print("Running stored procedure...")
result = run(session)

print("Stored procedure complete:")
result.show()
2 changes: 1 addition & 1 deletion src/udf/functions.py → src/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
This module contains the UDFs for the project.
"""


def combine(string_a: str, string_b: str) -> str:
"""
A sample UDF implementation
"""

return string_a + string_b
57 changes: 0 additions & 57 deletions src/procs/app.py

This file was deleted.

Empty file removed src/udf/__init__.py
Empty file.
16 changes: 16 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Fixtures and configurations for the PyTest suite
"""

import pytest
from snowflake.snowpark.session import Session
from src.util.local import get_env_var_config

@pytest.fixture
def session(scope='module'):
# pylint: disable=unused-argument
"""
Creates a Session object for tests
"""

return Session.builder.configs(get_env_var_config()).create()
24 changes: 0 additions & 24 deletions test/procs/test_app.py

This file was deleted.

17 changes: 17 additions & 0 deletions test/test_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
Tests for the procedure module.
"""

from snowflake.snowpark.session import Session
from src import functions
from src.app import run

def test_app_dim(session: Session):
session.add_import(functions.__file__, 'src.functions')
expected = session.create_dataframe(
[["Welcome to Snowflake!"], ["Learn more: https://www.snowflake.com/snowpark/"]],
["hello_world"])

actual = run(session)

assert expected.collect() == actual.collect()
6 changes: 5 additions & 1 deletion test/udf/test_functions.py → test/test_functions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from src.udf.functions import combine
"""
Tests for the functions module.
"""

from src.functions import combine

def test_combine():
expected = "hello world"
actual = combine("hello ", "world")

assert expected == actual