Skip to content

Release/v2.1.0 #40

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

Merged
merged 50 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
9df5957
wip: adding pydantic for spaces and publish consume endpoints
ashish-bagri Feb 4, 2025
d7233ec
WIP: removed dataclass api, operations and utils
ashish-bagri Feb 5, 2025
abd654b
removed some operation classes
ashish-bagri Feb 7, 2025
3eeb3c7
fix tests
PabloPardoGarcia Feb 10, 2025
fcdb0d1
add deleted __init__
PabloPardoGarcia Feb 10, 2025
6fcc9a5
Remove unnecessary objects
PabloPardoGarcia Feb 10, 2025
a234e92
removed unusued operations object
ashish-bagri Feb 10, 2025
4169c00
delete unnecessary import
PabloPardoGarcia Feb 11, 2025
a59abcc
convert datamodel-generator to pydantic_v2
PabloPardoGarcia Feb 11, 2025
66dea2a
update API to v0.27.2
PabloPardoGarcia Feb 11, 2025
6fa7896
use GetDetailedSpacePipeline data model
PabloPardoGarcia Feb 11, 2025
3ab2b3b
format
PabloPardoGarcia Feb 11, 2025
6643b5f
fix pipeline response
ashish-bagri Feb 11, 2025
4b98551
Merge branch 'pydantic' of github.com:glassflow/glassflow-python-sdk …
ashish-bagri Feb 11, 2025
121b7f3
add secret top level object
PabloPardoGarcia Feb 11, 2025
0331f17
add secret top level object
PabloPardoGarcia Feb 11, 2025
81cf764
organize exceptions
PabloPardoGarcia Feb 11, 2025
6ddb0c0
add secret api calls
PabloPardoGarcia Feb 12, 2025
8e5c3b8
add secret tests
PabloPardoGarcia Feb 12, 2025
89781aa
format code
PabloPardoGarcia Feb 12, 2025
315fac2
add secrets to docs
PabloPardoGarcia Feb 12, 2025
1d225d7
fix docstring raises references
PabloPardoGarcia Feb 12, 2025
9849510
add docstrings for response data models
PabloPardoGarcia Feb 12, 2025
7b811dd
fix docstrings attributes types
PabloPardoGarcia Feb 12, 2025
89bca79
convert dataclass to pydantic
PabloPardoGarcia Feb 12, 2025
40d5a3a
add pydantic and python objects cross-references to docs
PabloPardoGarcia Feb 12, 2025
f1f2b8a
added a getting-started script
ashish-bagri Feb 12, 2025
af8ca35
remove type from response in docstrings
PabloPardoGarcia Feb 12, 2025
d6d461b
fix docstr types
PabloPardoGarcia Feb 12, 2025
3e0d133
add integration tests for list spaces and secrets
PabloPardoGarcia Feb 12, 2025
62ad3b2
format code
PabloPardoGarcia Feb 12, 2025
d194afe
sort methods
PabloPardoGarcia Feb 12, 2025
1bc64f9
accept connector secret refs
PabloPardoGarcia Feb 12, 2025
9407fb3
add source_conf to test case
PabloPardoGarcia Feb 12, 2025
215e3e7
exclude none fields from model dump
PabloPardoGarcia Feb 12, 2025
655f21e
format code
PabloPardoGarcia Feb 12, 2025
d00b074
add test to create pipeline with secrets
PabloPardoGarcia Feb 12, 2025
b9a5db6
use `event` method to get message
PabloPardoGarcia Feb 12, 2025
251250c
add event method
PabloPardoGarcia Feb 12, 2025
735ac6b
format code
PabloPardoGarcia Feb 12, 2025
d976290
Merge pull request #39 from glassflow/connector-secrets
PabloPardoGarcia Feb 12, 2025
93e416d
format code
PabloPardoGarcia Feb 12, 2025
2b842df
move cli code to separated module
PabloPardoGarcia Feb 12, 2025
c16778c
format code
PabloPardoGarcia Feb 12, 2025
5795ede
Merge pull request #41 from glassflow/getting-started
PabloPardoGarcia Feb 12, 2025
9477cfe
raise ConnectorConfigValueError when both connector config and config…
PabloPardoGarcia Feb 13, 2025
d55353e
remove setting pipeline connector with `config_secret_ref`
PabloPardoGarcia Feb 13, 2025
47f70c9
format code
PabloPardoGarcia Feb 13, 2025
8871c3d
filter out error logs from test
PabloPardoGarcia Feb 13, 2025
cdc9035
rename variable
PabloPardoGarcia Feb 13, 2025
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ dist/
build
.env
tests/reports
.coverage
.coverage
.idea/
3 changes: 2 additions & 1 deletion docs/reference.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
::: src.glassflow.client
::: src.glassflow.pipeline
::: src.glassflow.pipeline_data
::: src.glassflow.secret
::: src.glassflow.space
::: src.glassflow.config
::: src.glassflow.models.errors
::: src.glassflow.models.operations
::: src.glassflow.models.responses
22 changes: 12 additions & 10 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,7 @@ add-noqa: generate-api-data-models
echo "Add noqa comment ..."
sed -i '' -e '1s/^/# ruff: noqa\n/' $(API_DATA_MODELS)


