dataflow-core 2.1.15rc2__py3-none-any.whl → 2.1.15rc4__py3-none-any.whl

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.

Potentially problematic release.


This version of dataflow-core might be problematic. Click here for more details.

@@ -1,6 +1,4 @@
1
- import os
2
- import uuid
3
- import re
1
+ import os, uuid, re, hashlib, secrets
4
2
  from datetime import datetime, timedelta
5
3
  from zoneinfo import ZoneInfo
6
4
  from traitlets import Bool, Unicode
@@ -77,6 +75,13 @@ class DataflowBaseAuthenticator(Authenticator):
77
75
  return email.split('@')[0]
78
76
  return email
79
77
 
78
+ def generate_secure_password(self):
79
+ """Generate a secure random password hash"""
80
+ salt = secrets.token_hex(16)
81
+ random_uuid = str(uuid.uuid4())
82
+ hash_obj = hashlib.sha256((random_uuid + salt).encode())
83
+ return hash_obj.hexdigest()
84
+
80
85
  def create_new_user(self, email, first_name=None, last_name=None):
81
86
  """Create a new user with Applicant role"""
82
87
  try:
@@ -103,11 +108,13 @@ class DataflowBaseAuthenticator(Authenticator):
103
108
  )
104
109
  counter += 1
105
110
 
111
+ secure_password = self.generate_secure_password()
106
112
  new_user = m_user.User(
107
113
  user_name=username,
108
114
  first_name=first_name or username,
109
115
  last_name=last_name or "",
110
116
  email=email,
117
+ password=secure_password,
111
118
  )
112
119
 
113
120
  self.db.add(new_user)
@@ -3,7 +3,7 @@
3
3
  from .role import Role
4
4
  from .user import User, UserOnboarding, OnboardingStatus
5
5
  from .team import Team
6
- from .environment import (Environment, LocalEnvironment, ArchivedEnvironment, JobLogs)
6
+ from .environment import (Environment, LocalEnvironment, ArchivedEnvironment, JobLogs, PipSource)
7
7
  from .project_details import ProjectDetails
8
8
  from .recent_projects import RecentProjects
9
9
  from .pinned_projects import PinnedProject
@@ -6,10 +6,10 @@ class AppType(Base):
6
6
  __tablename__ = "APP_TYPE"
7
7
 
8
8
  id = Column(Integer, primary_key=True, autoincrement=True, unique=True)
9
- name = Column(String, unique=True, nullable=True)
9
+ name = Column(String, unique=True, nullable=False)
10
10
  display_name = Column(String, nullable=False)
11
11
  code_based = Column(Boolean, nullable=False)
12
- studio = Column(Boolean, nullable=False, default=False)
13
- runtime = Column(Boolean, nullable=False, default=False)
12
+ studio = Column(Boolean, nullable=False, default=False, server_default='false')
13
+ runtime = Column(Boolean, nullable=False, default=False, server_default='false')
14
14
 
15
15
  organizations = relationship("Organization", secondary="ORGANIZATION_APP_TYPE", back_populates="apps")
@@ -15,11 +15,11 @@ class Connection(Base):
15
15
  conn_type = Column(String, nullable=False)
16
16
  runtime = Column(String, nullable=True)
17
17
  slug = Column(String, nullable=True)
18
- status = Column(Boolean, default=False)
18
+ status = Column(Boolean, default=False, server_default='false')
19
19
  created_by = Column(String, nullable=True)
20
20
  created_at = Column(DateTime(timezone=True), server_default=func.now())
21
21
  updated_at = Column(DateTime(timezone=True), onupdate=func.now())
22
- is_active = Column(Boolean, default=True)
22
+ is_active = Column(Boolean, default=True, server_default='true')
23
23
 
