folio-migration-tools 1.9.0rc6__py3-none-any.whl → 1.9.0rc7__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.
- folio_migration_tools/custom_exceptions.py +7 -7
- folio_migration_tools/mapping_file_transformation/item_mapper.py +2 -4
- folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +3 -7
- folio_migration_tools/marc_rules_transformation/conditions.py +1 -1
- folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +4 -1
- folio_migration_tools/transaction_migration/legacy_loan.py +25 -27
- {folio_migration_tools-1.9.0rc6.dist-info → folio_migration_tools-1.9.0rc7.dist-info}/METADATA +1 -1
- {folio_migration_tools-1.9.0rc6.dist-info → folio_migration_tools-1.9.0rc7.dist-info}/RECORD +11 -11
- {folio_migration_tools-1.9.0rc6.dist-info → folio_migration_tools-1.9.0rc7.dist-info}/LICENSE +0 -0
- {folio_migration_tools-1.9.0rc6.dist-info → folio_migration_tools-1.9.0rc7.dist-info}/WHEEL +0 -0
- {folio_migration_tools-1.9.0rc6.dist-info → folio_migration_tools-1.9.0rc7.dist-info}/entry_points.txt +0 -0
|
@@ -5,12 +5,12 @@ import i18n
|
|
|
5
5
|
from folio_migration_tools import StrCoercible
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class
|
|
8
|
+
class TransformationError(Exception):
|
|
9
9
|
pass
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class TransformationFieldMappingError(
|
|
13
|
-
"""Raised when the
|
|
12
|
+
class TransformationFieldMappingError(TransformationError):
|
|
13
|
+
"""Raised when the field mapping fails, but the error is not critical.
|
|
14
14
|
The issue should be logged for the library to act upon it"""
|
|
15
15
|
|
|
16
16
|
def __init__(self, index_or_id="", message="", data_value: Union[str, StrCoercible]=""):
|
|
@@ -35,8 +35,8 @@ class TransformationFieldMappingError(TransfomationError):
|
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
class TransformationRecordFailedError(
|
|
39
|
-
"""Raised when the
|
|
38
|
+
class TransformationRecordFailedError(TransformationError):
|
|
39
|
+
"""Raised when the field mapping fails, Error is critical and means transformation fails"""
|
|
40
40
|
|
|
41
41
|
def __init__(self, index_or_id, message="", data_value=""):
|
|
42
42
|
self.index_or_id = index_or_id
|
|
@@ -61,8 +61,8 @@ class TransformationRecordFailedError(TransfomationError):
|
|
|
61
61
|
)
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
class TransformationProcessError(
|
|
65
|
-
"""Raised when the transformation fails due to incorrect
|
|
64
|
+
class TransformationProcessError(TransformationError):
|
|
65
|
+
"""Raised when the transformation fails due to incorrect configuration,
|
|
66
66
|
mapping or reference data. This error should take the process to a halt."""
|
|
67
67
|
|
|
68
68
|
def __init__(
|
|
@@ -75,9 +75,7 @@ class ItemMapper(MappingFileMapperBase):
|
|
|
75
75
|
self.folio_client,
|
|
76
76
|
"/locations",
|
|
77
77
|
"locations",
|
|
78
|
-
|
|
79
|
-
temporary_location_mapping, self.folio_client.locations
|
|
80
|
-
),
|
|
78
|
+
temporary_location_mapping,
|
|
81
79
|
"code",
|
|
82
80
|
"TemporaryLocationMapping",
|
|
83
81
|
)
|
|
@@ -118,7 +116,7 @@ class ItemMapper(MappingFileMapperBase):
|
|
|
118
116
|
self.folio_client,
|
|
119
117
|
"/locations",
|
|
120
118
|
"locations",
|
|
121
|
-
|
|
119
|
+
location_map,
|
|
122
120
|
"code",
|
|
123
121
|
"LocationMapping",
|
|
124
122
|
)
|
|
@@ -755,12 +755,8 @@ class MappingFileMapperBase(MapperBase):
|
|
|
755
755
|
for k in data
|
|
756
756
|
if k["folio_field"] == folio_prop_name
|
|
757
757
|
and any(
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
is_set_or_bool_or_numeric(k.get("legacy_field", "")),
|
|
761
|
-
is_set_or_bool_or_numeric(k.get("fallback_legacy_field", "")),
|
|
762
|
-
is_set_or_bool_or_numeric(k.get("fallback_value", "")),
|
|
763
|
-
]
|
|
758
|
+
is_set_or_bool_or_numeric(k.get(key, ""))
|
|
759
|
+
for key in ("value", "legacy_field", "fallback_legacy_field", "fallback_value")
|
|
764
760
|
)
|
|
765
761
|
)
|
|
766
762
|
|
|
@@ -972,4 +968,4 @@ def in_deep(dictionary, keys):
|
|
|
972
968
|
|
|
973
969
|
|
|
974
970
|
def is_set_or_bool_or_numeric(any_value):
|
|
975
|
-
return
|
|
971
|
+
return (isinstance(any_value, str) and (any_value.strip() not in empty_vals)) or isinstance(any_value, (int, float, complex))
|
|
@@ -818,7 +818,7 @@ class Conditions:
|
|
|
818
818
|
"""
|
|
819
819
|
This method handles the mapping of electronic access relationship IDs.
|
|
820
820
|
If the record type being mapped is FOLIO holdings, it provides an (optional) alternative
|
|
821
|
-
mapping
|
|
821
|
+
mapping based on a provided name parameter, bypassing the FOLIO MARC-to-Holdings mapping
|
|
822
822
|
engine behavior. This requires use of a supplemental mapping rules file in the
|
|
823
823
|
HoldingsMarcTransformer task definition containing the name parameter.
|
|
824
824
|
"""
|
|
@@ -61,7 +61,10 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
61
61
|
self.boundwith_relationship_map = self.setup_boundwith_relationship_map(
|
|
62
62
|
boundwith_relationship_map
|
|
63
63
|
)
|
|
64
|
-
self.location_map =
|
|
64
|
+
self.location_map = self.validate_location_map(
|
|
65
|
+
location_map,
|
|
66
|
+
self.folio_client.locations,
|
|
67
|
+
)
|
|
65
68
|
self.holdings_id_map: dict = {}
|
|
66
69
|
self.ref_data_dicts: dict = {}
|
|
67
70
|
self.fallback_holdings_type_id = self.task_configuration.fallback_holdings_type_id
|
|
@@ -3,9 +3,10 @@ from datetime import datetime
|
|
|
3
3
|
from zoneinfo import ZoneInfo
|
|
4
4
|
|
|
5
5
|
from dateutil import tz
|
|
6
|
-
from dateutil.parser import parse
|
|
6
|
+
from dateutil.parser import parse, ParserError
|
|
7
7
|
|
|
8
8
|
from folio_migration_tools.migration_report import MigrationReport
|
|
9
|
+
from folio_migration_tools.custom_exceptions import TransformationProcessError
|
|
9
10
|
|
|
10
11
|
utc = ZoneInfo("UTC")
|
|
11
12
|
|
|
@@ -42,46 +43,47 @@ class LegacyLoan(object):
|
|
|
42
43
|
|
|
43
44
|
self.tenant_timezone = tenant_timezone
|
|
44
45
|
self.errors = []
|
|
46
|
+
self.row = row
|
|
45
47
|
for prop in correct_headers:
|
|
46
48
|
if prop not in legacy_loan_dict and prop not in optional_headers:
|
|
47
|
-
self.errors.append(("Missing properties in legacy data", prop))
|
|
49
|
+
self.errors.append((f"Missing properties in legacy data {row=}", prop))
|
|
48
50
|
if (
|
|
49
51
|
prop != "next_item_status"
|
|
50
52
|
and not legacy_loan_dict.get(prop, "").strip()
|
|
51
53
|
and prop not in optional_headers
|
|
52
54
|
):
|
|
53
|
-
self.errors.append(("Empty properties in legacy data", prop))
|
|
55
|
+
self.errors.append((f"Empty properties in legacy data {row=}", prop))
|
|
54
56
|
try:
|
|
55
57
|
temp_date_due: datetime = parse(legacy_loan_dict["due_date"])
|
|
56
58
|
if temp_date_due.tzinfo != tz.UTC:
|
|
57
59
|
temp_date_due = temp_date_due.replace(tzinfo=self.tenant_timezone)
|
|
58
60
|
self.report(
|
|
59
|
-
f"Provided due_date is not UTC, "
|
|
60
|
-
f"setting
|
|
61
|
+
f"Provided due_date is not UTC in {row=}, "
|
|
62
|
+
f"setting tz-info to tenant timezone ({self.tenant_timezone})"
|
|
61
63
|
)
|
|
62
64
|
if temp_date_due.hour == 0 and temp_date_due.minute == 0:
|
|
63
65
|
temp_date_due = temp_date_due.replace(hour=23, minute=59)
|
|
64
66
|
self.report(
|
|
65
|
-
"Hour and minute not specified for due date. "
|
|
67
|
+
f"Hour and minute not specified for due date in {row=}. "
|
|
66
68
|
"Assuming end of local calendar day (23:59)..."
|
|
67
69
|
)
|
|
68
|
-
except
|
|
70
|
+
except (ParserError, OverflowError) as ee:
|
|
69
71
|
logging.error(ee)
|
|
70
|
-
self.errors.append(("Parse date failure. Setting UTC NOW", "due_date"))
|
|
72
|
+
self.errors.append((f"Parse date failure in {row=}. Setting UTC NOW", "due_date"))
|
|
71
73
|
temp_date_due = datetime.now(ZoneInfo("UTC"))
|
|
72
74
|
try:
|
|
73
75
|
temp_date_out: datetime = parse(legacy_loan_dict["out_date"])
|
|
74
76
|
if temp_date_out.tzinfo != tz.UTC:
|
|
75
77
|
temp_date_out = temp_date_out.replace(tzinfo=self.tenant_timezone)
|
|
76
78
|
self.report(
|
|
77
|
-
f"Provided out_date is not UTC, "
|
|
78
|
-
f"setting
|
|
79
|
+
f"Provided out_date is not UTC in {row=}, "
|
|
80
|
+
f"setting tz-info to tenant timezone ({self.tenant_timezone})"
|
|
79
81
|
)
|
|
80
|
-
except
|
|
82
|
+
except (ParserError, OverflowError):
|
|
81
83
|
temp_date_out = datetime.now(
|
|
82
84
|
ZoneInfo("UTC")
|
|
83
85
|
) # TODO: Consider moving this assignment block above the temp_date_due
|
|
84
|
-
self.errors.append(("Parse date failure. Setting UTC NOW", "out_date"))
|
|
86
|
+
self.errors.append((f"Parse date failure in {row=}. Setting UTC NOW", "out_date"))
|
|
85
87
|
|
|
86
88
|
# good to go, set properties
|
|
87
89
|
self.item_barcode: str = legacy_loan_dict["item_barcode"].strip()
|
|
@@ -94,7 +96,7 @@ class LegacyLoan(object):
|
|
|
94
96
|
self.renewal_count = self.set_renewal_count(legacy_loan_dict)
|
|
95
97
|
self.next_item_status = legacy_loan_dict.get("next_item_status", "").strip()
|
|
96
98
|
if self.next_item_status not in legal_statuses:
|
|
97
|
-
self.errors.append(("Not an allowed status", self.next_item_status))
|
|
99
|
+
self.errors.append((f"Not an allowed status {row=}", self.next_item_status))
|
|
98
100
|
self.service_point_id = (
|
|
99
101
|
legacy_loan_dict["service_point_id"]
|
|
100
102
|
if legacy_loan_dict.get("service_point_id", "")
|
|
@@ -107,23 +109,19 @@ class LegacyLoan(object):
|
|
|
107
109
|
try:
|
|
108
110
|
return int(renewal_count)
|
|
109
111
|
except ValueError:
|
|
110
|
-
self.report(
|
|
111
|
-
f"Unresolvable {renewal_count=} was replaced with 0.")
|
|
112
|
+
self.report(f"Unresolvable {renewal_count=} was replaced with 0.")
|
|
112
113
|
else:
|
|
113
114
|
self.report(f"Missing renewal count was replaced with 0.")
|
|
114
115
|
return 0
|
|
115
116
|
|
|
116
117
|
def correct_for_1_day_loans(self):
|
|
117
|
-
|
|
118
|
-
if self.due_date.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
raise ValueError("Due date is before out date")
|
|
125
|
-
except Exception:
|
|
126
|
-
self.errors.append(("Time alignment issues", "both dates"))
|
|
118
|
+
if self.due_date.date() <= self.out_date.date():
|
|
119
|
+
if self.due_date.hour == 0:
|
|
120
|
+
self.due_date = self.due_date.replace(hour=23, minute=59)
|
|
121
|
+
if self.out_date.hour == 0:
|
|
122
|
+
self.out_date = self.out_date.replace(hour=0, minute=1)
|
|
123
|
+
if self.due_date <= self.out_date:
|
|
124
|
+
raise TransformationProcessError(self.row, "Due date is before out date")
|
|
127
125
|
|
|
128
126
|
def to_dict(self):
|
|
129
127
|
return {
|
|
@@ -140,8 +138,8 @@ class LegacyLoan(object):
|
|
|
140
138
|
if self.tenant_timezone != ZoneInfo("UTC"):
|
|
141
139
|
self.due_date = self.due_date.astimezone(ZoneInfo("UTC"))
|
|
142
140
|
self.out_date = self.out_date.astimezone(ZoneInfo("UTC"))
|
|
143
|
-
except
|
|
144
|
-
self.errors.append(("UTC correction issues", "both dates"))
|
|
141
|
+
except TypeError:
|
|
142
|
+
self.errors.append((f"UTC correction issues {self.row}", "both dates"))
|
|
145
143
|
|
|
146
144
|
def report(self, what_to_report: str):
|
|
147
145
|
self.migration_report.add("Details", what_to_report)
|
{folio_migration_tools-1.9.0rc6.dist-info → folio_migration_tools-1.9.0rc7.dist-info}/RECORD
RENAMED
|
@@ -4,7 +4,7 @@ folio_migration_tools/circulation_helper.py,sha256=2kAkLM6caPiep0ZtBkMICbRDh53Kd
|
|
|
4
4
|
folio_migration_tools/colors.py,sha256=GP0wdI_GZ2WD5SjrbPN-S3u8vvN_u6rGQIBBcWv_0ZM,227
|
|
5
5
|
folio_migration_tools/config_file_load.py,sha256=zHHa6NDkN6EJiQE4DgjrFQPVKsd70POsfbGkB8308jg,2822
|
|
6
6
|
folio_migration_tools/custom_dict.py,sha256=-FUnhKp90Dg8EHlY6twx-PYQxBUWEO7FgxL2b7pf-xk,678
|
|
7
|
-
folio_migration_tools/custom_exceptions.py,sha256=
|
|
7
|
+
folio_migration_tools/custom_exceptions.py,sha256=1zgOKy3NBUVGG6i9YxK6w2Hntlea8MHmm7mdnjBtzvQ,2687
|
|
8
8
|
folio_migration_tools/extradata_writer.py,sha256=fuchNcMc6BYb9IyfAcvXg7X4J2TfX6YiROfT2hr0JMw,1678
|
|
9
9
|
folio_migration_tools/folder_structure.py,sha256=yyVvbkM9PbczSHNI8vK0Ru7i0x4nbYGzrRriXrnIh38,6715
|
|
10
10
|
folio_migration_tools/helper.py,sha256=KkOkNAGO_fuYqxdLrsbLzCJLQHUrFZG1NzD4RmpQ-KM,2804
|
|
@@ -15,16 +15,16 @@ folio_migration_tools/mapper_base.py,sha256=ftYQJ6UDsP96EvCr5t3yMJemsmSNXsSH5zCh
|
|
|
15
15
|
folio_migration_tools/mapping_file_transformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
folio_migration_tools/mapping_file_transformation/courses_mapper.py,sha256=mJQxxeTn1bCYb2zwFYyXJ6EGZpJ0DsmwOY3nED7D_gQ,8091
|
|
17
17
|
folio_migration_tools/mapping_file_transformation/holdings_mapper.py,sha256=nJS-xx1LszvbYfw0qdTUHX9xXHlxS7wP5mYmixFMh8A,7221
|
|
18
|
-
folio_migration_tools/mapping_file_transformation/item_mapper.py,sha256=
|
|
18
|
+
folio_migration_tools/mapping_file_transformation/item_mapper.py,sha256=KiE-y6ZcKAV2XMqrgax3mx3KHB_oRxBfCBSanIBs95E,10853
|
|
19
19
|
folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py,sha256=nCkqbxaDHKxMuqQHh_afxQp48YrVD-SeCZ0L1iGvnkk,13402
|
|
20
|
-
folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py,sha256=
|
|
20
|
+
folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py,sha256=vu-5dw20NbxpDTDNq2zIgbto8KkWMf6ImXj2U0XbHPg,37812
|
|
21
21
|
folio_migration_tools/mapping_file_transformation/notes_mapper.py,sha256=auLQZqa4rSJo_MIV4Lc5-LG8RcBpp2bnKH243qNYq_0,3470
|
|
22
22
|
folio_migration_tools/mapping_file_transformation/order_mapper.py,sha256=k-kIuf2ceXrPWe3oVnfhuQlE7eglcx6PDLVJtddkeiM,17680
|
|
23
23
|
folio_migration_tools/mapping_file_transformation/organization_mapper.py,sha256=0zjw0-C-qTYH9GC6FDBElucWCZWdoOiTHOY7q9_4NQg,14571
|
|
24
24
|
folio_migration_tools/mapping_file_transformation/ref_data_mapping.py,sha256=qFsn_LwKZeKFdOudfEQnNA3DEHOdNQVKzTPdZAlDPX0,8864
|
|
25
25
|
folio_migration_tools/mapping_file_transformation/user_mapper.py,sha256=oWuIPRQL0anF_qTVFibHtc1oOaqyKCBH4O1hX5rQAZQ,7806
|
|
26
26
|
folio_migration_tools/marc_rules_transformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
-
folio_migration_tools/marc_rules_transformation/conditions.py,sha256=
|
|
27
|
+
folio_migration_tools/marc_rules_transformation/conditions.py,sha256=ttTZISieqveu3YpvpnawHh3In1_DNQMTziI5yasfmWU,39142
|
|
28
28
|
folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py,sha256=lTb5QWEAgwyFHy5vdSK6oDl1Q5v2GnzuV04xWV3p4rc,12401
|
|
29
29
|
folio_migration_tools/marc_rules_transformation/hrid_handler.py,sha256=Ihdv0_1q7gL_pZ3HWU3GcfV_jjpIfOLithWk9z_uH3Y,9997
|
|
30
30
|
folio_migration_tools/marc_rules_transformation/loc_language_codes.xml,sha256=ztn2_yKws6qySL4oSsZh7sOjxq5bCC1PhAnXJdtgmJ0,382912
|
|
@@ -33,7 +33,7 @@ folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py,sha256=9A
|
|
|
33
33
|
folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py,sha256=GFw8j9UtCxnUdLShmPzJa1MpCK8a0NkQIN5C3jyouRs,9604
|
|
34
34
|
folio_migration_tools/marc_rules_transformation/rules_mapper_base.py,sha256=-vJDMNZe-7JbARgybVj6lLtZM79PgWU9V_k23330uLM,41195
|
|
35
35
|
folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py,sha256=ckVeysbpW9s19pmHvogdRFOCouzz17Y6oKJD0_QfQAk,28924
|
|
36
|
-
folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py,sha256=
|
|
36
|
+
folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py,sha256=p_WIsn-6VphLNVCeDyvTEv-tdYFU5QuV4GhnM4gvwt8,19046
|
|
37
37
|
folio_migration_tools/migration_report.py,sha256=BkRspM1hwTBnWeqsHamf7yVEofzLj560Q-9G--O00hw,4258
|
|
38
38
|
folio_migration_tools/migration_tasks/__init__.py,sha256=ZkbY_yGyB84Ke8OMlYUzyyBj4cxxNrhMTwQlu_GbdDs,211
|
|
39
39
|
folio_migration_tools/migration_tasks/authority_transformer.py,sha256=AoXg9s-GLO3yEEDCrQV7hc4YVXxwxsdxDdpj1zhHydE,4251
|
|
@@ -55,13 +55,13 @@ folio_migration_tools/task_configuration.py,sha256=C5-OQtZLH7b4lVeyj5v8OXsqKNN4t
|
|
|
55
55
|
folio_migration_tools/test_infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
56
56
|
folio_migration_tools/test_infrastructure/mocked_classes.py,sha256=rNes6UlRqIWGwPurfiQK97IvgB5OPwnZTbv1T28jHzk,9150
|
|
57
57
|
folio_migration_tools/transaction_migration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
|
-
folio_migration_tools/transaction_migration/legacy_loan.py,sha256=
|
|
58
|
+
folio_migration_tools/transaction_migration/legacy_loan.py,sha256=3PDyC1wbJzF0CcNWelvZ0tC8hjl3p5hbLVJHrz78ORM,6006
|
|
59
59
|
folio_migration_tools/transaction_migration/legacy_request.py,sha256=1ulyFzPQw_InOjyPzkWpGnNptgXdQ18nmri0J8Nlpkc,6124
|
|
60
60
|
folio_migration_tools/transaction_migration/legacy_reserve.py,sha256=d0qbh2fWpwlVSYRL6wZyZG20__NAYNxh7sPSsB-LAes,1804
|
|
61
61
|
folio_migration_tools/transaction_migration/transaction_result.py,sha256=cTdCN0BnlI9_ZJB2Z3Fdkl9gpymIi-9mGZsRFlQcmDk,656
|
|
62
62
|
folio_migration_tools/translations/en.json,sha256=HOVpkb_T-SN_x0NpDp8gyvV1hMLCui3SsG7ByyIv0OU,38669
|
|
63
|
-
folio_migration_tools-1.9.
|
|
64
|
-
folio_migration_tools-1.9.
|
|
65
|
-
folio_migration_tools-1.9.
|
|
66
|
-
folio_migration_tools-1.9.
|
|
67
|
-
folio_migration_tools-1.9.
|
|
63
|
+
folio_migration_tools-1.9.0rc7.dist-info/LICENSE,sha256=PhIEkitVi3ejgq56tt6sWoJIG_zmv82cjjd_aYPPGdI,1072
|
|
64
|
+
folio_migration_tools-1.9.0rc7.dist-info/METADATA,sha256=ZBN-JMKfGXNzGGKEgecmOsbOS49pl09CF7KtyfVBhKs,7415
|
|
65
|
+
folio_migration_tools-1.9.0rc7.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
66
|
+
folio_migration_tools-1.9.0rc7.dist-info/entry_points.txt,sha256=Hbe-HjqMcU8FwVshVIkeWyZd9XwgT1CCMNf06EpHQu8,77
|
|
67
|
+
folio_migration_tools-1.9.0rc7.dist-info/RECORD,,
|
{folio_migration_tools-1.9.0rc6.dist-info → folio_migration_tools-1.9.0rc7.dist-info}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|