add-dataclass-json-decorators: add-noqa
echo "Import dataclass_json ..."
sed -i '' -e '/^from __future__ import annotations/a\'$$'\n''from dataclasses_json import dataclass_json' $(API_DATA_MODELS)


echo "Add dataclass_json decorators ..."
sed -i '' -e '/@dataclass/ i\'$$'\n''@dataclass_json\''' $(API_DATA_MODELS)

generate: add-dataclass-json-decorators
generate: add-noqa

include .env
export
Expand All @@ -32,3 +23,14 @@ lint:

formatter:
ruff format --check .

fix-format:
ruff format .

fix-lint:
ruff check --fix .

fix: fix-format fix-lint

serve-docs-locally:
mkdocs serve
6 changes: 5 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ plugins:
handlers:
python:
import:
- url: https://docs.python-requests.org/en/master/objects.inv
- url: https://docs.python.org/3/objects.inv # Add Python's objects.inv
domains: [ std, py ]
- url: https://docs.python-requests.org/en/master/objects.inv # Add requests objects.inv
domains: [ std, py ]
- url: https://docs.pydantic.dev/latest/objects.inv # Add Pydantic's objects.inv
domains: [ std, py ]
options:
members_order: source
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ convention = "google"
field-constraints = true
snake-case-field = true
strip-default-none = false
target-python-version = "3.7"
target-python-version = "3.8"
use-title-as-name = true
disable-timestamp = true
enable-version-header = true
use-double-quotes = true
use-subclass-enum=true
use-standard-collections=true
input-file-type = "openapi"
output-model-type = "dataclasses.dataclass"
output-model-type = "pydantic_v2.BaseModel"
24 changes: 15 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setuptools.setup(
name="glassflow",
version="2.0.8",
version="2.1.0",
author="glassflow",
description="GlassFlow Python Client SDK",
url="https://www.glassflow.dev/docs",
Expand All @@ -22,7 +22,7 @@
"urllib3==1.26.15",
"certifi>=2023.7.22",
"charset-normalizer>=3.2.0",
"dataclasses-json>=0.6.4",
"pydantic>=2.10.6",
"idna>=3.4",
"jsonpath-python>=1.0.6 ",
"marshmallow>=3.19.0",
Expand All @@ -34,19 +34,25 @@
"typing-inspect>=0.9.0",
"typing_extensions>=4.7.1",
"python-dotenv==1.0.1",
"eval_type_backport>=0.2.0",
],
extras_require={
"dev": [
"pylint==2.16.2",
"pytest==8.3.2",
"pytest-cov==5.0.0",
"datamodel-code-generator[http]==0.26.0",
"requests-mock==1.12.1",
"isort==5.13.2",
"ruff==0.6.3",
"pylint>=2.16.2",
"pytest>=8.3.2",
"pytest-cov>=5.0.0",
"datamodel-code-generator[http]>=0.27.0",
"requests-mock>=1.12.1",
"isort>=5.13.2",
"ruff>=0.9.0",
]
},
package_dir={"": "src"},
python_requires=">=3.8",
package_data={"glassflow": ["py.typed"]},
entry_points={
"console_scripts": [
"glassflow = cli.cli:glassflow",
],
},
)
Empty file added src/cli/__init__.py
Empty file.
43 changes: 43 additions & 0 deletions src/cli/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import click

from .commands import get_started


@click.group()
def glassflow():
"""Glassflow CLI - Manage and control Glassflow SDK"""
pass


@click.command()
@click.argument("command", required=False)
def help(command):
"""Displays help information about Glassflow CLI and its commands."""

commands = {
"get-started": "Initialize Glassflow with an access token.\nUsage: "
"glassflow get-started --token YOUR_TOKEN",
"help": "Shows help information.\nUsage: glassflow help [command]",
}

if command:
if command in commands:
click.echo(f"ℹ️ Help for `{command}`:\n{commands[command]}")
else:
click.echo(
f"❌ Unknown command: `{command}`. Run `glassflow help` for a "
f"list of commands."
)
else:
click.echo("📖 Glassflow CLI Help:")
for cmd, desc in commands.items():
click.echo(f" ➜ {cmd}: {desc.splitlines()[0]}")
click.echo("\nRun `glassflow help <command>` for more details.")


# Add commands to CLI group
glassflow.add_command(get_started)
glassflow.add_command(help)

if __name__ == "__main__":
glassflow()
1 change: 1 addition & 0 deletions src/cli/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .get_started import get_started as get_started
107 changes: 107 additions & 0 deletions src/cli/commands/get_started.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import os

import click
from dotenv import load_dotenv


@click.command()
@click.option(
"--personal-access-token", "-pat", default=None, help="Personal access token."
)
@click.option(
"--env-file",
"-e",
default=".env",
help="Path to the .env file (default: .env in current directory).",
)
def get_started(personal_access_token, env_file):
"""Displays a welcome message and setup instructions."""

# Load token from .env if not provided in CLI
if personal_access_token is None:
if os.path.exists(env_file):
load_dotenv(env_file) # Load environment variables
personal_access_token = os.getenv("PERSONAL_ACCESS_TOKEN")
else:
click.echo("⚠️ No token provided and .env file not found!", err=True)
return

if not personal_access_token:
click.echo("❌ Error: Personal access token is required.", err=True)
return

click.echo("🚀 Welcome to Glassflow! \n")
click.echo(
f"🔑 Using Personal Access Token: {personal_access_token[:4]}... "
f"(hidden for security)"
)
click.echo("\n📝 In this getting started guide, we will do the following:")
click.echo("1. Define a data transformation function in Python.\n")
click.echo("2. Create a pipeline with the function.\n")
click.echo("3. Send events to the pipeline.\n")
click.echo("4. Consume transformed events in real-time from the pipeline\n")
click.echo("5. Monitor the pipeline and view logs.\n")

filename = create_transformation_function()
pipeline = create_space_pipeline(personal_access_token, filename)
send_consume_events(pipeline)

click.echo(
"\n🎉 Congratulations! You have successfully created a pipeline and sent"
" events to it.\n"
)
click.echo(
"💻 View the logs and monitor the Pipeline in the "
f"Glassflow Web App at https://app.glassflow.dev/pipelines/{pipeline.id}"
)


def create_transformation_function(filename="transform_getting_started.py"):
file_content = """import json
import logging

def handler(data: dict, log: logging.Logger):
log.info("Echo: " + json.dumps(data))
data['transformed_by'] = "glassflow"

return data
"""
with open(filename, "w") as f:
f.write(file_content)
click.echo(f"✅ Transformation function created in {filename}")
click.echo("The transformation function is:\n")
click.echo(file_content)
click.echo("📝 You can modify the transformation function in the file.")
return filename


def create_space_pipeline(personal_access_token, transform_filename):
import glassflow

# create glassflow client to interact with GlassFlow
client = glassflow.GlassFlowClient(personal_access_token=personal_access_token)
example_space = client.create_space(name="getting-started")
pipeline = client.create_pipeline(
name="getting-started-pipeline",
transformation_file=transform_filename,
space_id=example_space.id,
)
click.echo(f"✅ Created a pipeline with pipeline_id {pipeline.id}")
return pipeline


def send_consume_events(pipeline):
click.echo("🔄 Sending some generated events to pipeline .....")
data_source = pipeline.get_source()
for i in range(10):
event = {"data": f"hello GF {i}"}
res = data_source.publish(event)
if res.status_code == 200:
click.echo(f"Sent event: {event}")

click.echo("📡 Consuming transformed events from the pipeline")
data_sink = pipeline.get_sink()
for _ in range(10):
resp = data_sink.consume()
if resp.status_code == 200:
click.echo(f"Consumed event: {resp.event()} ")
3 changes: 3 additions & 0 deletions src/glassflow/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from .client import GlassFlowClient as GlassFlowClient
from .config import GlassFlowConfig as GlassFlowConfig
from .models import api as internal # noqa: F401
from .models import errors as errors
from .models import responses as responses
from .pipeline import Pipeline as Pipeline
from .pipeline_data import PipelineDataSink as PipelineDataSink
from .pipeline_data import PipelineDataSource as PipelineDataSource
from .secret import Secret as Secret
from .space import Space as Space
Loading
Loading