Skip to content

Commit 53dedce

Browse files
committed
🔧 Add dotenv file support to example API workflow
1 parent 9b289ba commit 53dedce

File tree

1 file changed

+85
-2
lines changed

1 file changed

+85
-2
lines changed

example/example_api_workflow.py

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,24 @@
2222
2323
All configuration is explicitly passed to the ConnectorController and other
2424
components, eliminating reliance on implicit environment variables.
25+
26+
Configuration can be provided via environment variables or loaded from a
27+
dotenv file using the --env-file option. This allows you to easily switch
28+
between different environment configurations.
29+
30+
Usage:
31+
# Use existing environment variables
32+
python example_api_workflow.py
33+
34+
# Load configuration from a dotenv file
35+
python example_api_workflow.py --env-file ../dev-config/.env.dev.consumer
2536
"""
2637

38+
import argparse
2739
import asyncio
2840
import json
2941
import logging
42+
import os
3043
import pprint
3144
from typing import Dict, Optional
3245
from urllib.parse import urlparse
@@ -45,6 +58,15 @@
4558

4659
_logger = logging.getLogger(__name__)
4760

61+
# Try to import dotenv, but degrade gracefully if not available
62+
try:
63+
from dotenv import load_dotenv
64+
65+
_DOTENV_AVAILABLE = True
66+
except ImportError:
67+
_DOTENV_AVAILABLE = False
68+
_logger.debug("python-dotenv not available; --env-file option will be ignored")
69+
4870

4971
@environ.config(prefix="")
5072
class WorkflowConfig:
@@ -87,7 +109,7 @@ class WorkflowConfig:
87109
consumer_backend_url: str = environ.var(default="http://host.docker.internal:28000")
88110

89111
# Asset configuration
90-
asset_id: str = environ.var(default="api-workflow-users")
112+
asset_id: str = environ.var(default="example-asset-managed-via-api")
91113
data_source_url: str = environ.var(default="https://jsonplaceholder.typicode.com")
92114
data_source_path: str = environ.var(default="/users")
93115

@@ -118,7 +140,8 @@ async def start_listening(self, protocol_url: str):
118140
return
119141

120142
provider_host = urlparse(protocol_url).hostname
121-
url = f"{self.config.consumer_backend_url}/pull/stream/provider/{provider_host}"
143+
base_url = self.config.consumer_backend_url.rstrip("/")
144+
url = f"{base_url}/pull/stream/provider/{provider_host}"
122145

123146
_logger.info("Connecting to SSE stream for provider: %s", provider_host)
124147
self._connected_event.clear()
@@ -450,7 +473,67 @@ async def main(config: WorkflowConfig):
450473
return data
451474

452475

476+
def parse_args():
477+
"""Parse command line arguments."""
478+
479+
parser = argparse.ArgumentParser(
480+
description="EDC Management API Workflow Example",
481+
formatter_class=argparse.RawDescriptionHelpFormatter,
482+
epilog="""
483+
Environment Configuration:
484+
Configuration can be provided via environment variables or a dotenv file.
485+
Use --env-file to load environment variables from a specific file.
486+
487+
Example:
488+
python example_api_workflow.py --env-file ../dev-config/.env.dev.consumer
489+
""",
490+
)
491+
492+
parser.add_argument(
493+
"--env-file",
494+
type=str,
495+
help="Path to a dotenv file to load environment variables from. "
496+
"Requires python-dotenv to be installed.",
497+
metavar="PATH",
498+
)
499+
500+
return parser.parse_args()
501+
502+
503+
def load_env_file(env_file_path: str) -> bool:
504+
"""Load environment variables from a dotenv file.
505+
506+
Args:
507+
env_file_path: Path to the dotenv file
508+
509+
Returns:
510+
True if the file was loaded successfully, False otherwise
511+
"""
512+
513+
if not _DOTENV_AVAILABLE:
514+
_logger.warning(
515+
"Cannot load env file '%s': python-dotenv is not installed. "
516+
"Install it with: pip install python-dotenv",
517+
env_file_path,
518+
)
519+
return False
520+
521+
if not os.path.exists(env_file_path):
522+
_logger.error("Environment file not found: %s", env_file_path)
523+
return False
524+
525+
_logger.info("Loading environment variables from: %s", env_file_path)
526+
load_dotenv(env_file_path, override=True)
527+
return True
528+
529+
453530
if __name__ == "__main__":
531+
args = parse_args()
532+
533+
# Load dotenv file if specified
534+
if args.env_file:
535+
load_env_file(args.env_file)
536+
454537
config: WorkflowConfig = WorkflowConfig.from_environ()
455538
coloredlogs.install(level=config.log_level)
456539
asyncio.run(main(config))

0 commit comments

Comments
 (0)