Skip to content

Commit 16fac23

Browse files
committed
make release-tag: Merge branch 'main' into stable
2 parents af8825b + 8e96a3a commit 16fac23

7 files changed

Lines changed: 65 additions & 7 deletions

File tree

HISTORY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Release Notes
22

3+
## v1.22.1 - 2025-06-03
4+
5+
### Bugs Fixed
6+
7+
* Original metadata object passed to ProgrammableConstraint - Issue [#2565](https://github.com/sdv-dev/SDV/issues/2565) by @frances-h
8+
39
## v1.22.0 - 2025-06-02
410

511
### New Features

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ dependencies = [
3939
'ctgan>=0.11.0',
4040
'deepecho>=0.7.0',
4141
'rdt>=1.17.0',
42-
'sdmetrics>=0.21.0.dev0',
42+
'sdmetrics>=0.21.0',
4343
'platformdirs>=4.0',
4444
'pyyaml>=6.0.1',
4545
]
@@ -144,7 +144,7 @@ namespaces = false
144144
version = {attr = 'sdv.__version__'}
145145

146146
[tool.bumpversion]
147-
current_version = "1.22.0"
147+
current_version = "1.22.1.dev1"
148148
parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+)(?P<candidate>\d+))?'
149149
serialize = [
150150
'{major}.{minor}.{patch}.{release}{candidate}',

sdv/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
__author__ = 'DataCebo, Inc.'
88
__email__ = 'info@sdv.dev'
9-
__version__ = '1.22.0'
9+
__version__ = '1.22.1.dev1'
1010

1111

1212
import sys

sdv/cag/programmable_constraint.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Programmable constraints base classes."""
22

3+
from copy import deepcopy
4+
35
from sdv.cag._errors import ConstraintNotMetError
46
from sdv.cag.base import BaseConstraint
57

@@ -154,6 +156,7 @@ def _validate_constraint_with_data(self, data, metadata):
154156
self.programmable_constraint.validate_input_data(data)
155157

156158
def _get_updated_metadata(self, metadata):
159+
metadata = deepcopy(metadata)
157160
return self.programmable_constraint.get_updated_metadata(metadata)
158161

159162
def _fit(self, data, metadata):

static_code_analysis.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Run started:2025-06-02 18:59:40.969469
1+
Run started:2025-06-03 16:48:44.576975
22

33
Test results:
44
>> Issue: [B110:try_except_pass] Try, Except, Pass detected.

tests/integration/cag/test_programmable_constraint.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from sdv.cag import FixedCombinations, ProgrammableConstraint, SingleTableProgrammableConstraint
66
from sdv.datasets.demo import download_demo
7+
from sdv.metadata import Metadata
78
from sdv.multi_table import HMASynthesizer
89
from sdv.single_table import GaussianCopulaSynthesizer
910

@@ -196,3 +197,46 @@ def test_end_to_end_simple_constraint_with_no_fit(programmable_constraint):
196197
true_values = (sampled_data['has_rewards']) & (sampled_data['amenities_fee'] == 0.0)
197198
false_values = ~sampled_data['has_rewards']
198199
assert all((true_values) | (false_values))
200+
201+
202+
def test_get_updated_metadata_is_passed_metadata_copy(single_table_programmable_constraint):
203+
"""Test that the ``get_updated_metadata`` is not given the original metadata."""
204+
# Setup
205+
data, metadata = download_demo('single_table', 'fake_hotel_guests')
206+
original_metadata = Metadata.load_from_dict(metadata.to_dict())
207+
208+
def get_updated_metadata(self, metadata):
209+
for column in self.column_names:
210+
metadata.remove_column(column)
211+
212+
metadata.add_column(self._joint_column, sdtype='categorical')
213+
return metadata
214+
215+
single_table_programmable_constraint.get_updated_metadata = get_updated_metadata
216+
my_constraint = single_table_programmable_constraint(
217+
column_names=['has_rewards', 'room_type'], table_name='fake_hotel_guests'
218+
)
219+
220+
synthesizer = GaussianCopulaSynthesizer(metadata)
221+
222+
# Run
223+
synthesizer.add_constraints([my_constraint])
224+
synthesizer.fit(data)
225+
updated_metadata = synthesizer.get_metadata('modified')
226+
227+
# Assert
228+
assert metadata.to_dict() == original_metadata.to_dict()
229+
expected_modified_metadata = Metadata.load_from_dict({
230+
'tables': {
231+
'fake_hotel_guests': {
232+
'columns': {
233+
col: meta
234+
for col, meta in original_metadata.tables['fake_hotel_guests'].columns.items()
235+
if col not in ['has_rewards', 'room_type']
236+
},
237+
'primary_key': 'guest_email',
238+
}
239+
}
240+
})
241+
expected_modified_metadata.add_column('has_rewards#room_type', sdtype='categorical')
242+
assert updated_metadata.to_dict() == expected_modified_metadata.to_dict()

tests/unit/cag/test_programmable_constraint.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Test ProgrammableConstraint and ProgrammableConstraintHarness."""
22

33
import re
4-
from unittest.mock import Mock
4+
from unittest.mock import Mock, patch
55

66
import pandas as pd
77
import pytest
@@ -158,12 +158,17 @@ def test__validate_constraint_with_data_single_table(self):
158158
# Assert
159159
programmable_constraint.validate_input_data.assert_called_once_with(data_dict['table'])
160160

161-
def test__get_updated_metadata(self):
161+
@patch('sdv.cag.programmable_constraint.deepcopy')
162+
def test__get_updated_metadata(self, mock_deepcopy):
162163
"""Test the ``_get_updated_metadata`` method."""
163164
# Setup
164165
metadata = Metadata().load_from_dict({
165166
'tables': {'table': {'columns': {'col_A': {'sdtype': 'numerical'}}}}
166167
})
168+
copied_metadata = Metadata().load_from_dict({
169+
'tables': {'table': {'columns': {'col_A': {'sdtype': 'numerical'}}}}
170+
})
171+
mock_deepcopy.return_value = copied_metadata
167172
programmable_constraint = ProgrammableConstraint()
168173
programmable_constraint.get_updated_metadata = Mock()
169174
instance = ProgrammableConstraintHarness(programmable_constraint)
@@ -172,7 +177,7 @@ def test__get_updated_metadata(self):
172177
instance._get_updated_metadata(metadata)
173178

174179
# Assert
175-
programmable_constraint.get_updated_metadata.assert_called_once_with(metadata)
180+
programmable_constraint.get_updated_metadata.assert_called_once_with(copied_metadata)
176181

177182
def test__fit(self):
178183
"""Test the ``_fit`` method."""

0 commit comments

Comments
 (0)