rococo 1.3.0__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.
- {rococo-1.3.0 → rococo-1.3.2}/PKG-INFO +1 -1
- {rococo-1.3.0 → rococo-1.3.2}/rococo/data/postgresql.py +19 -5
- {rococo-1.3.0 → rococo-1.3.2}/rococo/emailing/mailjet.py +10 -4
- {rococo-1.3.0 → rococo-1.3.2}/rococo.egg-info/PKG-INFO +1 -1
- {rococo-1.3.0 → rococo-1.3.2}/setup.py +1 -1
- {rococo-1.3.0 → rococo-1.3.2}/LICENSE +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/README.md +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/auth/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/auth/tokens.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/config/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/config/config.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/data/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/data/base.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/data/dynamodb.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/data/mongodb.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/data/mysql.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/data/surrealdb.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/emailing/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/emailing/base.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/emailing/config.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/emailing/enums.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/emailing/factory.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/emailing/ses.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/faxing/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/faxing/base.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/faxing/config.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/faxing/enums.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/faxing/factory.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/faxing/ifax.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/messaging/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/messaging/base.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/messaging/rabbitmq.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/messaging/sqs.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/common/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/common/cli_base.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/common/migration_base.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/common/migration_runner.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/common/migration_template.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/common/sql_migration_base.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/mongo/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/mongo/cli.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/mongo/migration.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/mysql/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/mysql/cli.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/mysql/migration.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/postgres/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/postgres/cli.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/migrations/postgres/migration.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/email.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/login_method.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/organization.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/otp_method.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/person.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/person_organization_role.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/recovery_code.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/surrealdb/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/surrealdb/email.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/surrealdb/login_method.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/surrealdb/organization.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/surrealdb/otp_method.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/surrealdb/person.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/surrealdb/person_organization_role.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/surrealdb/surreal_versioned_model.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/models/versioned_model.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/plugins/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/plugins/pooled_connection.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/base_repository.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/dynamodb/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/dynamodb/dynamodb_repository.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/mongodb/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/mongodb/mongodb_repository.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/mysql/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/mysql/mysql_repository.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/mysql/organization_repository.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/postgresql/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/postgresql/postgresql_repository.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/surrealdb/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/surrealdb/organization_repository.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/surrealdb/person_organization_role_repository.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/surrealdb/surreal_db_repository.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/sms/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/sms/base.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/sms/config.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/sms/enums.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/sms/factory.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo/sms/twilio.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo.egg-info/SOURCES.txt +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo.egg-info/dependency_links.txt +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo.egg-info/entry_points.txt +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo.egg-info/requires.txt +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/rococo.egg-info/top_level.txt +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/setup.cfg +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/base_repository_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/config_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/database-integration/__init__.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/database-integration/conftest.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/database-integration/test_dynamodb_integration.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/database-integration/test_models.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/database-integration/test_mongodb_integration.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/database-integration/test_mysql_integration.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/database-integration/test_postgres_integration.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/database-integration/test_surrealdb_integration.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/dynamodb_repository_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/migration_cli_base_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/migration_runner_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/model_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/mongodb_repository_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/mysql_repository_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/postgre_repository_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/sql_migration_base_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/surrealdb_repository_test.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/test_calculated_properties_fix.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/test_faxing.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/test_mailjet_addresses.py +0 -0
- {rococo-1.3.0 → rococo-1.3.2}/tests/test_non_versioned_model.py +0 -0
|
@@ -11,7 +11,18 @@ from rococo.data.base import DbAdapter
|
|
|
11
11
|
class PostgreSQLAdapter(DbAdapter):
|
|
12
12
|
"""PostgreSQL adapter for interacting with PostgreSQL."""
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
host: str,
|
|
18
|
+
port: int,
|
|
19
|
+
user: str,
|
|
20
|
+
password: str,
|
|
21
|
+
database: str,
|
|
22
|
+
connection_resolver: Optional[Callable] = None,
|
|
23
|
+
connection_closer: Optional[Callable] = None,
|
|
24
|
+
connect_kwargs: Optional[dict] = None,
|
|
25
|
+
):
|
|
15
26
|
self._host = host
|
|
16
27
|
self._port = port
|
|
17
28
|
self._user = user
|
|
@@ -19,7 +30,8 @@ class PostgreSQLAdapter(DbAdapter):
|
|
|
19
30
|
self._database = database
|
|
20
31
|
self._connection = None
|
|
21
32
|
self._cursor = None
|
|
22
|
-
self._table_columns_cache = {}
|
|
33
|
+
self._table_columns_cache = {}
|
|
34
|
+
self._connect_kwargs = connect_kwargs or {}
|
|
23
35
|
|
|
24
36
|
if connection_resolver is None:
|
|
25
37
|
self._connection_resolver = psycopg2.connect
|
|
@@ -28,6 +40,7 @@ class PostgreSQLAdapter(DbAdapter):
|
|
|
28
40
|
|
|
29
41
|
self._connection_closer = connection_closer
|
|
30
42
|
|
|
43
|
+
|
|
31
44
|
def __enter__(self):
|
|
32
45
|
"""Context manager entry point for creating DB connection."""
|
|
33
46
|
self._connection = self.connect
|
|
@@ -60,7 +73,8 @@ class PostgreSQLAdapter(DbAdapter):
|
|
|
60
73
|
port=self._port,
|
|
61
74
|
user=self._user,
|
|
62
75
|
password=self._password,
|
|
63
|
-
database=self._database
|
|
76
|
+
database=self._database,
|
|
77
|
+
**self._connect_kwargs
|
|
64
78
|
)
|
|
65
79
|
|
|
66
80
|
def _call_cursor(self, function_name, *args, **kwargs):
|
|
@@ -405,8 +419,8 @@ class PostgreSQLAdapter(DbAdapter):
|
|
|
405
419
|
return True
|
|
406
420
|
except psycopg2.Error as ex:
|
|
407
421
|
self._connection.rollback()
|
|
408
|
-
if retry_count < 3 and ex
|
|
409
|
-
# Deadlock detected
|
|
422
|
+
if retry_count < 3 and getattr(ex, 'pgcode', None) == '40P01':
|
|
423
|
+
# Deadlock detected (PostgreSQL SQLSTATE 40P01)
|
|
410
424
|
logging.warning("Deadlock detected on table %s. Retrying in %d seconds. Attempt %d",
|
|
411
425
|
table_name, 2**retry_count, retry_count+1)
|
|
412
426
|
time.sleep(2**retry_count)
|
|
@@ -71,8 +71,14 @@ class MailjetService(EmailService):
|
|
|
71
71
|
def __call__(self, config: MailjetConfig, *args, **kwargs):
|
|
72
72
|
super().__call__(config)
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
# Parse SOURCE_EMAIL which accepts two formats:
|
|
75
|
+
# "Name <email@example.com>" → {"Name": "Name", "Email": "email@example.com"}
|
|
76
|
+
# "user@example.com" → {"Name": "", "Email": "user@example.com"}
|
|
77
|
+
match = re.match(r'^\s*(.*?)\s*<(.+)>\s*$', self.config.SOURCE_EMAIL)
|
|
78
|
+
if match:
|
|
79
|
+
name, email = match.groups()
|
|
80
|
+
else:
|
|
81
|
+
name, email = '', self.config.SOURCE_EMAIL.strip()
|
|
76
82
|
self.from_address = {"Name": name, "Email": email}
|
|
77
83
|
|
|
78
84
|
self.client = Client(
|
|
@@ -152,7 +158,7 @@ class MailjetService(EmailService):
|
|
|
152
158
|
response_data = result.json()["Data"]
|
|
153
159
|
except Exception as e:
|
|
154
160
|
message = f"Couldn't find Mailjet contact for {email}: {e}"
|
|
155
|
-
logger.exception(message
|
|
161
|
+
logger.exception(message)
|
|
156
162
|
return
|
|
157
163
|
|
|
158
164
|
for contact in response_data:
|
|
@@ -163,4 +169,4 @@ class MailjetService(EmailService):
|
|
|
163
169
|
self.config.MAILJET_API_KEY, self.config.MAILJET_API_SECRET), timeout=15)
|
|
164
170
|
except Exception as e:
|
|
165
171
|
message = f"Couldn't remove Mailjet contact for {email} : {e}"
|
|
166
|
-
logger.exception(message
|
|
172
|
+
logger.exception(message)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rococo-1.3.0 → rococo-1.3.2}/rococo/repositories/surrealdb/person_organization_role_repository.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|