24
24
  __table_args__ = (
25
25
  UniqueConstraint('conn_id', 'org_id', 'runtime', 'slug', 'is_active', 'created_by', name='uq_active_conn_with_runtime_slug'),
@@ -8,9 +8,9 @@ class DataflowZone(Base):
8
8
  id = Column(Integer, primary_key=True, autoincrement=True)
9
9
  slug = Column(String, unique=True, nullable=False)
10
10
  display_name = Column(String, nullable=False)
11
- is_runtime = Column(Boolean, default=False)
11
+ is_runtime = Column(Boolean, default=False, server_default='false')
12
12
  subdomain = Column(String)
13
- display_order = Column(Integer, default=0)
13
+ display_order = Column(Integer, default=0, server_default='0')
14
14
 
15
15
  role_zone_assocs = relationship("RoleZone", back_populates="zone")
16
16
 
@@ -1,5 +1,8 @@
1
- from sqlalchemy import Column, Integer, String, Boolean, Text, ForeignKey, DateTime, UniqueConstraint
2
- from sqlalchemy.orm import relationship
1
+ from sqlalchemy import (
2
+ Column, Integer, String, Boolean, Text,
3
+ ForeignKey, DateTime, UniqueConstraint, CheckConstraint
4
+ )
5
+ from sqlalchemy.orm import relationship, Session
3
6
  from sqlalchemy.sql import func
4
7
  from datetime import datetime, timezone
5
8
  from dataflow.db import Base
@@ -11,14 +14,14 @@ class EnvironmentAttributes(Base):
11
14
  """
12
15
  __abstract__ = True
13
16
 
14
- name = Column(String)
17
+ name = Column(String, nullable=False)
15
18
  url = Column(String)
16
- enabled = Column(Boolean, default=True)
17
- version = Column(String, default=0)
18
- is_latest = Column(Boolean, default=True)
19
- base_env_id = Column(Integer, nullable=True)
19
+ enabled = Column(Boolean, default=True, server_default='true')
20
+ version = Column(String, default=0, server_default='0')
21
+ is_latest = Column(Boolean, default=True, server_default='true')
22
+ base_env_id = Column(Integer, default=None)
20
23
  short_name = Column(String(5))
21
- status = Column(String, default="Saved")
24
+ status = Column(String, default="Saved", server_default="Saved")
22
25
  icon = Column(String)
23
26
  py_version = Column(String)
24
27
  r_version = Column(String)
@@ -52,7 +55,7 @@ class JobLogs(Base):
52
55
  __table_args__ = (UniqueConstraint('log_file_name', 'org_id', name='_job_log_file_org_uc'),)
53
56
 
54
57
  id = Column(Integer, primary_key=True, index=True)
55
- created_at = Column(DateTime, default=datetime.now)
58
+ created_at = Column(DateTime, default=datetime.now, server_default=func.now())
56
59
  completed_at = Column(DateTime, nullable=True)
57
60
  log_file_name = Column(String, nullable=False)
58
61
  log_file_location = Column(String, nullable=False)
@@ -71,11 +74,52 @@ class LocalEnvironment(Base):
71
74
  py_version = Column(String)
72
75
  pip_libraries = Column(Text)
73
76
  conda_libraries = Column(Text)
74
- status = Column(String, default="Created")
77
+ status = Column(String, default="Created", server_default="Created")
75
78
  cloned_from = Column(String, nullable=True)
76
79
  updated_at = Column(DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc))
77
- need_refresh = Column(Boolean, default=False)
80
+ need_refresh = Column(Boolean, default=False, server_default='false')
78
81
 
79
82
  class EnvType(str, Enum):
80
83
  dataflow = "dataflow"
81
84
  local = "local"
85
+
86
+ class PipSource(Base):
87
+ __tablename__ = "PIP_SOURCE"
88
+
89
+ id = Column(Integer, primary_key=True, autoincrement=True)
90
+
91
+ org_id = Column(Integer, ForeignKey("ORGANIZATION.id", ondelete="CASCADE"), nullable=False, index=True)
92
+ user_name = Column(String, ForeignKey("USER.user_name", ondelete="CASCADE"), nullable=True, index=True)
93
+
94
+ name = Column(String, nullable=False)
95
+ url = Column(String, nullable=False)
96
+ is_index = Column(Boolean, default=False, nullable=False, server_default='false')
97
+
98
+ created_at = Column(DateTime, default=datetime.now(timezone.utc), nullable=False)
99
+ updated_at = Column(DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc), nullable=False)
100
+
101
+ __table_args__ = (
102
+ UniqueConstraint("org_id", "name", "user_name", name="uq_pip_source_per_user_org"),
103
+ CheckConstraint("NOT (is_index = TRUE AND user_name IS NOT NULL)", name="check_no_user_index_url"),
104
+ )
105
+
106
+ @classmethod
107
+ def get_org_sources(cls, session: Session, org_id: int):
108
+ """
109
+ Returns all sources for the given org (org-level).
110
+ """
111
+ return session.query(cls).filter(
112
+ cls.org_id == org_id,
113
+ cls.user_name == None
114
+ ).all()
115
+
116
+ @classmethod
117
+ def get_user_sources(cls, session: Session, org_id: int, user_name: str):
118
+ """
119
+ Returns merged sources for a user in an org (org-level + user-level personal sources).
120
+ """
121
+ return session.query(cls).filter(
122
+ cls.org_id == org_id,
123
+ ((cls.user_name == None) | (cls.user_name == user_name))
124
+ ).all()
125
+
@@ -13,12 +13,12 @@ class OrganizationUser(Base):
13
13
 
14
14
  org_id = Column(Integer, ForeignKey('ORGANIZATION.id', ondelete="CASCADE"), primary_key=True, nullable=False)
15
15
  user_id = Column(Integer, ForeignKey('USER.user_id', ondelete="CASCADE"), primary_key=True, nullable=False)
16
- role_id = Column(Integer, ForeignKey('ROLE.id', ondelete="SET NULL"))
16
+ role_id = Column(Integer, ForeignKey('ROLE.id', ondelete="SET NULL"), nullable=False)
17
17
  active_env_short_name = Column(String, nullable=True)
18
18
  active_env_type = Column(Enum(EnvType), nullable=True)
19
19
  active_server_id = Column(Integer, ForeignKey('CUSTOM_SERVER.id', ondelete="SET NULL"))
20
- show_server_page = Column(Boolean, default=True)
21
- monthly_allocation = Column(Integer, default=0)
20
+ show_server_page = Column(Boolean, default = True, server_default='true')
21
+ monthly_allocation = Column(Integer, nullable=True, default=0, server_default='0')
22
22
 
23
23
  # Relationships
24
24
  user = relationship("User", back_populates="org_user_assocs")
@@ -1,5 +1,5 @@
1
1
  from sqlalchemy import (
2
- Column, Integer, String, Enum, DateTime, ForeignKey, Index
2
+ Column, Integer, String, Enum, DateTime, ForeignKey, Index, text
3
3
  )
4
4
  import uuid, enum
5
5
  from sqlalchemy.dialects.postgresql import JSONB, UUID
@@ -16,12 +16,12 @@ class Organization(Base):
16
16
  __tablename__ = "ORGANIZATION"
17
17
 
18
18
  id = Column(Integer, primary_key=True, autoincrement=True)
19
- uid = Column(UUID(as_uuid=True), default=uuid.uuid4, nullable=False, unique=True)
19
+ uid = Column(UUID(as_uuid=True), default=uuid.uuid4, nullable=False, unique=True, server_default=text("gen_random_uuid()"))
20
20
  name = Column(String(255), nullable=False, unique=True)
21
21
  invite_code = Column(String(64), nullable=False, unique=True)
22
22
  email_domain = Column(String(255), nullable=False, unique=True)
23
- spark_enabled_zones = Column(JSONB, default=func.json([])) # List of zone IDs where Spark is enabled
24
- created_at = Column(DateTime, default=datetime.utcnow)
23
+ spark_enabled_zones = Column(JSONB, default=func.json([]), server_default=text("'[]'::jsonb")) # List of zone IDs where Spark is enabled
24
+ created_at = Column(DateTime, default=datetime.utcnow, server_default=func.now())
25
25
 
26
26
  # Association object link
27
27
  org_user_assocs = relationship("OrganizationUser", back_populates="organization", cascade="all, delete-orphan")
@@ -68,7 +68,6 @@ class OrganizationOnboarding(Base):
68
68
  admin_username = Column(String(100), nullable=False, unique=True)
69
69
  admin_password = Column(String(255), nullable=False)
70
70
 
71
- # New fields
72
71
  discovery_source = Column(String(255), nullable=True)
73
72
  additional_info = Column(String(1000), nullable=True)
74
73
  size_of_data = Column(String(100), nullable=True)
@@ -1,4 +1,4 @@
1
- from sqlalchemy import Column, Integer, ForeignKey, DateTime, UniqueConstraint
1
+ from sqlalchemy import Column, Integer, ForeignKey, DateTime, UniqueConstraint, func
2
2
  from dataflow.db import Base
3
3
  from datetime import datetime
4
4
 
@@ -8,7 +8,7 @@ class PinnedProject(Base):
8
8
  id = Column(Integer, primary_key=True)
9
9
  user_id = Column(Integer, ForeignKey('USER.user_id', ondelete="CASCADE"), index=True)
10
10
  project_id = Column(Integer, ForeignKey('PROJECT_DETAIL.project_id', ondelete="CASCADE"), index=True)
11
- pinned_at = Column(DateTime, default=datetime.utcnow)
11
+ pinned_at = Column(DateTime, default=datetime.utcnow, server_default=func.now())
12
12
 
13
13
  __table_args__ = (
14
14
  UniqueConstraint("user_id", "project_id", name="uix_user_project"),
@@ -16,10 +16,11 @@ class ProjectDetails(Base):
16
16
  runtime = Column(String, nullable=False)
17
17
  py_env = Column(Integer, nullable=True)
18
18
  launch_url = Column(String, nullable=True)
19
- status = Column(Enum("pending", "created" ,"deployed", "stopped", "failed", name="deployment_status"), default="created")
19
+ status = Column(Enum("pending", "created" ,"deployed", "stopped", "failed", name="deployment_status"), default="created", server_default="created")
20
20
  last_deployed = Column(DateTime, nullable=True)
21
21
  created_at = Column(DateTime, nullable=False, server_default=func.now())
22
22
  created_by = Column(String, nullable=False)
23
23
  org_id = Column(Integer, ForeignKey('ORGANIZATION.id', ondelete='CASCADE'), nullable=False)
24
+ airflow_config_file = Column(String, nullable=True)
24
25
 
25
26
  app_type = relationship("AppType")
@@ -12,7 +12,7 @@ class RecentProjectStudio(Base):
12
12
  project_name = Column(String, nullable=False)
13
13
  project_path = Column(String, nullable=False)
14
14
  last_opened_date = Column(DateTime, server_default=func.now(), nullable=False)
15
- remember = Column(Boolean, default=False)
15
+ remember = Column(Boolean, default=False, server_default='false')
16
16
 
17
17
  __table_args__ = (
18
18
  UniqueConstraint(user_name, project_path, app_name, name='user_name_project_path_app_name_unique'),
dataflow/models/role.py CHANGED
@@ -23,7 +23,7 @@ class Role(Base):
23
23
  name = Column(String, nullable=False)
24
24
  org_id = Column(Integer, ForeignKey('ORGANIZATION.id'))
25
25
  description = Column(String, nullable=True)
26
- base_role = Column(Enum(BaseRoleField), nullable=False, default=BaseRoleField.user)
26
+ base_role = Column(Enum(BaseRoleField), nullable=False, default=BaseRoleField.user, server_default=BaseRoleField.user.value)
27
27
 
28
28
  # Relationships
29
29
  role_zone_assocs = relationship("RoleZone", back_populates="role")
@@ -1,14 +1,19 @@
1
1
  from typing import Dict, List, Optional
2
- from sqlalchemy import Column, Integer, ForeignKey, UniqueConstraint, Boolean
2
+ from sqlalchemy import Column, Integer, ForeignKey, UniqueConstraint, Boolean, Index
3
3
  from sqlalchemy.orm import relationship
4
4
  from dataflow.db import Base
5
5
 
6
6
  class RoleZone(Base):
7
7
  __tablename__ = 'ROLE_ZONE'
8
-
8
+
9
9
  role_id = Column(Integer, ForeignKey('ROLE.id', ondelete="CASCADE"), primary_key=True)
10
10
  zone_id = Column(Integer, ForeignKey('DATAFLOW_ZONE.id', ondelete="CASCADE"), primary_key=True)
11
- is_default = Column(Boolean, default=False, nullable=False)
11
+ is_default = Column(Boolean, default=False, nullable=False, server_default='false')
12
+
13
+ __table_args__ = (
14
+ Index('idx_role_runtime_default', 'role_id', unique=True,
15
+ postgresql_where=is_default.is_(True)),
16
+ )
12
17
 
13
18
  role = relationship("Role", back_populates="role_zone_assocs")
14
19
  zone = relationship("DataflowZone", back_populates="role_zone_assocs")
@@ -1,4 +1,4 @@
1
- from sqlalchemy import Column, Integer, String, Boolean, Text, ForeignKey
1
+ from sqlalchemy import Column, Integer, String, Boolean, Text, ForeignKey, text
2
2
  from sqlalchemy.dialects.postgresql import JSONB
3
3
  from sqlalchemy.sql import func
4
4
  from sqlalchemy.orm import relationship
@@ -14,10 +14,10 @@ class ServerConfig(Base):
14
14
  ram = Column(String, nullable=False)
15
15
  cpu = Column(String, nullable=False)
16
16
  gpu = Column(String)
17
- default = Column(Boolean, default=False)
18
- tags = Column(JSONB, default=func.json([]))
17
+ default = Column(Boolean, default=False, server_default='false')
18
+ tags = Column(JSONB, default=func.json([]), server_default=text("'[]'::jsonb"))
19
19
  description = Column(Text, nullable=True)
20
- kubespawner_override = Column(JSONB, default=func.json({}))
20
+ kubespawner_override = Column(JSONB, default=func.json({}), server_default=text("'{}'::jsonb"))
21
21
 
22
22
  # Relationships
23
23
  organizations = relationship("Organization", secondary="ORGANIZATION_SERVER", back_populates="servers")
@@ -27,7 +27,7 @@ class CustomServerConfig(Base):
27
27
 
28
28
  id = Column(Integer, primary_key=True, autoincrement=True)
29
29
  base_server_id = Column(Integer, ForeignKey(ServerConfig.id, ondelete="CASCADE"), nullable=False)
30
- org_id = Column(Integer, ForeignKey('ORGANIZATION.id'), nullable=False)
30
+ org_id = Column(Integer, ForeignKey('ORGANIZATION.id', ondelete="CASCADE"), nullable=False)
31
31
  display_name = Column(String, nullable=False, unique=True, index=True)
32
32
  description = Column(Text, nullable=True)
33
33
 
dataflow/models/user.py CHANGED
@@ -19,7 +19,7 @@ class User(Base):
19
19
  email = Column(String, unique=True)
20
20
  image = Column(LargeBinary)
21
21
  image_url = Column(String, nullable=True)
22
- active = Column(Boolean, nullable=False, default=True)
22
+ active = Column(Boolean, nullable=False, default=True, server_default='true')
23
23
  password = Column(String, nullable=False)
24
24
  active_org_id = Column(Integer, ForeignKey('ORGANIZATION.id'))
25
25
 
@@ -59,9 +59,9 @@ class UserOnboarding(Base):
59
59
  id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
60
60
  user_id = Column(Integer, ForeignKey("USER.user_id", ondelete="CASCADE"), nullable=False)
61
61
  org_id = Column(Integer, ForeignKey("ORGANIZATION.id", ondelete="CASCADE"), nullable=False)
62
- status = Column(Enum(OnboardingStatus, name='onboarding_status'), nullable=False, default=OnboardingStatus.pending.value)
63
- created_at = Column(DateTime, default=func.now(), nullable=False)
64
- updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False)
62
+ status = Column(Enum(OnboardingStatus, name='onboarding_status'), nullable=False, default=OnboardingStatus.pending.value, server_default='pending')
63
+ created_at = Column(DateTime, default=func.now(), nullable=False, server_default=func.now())
64
+ updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False, server_default=func.now())
65
65
 
66
66
  # Relationships
67
67
  user = relationship("User", back_populates="onboarding_requests")
@@ -25,9 +25,10 @@ class Variable(Base):
25
25
  created_at = Column(DateTime, server_default=func.now())
26
26
  updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
27
27
  created_by = Column(String, ForeignKey('USER.user_name'), nullable=True)
28
- is_active = Column(Boolean, default=True, nullable=False)
28
+ is_active = Column(Boolean, default=True, nullable=False, server_default='true')
29
29
  datatype = Column(Enum(DataType, name="data_type"), nullable=False)
30
- set_as_env = Column(Boolean, default=False, nullable=False)
30
+ set_as_env = Column(Boolean, default=False, nullable=False, server_default='false')
31
+
31
32
 
32
33
  __table_args__ = (
33
34
  CheckConstraint(type.in_(['variable', 'secret']), name='check_variable_type'),
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataflow-core
3
- Version: 2.1.15rc2
3
+ Version: 2.1.15rc4
4
4
  Summary: Dataflow core package
5
5
  Author: Dataflow
6
6
  Author-email:
7
7
  Requires-Dist: sqlalchemy
8
+ Requires-Dist: alembic
8
9
  Requires-Dist: boto3
9
10
  Requires-Dist: psycopg2-binary
10
11
  Requires-Dist: pymysql
@@ -1,6 +1,6 @@
1
1
  authenticator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  authenticator/dataflowairflowauthenticator.py,sha256=gEdCiL2yJQ7lYvAwbrjcAkccVMfehoMJldw9eU7cc2s,2243
3
- authenticator/dataflowhubauthenticator.py,sha256=drs6M9tp0QFLzmj-eNaa6zefKat9cN0cJvwGLrSeYvQ,12531
3
+ authenticator/dataflowhubauthenticator.py,sha256=0dt8-yeFtty1kq50qxBHafzwuWy8fG00QVnq6svH12c,12913
4
4
  authenticator/dataflowsupersetauthenticator.py,sha256=NkAmDaIc-ui-qEolu4xz_UY7P_2g8111hwNjPvAOW1Q,2839
5
5
  dataflow/__init__.py,sha256=WTRg8HMpMWSgxYJ9ZGVldx4k07fAbta3mBmZ1hG9mWE,30
6
6
  dataflow/configuration.py,sha256=7To6XwH1eESiYp39eqPcswXWwrdBUdPF6xN6WnazOF0,663
@@ -8,31 +8,31 @@ dataflow/database_manager.py,sha256=tJHMuOZ9Muskrh9t4uLRlTuFU0VkHAzoHlGP5DORIC4,
8
8
  dataflow/dataflow.py,sha256=EzeOMtMCqG0WJ0vld6ArKbKNFAmA9sbjBqVJ8sd2sQw,13026
9
9
  dataflow/db.py,sha256=73ojGqpCTRVTlPszD73Ozhjih_BI2KTHmazqxxL6iWk,3780
10
10
  dataflow/environment.py,sha256=7XiSojSIOnMOz5YVk-k6w1yQCKbBTTvUxv5cnn6cqJg,28830
11
- dataflow/models/__init__.py,sha256=UKaiCxJJLXvWOqZlHmDWr9fTwBncKbnyjSIsPWKvlVI,1167
12
- dataflow/models/app_types.py,sha256=NMHUHBoGnxYHbtlBVppNqQ6NW2T6pSedmQ6-T4t2JAc,640
11
+ dataflow/models/__init__.py,sha256=FHus-b2oTgLSJ9H7dOCNJ14XpjTzHARqK_Vwh8VhCtM,1178
12
+ dataflow/models/app_types.py,sha256=BNGtjwpQU6MSpBGp0pDzUI4uDZNqvE3_x33itIInasM,689
13
13
  dataflow/models/blacklist_library.py,sha256=B2oi3Z8GcR_glhLAyinFk0W8c9txXvm3uOER6dY-q7I,991
14
- dataflow/models/connection.py,sha256=Kv0vo4V5z7EBfJUSnXWxKOB-AXPWIte9ttauNdM5lyk,1127
15
- dataflow/models/dataflow_zone.py,sha256=ScCM7963Rd5G4e4eFQGF0gNeg6abaWEwIgGOqoezfrg,719
16
- dataflow/models/environment.py,sha256=Pnma45hzDdr5jQ0k6mSAH6eZQGTQWm87AnebovtVBdU,3263
14
+ dataflow/models/connection.py,sha256=c1zfwanuZRf6NvtA7lVU8z3taj_QX-bQSO1zbQzcBI0,1174
15
+ dataflow/models/dataflow_zone.py,sha256=PHvZRpINTBN3NTxHYsSuTR-v2G2jZHF0zIIIrQVaBJw,762
16
+ dataflow/models/environment.py,sha256=vkuFBRY9pZNMRXx3F4ZI6P2Nr-UNpqwzZkT-gM4NhyU,5097
17
17
  dataflow/models/environment_status.py,sha256=lvPDNUsUoTW9D97B07aKqJQHRKp4LvPM28pQDMPH1ac,536
18
18
  dataflow/models/git_ssh.py,sha256=xRkzK8lZ4Fa25zhE3Y9J78BiWv6xtd10YDBNf1XDKXE,797
19
- dataflow/models/org_associations.py,sha256=Kw1zK-Rg97GBV6U61O5V57sohPTHSchalMDAelo2hUQ,1915
20
- dataflow/models/organization.py,sha256=SGonZsaGRPu7Z9VLqFE32l68mwLdlki-OLxqdMpHtyU,3353
21
- dataflow/models/pinned_projects.py,sha256=I-XMQq7__XJJi2lyOdEvQEfhPRz8D6KHA6Cbavbf05o,606
19
+ dataflow/models/org_associations.py,sha256=iih8xpbcWTsvOdBTs9LjW8kqPtFy7sBhIh7IU2pMGvo,1991
20
+ dataflow/models/organization.py,sha256=hrvwQQuypM20eFX48QPmly1N0SM_pgML38BYA98vMb8,3446
21
+ dataflow/models/pinned_projects.py,sha256=R_Euj98J2LzWrmedQ-A7mAluDyWes5VWt5dgqUs7EWc,639
22
22
  dataflow/models/pod_activity.py,sha256=4NQplUtckS4d2Uc-Iyi8PfgciblHiExbXo_VTMaukB8,751
23
23
  dataflow/models/pod_session_history.py,sha256=-O8DHtH1AtGLntJ1shI6eiciTJGL_vYvG3gfupvr0zY,778
24
- dataflow/models/project_details.py,sha256=pjunEIjgFW66N7kP23cVtRU37LVOnKaqT8K7WBekAVg,1260
25
- dataflow/models/recent_project_studio.py,sha256=m12KGCsv453C1ijHjfVD8E7cJ7Og_0N8uc7_9VlfkYw,812
24
+ dataflow/models/project_details.py,sha256=C7b2VTOiF1BiUfgixIxdyZ2fMncCR7klQdTpF1rB6Wc,1342
25
+ dataflow/models/recent_project_studio.py,sha256=5E5f55FXOq7vC76GNw-Bf8dUKmpFjwkkD-qthPGFKhM,836
26
26
  dataflow/models/recent_projects.py,sha256=OFd5MSRXVRHs9UbvUNoJBBnh9rgsJ0lwE23wm5_Hc5w,321
27
- dataflow/models/role.py,sha256=LQoEWSc_Pm79IjNC1uFKGFfkhaZkhI3JSq6Sj6Xrm_g,1266
27
+ dataflow/models/role.py,sha256=Kw9zqpG3R5nzwPXzg8MaoJGwDzN9r0rrOAKcVpsdkeY,1307
28
28
  dataflow/models/role_server.py,sha256=Qz9VqGSpVGvfLz9_lKITUfkiuR7pmVc8SIIfYrDPDso,547
29
- dataflow/models/role_zone.py,sha256=uH8JheWyzUWcRECRzYuzdphUAUXeU5zRVA1Bhuz3h9w,772
30
- dataflow/models/server_config.py,sha256=Npf4xP7zQ6eXp9kqwM9Owsm8C0e8Qw6jei2YX5k0in0,1646
29
+ dataflow/models/role_zone.py,sha256=kQ9tUxxpwQ_VdbUNKqyacQ87SovsKKP5K6-EFrSTphk,962
30
+ dataflow/models/server_config.py,sha256=FHO4y0Lm7wBcYDQYn1144duOkihIdRTLPIK0sfDEXIo,1768
31
31
  dataflow/models/session.py,sha256=c8TI6qXsM8utzp5vSQtAOXJSbgasnyu-a0qSAvA-rWs,459
32
32
  dataflow/models/team.py,sha256=u5VKOxi-0wGgxssIhXr1Ydn3X9IEAHNWxz029KaVm5g,780
33
- dataflow/models/user.py,sha256=XSd3PuqMRzm4qglNaUF0S-9RjH_f016eZX4I0iDtq2Q,2856
33
+ dataflow/models/user.py,sha256=ggJftOVLBEs_6fhn1_13Joe9aL32KMnJwHfBMzeMAOA,2959
34
34
  dataflow/models/user_team.py,sha256=vD6BsiMfx1iIMQiT8fpwhsQ8AGuPuBO83F22Cy7j-nU,524
35
- dataflow/models/variables.py,sha256=v6a1r5OgmKOAlyVdmOFM6Axre7DEBEsgrF4yTV5h3U0,1524
35
+ dataflow/models/variables.py,sha256=qCyiVbzC3Wd2onLx-eCY36VWiVytxxWvYld6_3ki5H8,1572
36
36
  dataflow/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  dataflow/schemas/connection.py,sha256=ut2sqz06yOjmFKzHry92FEt7DN09Bj30GYse35__Cuw,2467
38
38
  dataflow/schemas/git_ssh.py,sha256=N1O7HM6ZbygIBZn2rKvNR0e7IM3ZJMAH6aJtjaghDr0,1283
@@ -52,8 +52,12 @@ dataflow/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
52
  dataflow/utils/exceptions.py,sha256=8GRFoYZ5dPGQckVm2znaHpPi0ZAs69fK-RGKukEsapk,4432
53
53
  dataflow/utils/get_current_user.py,sha256=iPyUpEpuxitdmFwvaPiRWIlII8JaaGoxUhQcmNWi0vI,2319
54
54
  dataflow/utils/logger.py,sha256=7BFrOq5Oiqn8P4XZbgJzMP5O07d2fpdECbbfsjrUuHw,1213
55
- dataflow_core-2.1.15rc2.dist-info/METADATA,sha256=t8vhx-r4NQ9rhkLblo_9sZRH1nvOnaYH7UpkqBPUaCw,443
56
- dataflow_core-2.1.15rc2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
- dataflow_core-2.1.15rc2.dist-info/entry_points.txt,sha256=ppj_EIbYrJJwCPg1kfdsZk5q1N-Ejfis1neYrnjhO8o,117
58
- dataflow_core-2.1.15rc2.dist-info/top_level.txt,sha256=SZsUOpSCK9ntUy-3Tusxzf5A2e8ebwD8vouPb1dPt_8,23
59
- dataflow_core-2.1.15rc2.dist-info/RECORD,,
55
+ dfmigration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ dfmigration/env.py,sha256=w_3Kzr3LJCU5l1zBGsNcoNGZyR8fZEtMRsxE-cEqfHQ,1110
57
+ dfmigration/versions/001_initial_baseline_migration.py,sha256=lxjs7LZLs9-c7FQj7t7t49EOfLPPHMLI6iNp0PIBMRA,299
58
+ dfmigration/versions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
+ dataflow_core-2.1.15rc4.dist-info/METADATA,sha256=NM9-0YqN16BHxRN6iHZVfofebsfMK7zVVaL615WttpY,466
60
+ dataflow_core-2.1.15rc4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
61
+ dataflow_core-2.1.15rc4.dist-info/entry_points.txt,sha256=ppj_EIbYrJJwCPg1kfdsZk5q1N-Ejfis1neYrnjhO8o,117
62
+ dataflow_core-2.1.15rc4.dist-info/top_level.txt,sha256=-gGoIBh-bUMtzOdna2jsDOdkE2CRu3w3aA7yEFCmNAI,35
63
+ dataflow_core-2.1.15rc4.dist-info/RECORD,,
@@ -1,2 +1,3 @@
1
1
  authenticator
2
2
  dataflow
3
+ dfmigration
File without changes
dfmigration/env.py ADDED
@@ -0,0 +1,45 @@
1
+ from sqlalchemy import engine_from_config, pool
2
+ from alembic import context
3
+ import os
4
+
5
+ config = context.config
6
+ target_metadata = None
7
+
8
+ def get_url():
9
+ return os.getenv('DATABASE_URL')
10
+
11
+ def run_migrations_offline() -> None:
12
+ url = get_url()
13
+ context.configure(
14
+ url=url,
15
+ target_metadata=target_metadata,
16
+ literal_binds=True,
17
+ dialect_opts={"paramstyle": "named"},
18
+ )
19
+
20
+ with context.begin_transaction():
21
+ context.run_migrations()
22
+
23
+ def run_migrations_online() -> None:
24
+ configuration = config.get_section(config.config_ini_section) or {}
25
+ configuration['sqlalchemy.url'] = get_url()
26
+
27
+ connectable = engine_from_config(
28
+ configuration,
29
+ prefix="sqlalchemy.",
30
+ poolclass=pool.NullPool,
31
+ )
32
+
33
+ with connectable.connect() as connection:
34
+ context.configure(
35
+ connection=connection,
36
+ target_metadata=target_metadata
37
+ )
38
+
39
+ with context.begin_transaction():
40
+ context.run_migrations()
41
+
42
+ if context.is_offline_mode():
43
+ run_migrations_offline()
44
+ else:
45
+ run_migrations_online()
@@ -0,0 +1,20 @@
1
+ """Initial baseline migration
2
+
3
+ Revision ID: 001
4
+ Revises: None
5
+ Create Date: 2025-09-10 15:00:00.000000
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+ revision = '001'
12
+ down_revision = None
13
+ branch_labels = None
14
+ depends_on = None
15
+
16
+ def upgrade() -> None:
17
+ pass
18
+
19
+ def downgrade() -> None:
20
+ pass
File without changes