nui-python-shared-utils 1.3.1__tar.gz → 1.3.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 (96) hide show
  1. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/PKG-INFO +1 -1
  2. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/es_client.py +4 -4
  3. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/secrets_helper.py +17 -1
  4. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_es_client.py +11 -0
  5. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_secrets_helper.py +37 -0
  6. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/.editorconfig +0 -0
  7. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/.github/workflows/ci.yml +0 -0
  8. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/.github/workflows/publish.yml +0 -0
  9. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/.github/workflows/test.yml +0 -0
  10. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/.markdownlint-cli2.yaml +0 -0
  11. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/CLAUDE.md +0 -0
  12. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/CONTRIBUTING.md +0 -0
  13. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/LICENSE +0 -0
  14. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/MANIFEST.in +0 -0
  15. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/README.md +0 -0
  16. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/README.md +0 -0
  17. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/development/testing.md +0 -0
  18. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/getting-started/configuration.md +0 -0
  19. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/getting-started/installation.md +0 -0
  20. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/getting-started/quickstart.md +0 -0
  21. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/guides/cli-tools.md +0 -0
  22. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/guides/elasticsearch-integration.md +0 -0
  23. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/guides/jwt-authentication.md +0 -0
  24. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/guides/lambda-utilities.md +0 -0
  25. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/guides/log-processing.md +0 -0
  26. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/guides/powertools-integration.md +0 -0
  27. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/guides/shared-types.md +0 -0
  28. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/docs/guides/slack-integration.md +0 -0
  29. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/mypy.ini +0 -0
  30. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/__init__.py +0 -0
  31. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/base_client.py +0 -0
  32. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/cli.py +0 -0
  33. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/cloudwatch_metrics.py +0 -0
  34. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/config.py +0 -0
  35. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/db_client.py +0 -0
  36. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/error_handler.py +0 -0
  37. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/es_client.py +0 -0
  38. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/es_query_builder.py +0 -0
  39. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/jwt_auth.py +0 -0
  40. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/lambda_helpers.py +0 -0
  41. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/log_processors.py +0 -0
  42. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/powertools_helpers.py +0 -0
  43. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/secrets_helper.py +0 -0
  44. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/slack_client.py +0 -0
  45. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/slack_formatter.py +0 -0
  46. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/slack_setup/__init__.py +0 -0
  47. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/slack_setup/channel_creator.py +0 -0
  48. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/slack_setup/channel_definitions.py +0 -0
  49. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/slack_setup/setup_helpers.py +0 -0
  50. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/timezone.py +0 -0
  51. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_lambda_shared_utils/utils.py +0 -0
  52. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_python_shared_utils.egg-info/SOURCES.txt +0 -0
  53. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/__init__.py +0 -0
  54. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/base_client.py +0 -0
  55. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/cli.py +0 -0
  56. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/cloudwatch_metrics.py +0 -0
  57. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/config.py +0 -0
  58. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/db_client.py +0 -0
  59. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/error_handler.py +0 -0
  60. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/es_query_builder.py +0 -0
  61. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/jwt_auth.py +0 -0
  62. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/lambda_helpers.py +0 -0
  63. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/log_processors.py +0 -0
  64. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/powertools_helpers.py +0 -0
  65. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/slack_client.py +0 -0
  66. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/slack_formatter.py +0 -0
  67. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/slack_setup/__init__.py +0 -0
  68. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/slack_setup/channel_creator.py +0 -0
  69. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/slack_setup/channel_definitions.py +0 -0
  70. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/slack_setup/setup_helpers.py +0 -0
  71. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/timezone.py +0 -0
  72. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/nui_shared_utils/utils.py +0 -0
  73. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/pyproject.toml +0 -0
  74. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/pytest.ini +0 -0
  75. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/redirect/README.md +0 -0
  76. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/redirect/pyproject.toml +0 -0
  77. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/redirect/setup.py +0 -0
  78. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/requirements-test.txt +0 -0
  79. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/setup.cfg +0 -0
  80. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/setup.py +0 -0
  81. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/__init__.py +0 -0
  82. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_aws_utils.py +0 -0
  83. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_base_client.py +0 -0
  84. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_cloudwatch_metrics.py +0 -0
  85. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_config.py +0 -0
  86. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_db_client.py +0 -0
  87. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_error_handler.py +0 -0
  88. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_es_query_builder.py +0 -0
  89. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_jwt_auth.py +0 -0
  90. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_lambda_helpers.py +0 -0
  91. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_log_processors.py +0 -0
  92. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_powertools_helpers.py +0 -0
  93. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_slack_client.py +0 -0
  94. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_slack_formatter.py +0 -0
  95. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_timezone.py +0 -0
  96. {nui_python_shared_utils-1.3.1 → nui_python_shared_utils-1.3.2}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nui-python-shared-utils
3
- Version: 1.3.1
3
+ Version: 1.3.2
4
4
  Summary: Shared Python utilities for AWS Lambda, CLI tools, and agents with Slack, Elasticsearch, and monitoring integrations
5
5
  Home-page: https://github.com/nuimarkets/nui-python-shared-utils
6
6
  Author: NUI Markets
@@ -52,14 +52,14 @@ class ElasticsearchClient(BaseClient, ServiceHealthMixin):
52
52
  def _resolve_credentials_from_env(self) -> Optional[Dict[str, Any]]:
53
53
  """Resolve Elasticsearch credentials from environment variables.
54
54
 
55
- Checks for ES_PASSWORD (required to trigger).
56
- ES_USERNAME defaults to "elastic" if not set.
55
+ Accepts both conventions: ES_PASSWORD/ES_USERNAME and ES_PASS/ES_USER.
56
+ Password is required to trigger. Username defaults to "elastic".
57
57
  """
58
- password = os.environ.get("ES_PASSWORD")
58
+ password = os.environ.get("ES_PASSWORD") or os.environ.get("ES_PASS")
59
59
  if not password:
60
60
  return None
61
61
  return {
62
- "username": os.environ.get("ES_USERNAME", "elastic"),
62
+ "username": os.environ.get("ES_USERNAME") or os.environ.get("ES_USER") or "elastic",
63
63
  "password": password,
64
64
  }
65
65
 
@@ -112,13 +112,29 @@ def get_elasticsearch_credentials(secret_name: Optional[str] = None) -> Dict:
112
112
  """
113
113
  Get Elasticsearch credentials.
114
114
 
115
+ Precedence (matching BaseServiceClient pattern):
116
+ 1. Environment variables (ES_PASSWORD/ES_PASS + ES_USERNAME/ES_USER)
117
+ 2. AWS Secrets Manager
118
+
115
119
  Args:
116
- secret_name: Override default from configuration or environment
120
+ secret_name: Override default secret name for Secrets Manager lookup.
121
+ Ignored when credentials are resolved from environment variables.
117
122
 
118
123
  Returns:
119
124
  Dict with host, username, password
120
125
  """
121
126
  config = get_config()
127
+
128
+ # Environment variables first (local dev, CLI usage)
129
+ es_password = os.environ.get("ES_PASSWORD") or os.environ.get("ES_PASS")
130
+ if es_password:
131
+ es_user = os.environ.get("ES_USERNAME") or os.environ.get("ES_USER") or "elastic"
132
+ host = os.environ.get("ES_HOST") or config.es_host
133
+ if ":" not in host and not host.startswith("http"):
134
+ host = f"{host}:9200"
135
+ return {"host": host, "username": es_user, "password": es_password}
136
+
137
+ # Secrets Manager (Lambda runtime)
122
138
  secret = secret_name or os.environ.get("ES_CREDENTIALS_SECRET") or config.es_credentials_secret
123
139
  if not secret:
124
140
  raise ValueError("No Elasticsearch secret name provided")
@@ -500,6 +500,17 @@ class TestElasticsearchCredentialResolution:
500
500
  assert client.credentials["username"] == "custom-user"
501
501
  assert client.credentials["password"] == "env-pass"
502
502
 
503
+ @patch("nui_shared_utils.base_client.get_secret")
504
+ @patch("nui_shared_utils.es_client.Elasticsearch")
505
+ @patch.dict("os.environ", {"ES_PASS": "short-pass", "ES_USER": "short-user"}, clear=True)
506
+ def test_env_var_short_form(self, mock_es, mock_get_secret):
507
+ """ES_PASS/ES_USER convention also works."""
508
+ client = ElasticsearchClient()
509
+
510
+ mock_get_secret.assert_not_called()
511
+ assert client.credentials["password"] == "short-pass"
512
+ assert client.credentials["username"] == "short-user"
513
+
503
514
  @patch("nui_shared_utils.base_client.get_secret")
504
515
  @patch("nui_shared_utils.es_client.Elasticsearch")
505
516
  @patch.dict("os.environ", {"ES_PASSWORD": "env-pass"}, clear=False)
@@ -228,6 +228,43 @@ class TestGetElasticsearchCredentials:
228
228
  assert "No Elasticsearch secret name provided" in str(exc_info.value)
229
229
 
230
230
 
231
+ @patch.dict("os.environ", {"ES_PASSWORD": "env_pass", "ES_USERNAME": "env_user", "ES_HOST": "env-host:9200"}, clear=True)
232
+ def test_get_elasticsearch_credentials_env_vars_first(self, mock_secrets_manager):
233
+ """Env vars take precedence over Secrets Manager."""
234
+ result = secrets_helper.get_elasticsearch_credentials("es-secret")
235
+
236
+ assert result == {"host": "env-host:9200", "username": "env_user", "password": "env_pass"}
237
+ mock_secrets_manager.get_secret_value.assert_not_called()
238
+
239
+ @patch.dict("os.environ", {"ES_PASS": "env_pass2", "ES_USER": "env_user2", "ES_HOST": "env-host:9200"}, clear=True)
240
+ def test_get_elasticsearch_credentials_short_env_vars(self, mock_secrets_manager):
241
+ """ES_PASS/ES_USER convention also works."""
242
+ result = secrets_helper.get_elasticsearch_credentials()
243
+
244
+ assert result == {"host": "env-host:9200", "username": "env_user2", "password": "env_pass2"}
245
+ mock_secrets_manager.get_secret_value.assert_not_called()
246
+
247
+ @patch.dict("os.environ", {"ES_PASSWORD": "env_pass"}, clear=True)
248
+ @patch("nui_shared_utils.secrets_helper.get_config")
249
+ def test_get_elasticsearch_credentials_partial_env_vars(self, mock_get_config):
250
+ """Password-only env var works, username defaults to 'elastic'."""
251
+ mock_config = Mock()
252
+ mock_config.es_host = "default-host"
253
+ mock_get_config.return_value = mock_config
254
+
255
+ result = secrets_helper.get_elasticsearch_credentials()
256
+
257
+ assert result == {"host": "default-host:9200", "username": "elastic", "password": "env_pass"}
258
+
259
+ @patch.dict("os.environ", {"ES_PASSWORD": "env_pass", "ES_HOST": "env-host:9200"}, clear=True)
260
+ def test_get_elasticsearch_credentials_env_vars_override_secret_name(self, mock_secrets_manager):
261
+ """Env vars win even when secret_name is explicitly passed."""
262
+ result = secrets_helper.get_elasticsearch_credentials(secret_name="my-specific-secret")
263
+
264
+ assert result["password"] == "env_pass"
265
+ mock_secrets_manager.get_secret_value.assert_not_called()
266
+
267
+
231
268
  class TestGetSlackCredentials:
232
269
  """Tests for get_slack_credentials function."""
233
270