ims.fieldupdater 3.0.0rc2__py3-none-any.whl → 3.0.1__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.
@@ -1,2 +1,4 @@
1
1
  from zope.i18nmessageid import MessageFactory
2
- _ = MessageFactory('ims.fieldupdater')
2
+
3
+ _ = MessageFactory("ims.fieldupdater")
4
+ __version__ = "3.0.1"
@@ -1,6 +1,6 @@
1
1
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"
2
2
  lang="en-US"
3
- metal:use-macro="context/prefs_main_template/macros/master"
3
+ metal:use-macro="context/prefs_main_template/macros/master">
4
4
  <tal:icon tal:replace="structure python:icons.tag('plone-statusmessage-info', tag_alt='status', tag_class='statusmessage-icon mb-1 me-2')" />
5
5
  i18n:domain="ims.fieldupdater">
6
6
 
@@ -26,34 +26,36 @@ def get_behav(name):
26
26
 
27
27
 
28
28
  class MassEditForm(BrowserView):
29
- template = ViewPageTemplateFile('mass.pt')
29
+ template = ViewPageTemplateFile("mass.pt")
30
30
  unsupported = None
31
31
 
32
32
  def __call__(self):
33
- if not self.request.form.get('form.button.Merge', '') and not self.request.form.get('form.button.Delete', ''):
33
+ if not self.request.form.get("form.button.Merge", "") and not self.request.form.get("form.button.Delete", ""):
34
34
  return self.template({})
35
35
 
36
- schema = self.request.get('schema', None)
37
- field = self.request.get('field', None)
38
- fkey = self.request.get('fkey', None)
39
- match = self.request.get('match', None)
40
- replacement = self.request.get('replacement_marker', None)
36
+ schema = self.request.get("schema", None)
37
+ field = self.request.get("field", None)
38
+ fkey = self.request.get("fkey", None)
39
+ match = self.request.get("match", None)
40
+ replacement = self.request.get("replacement_marker", None)
41
41
 
42
- if self.request.form.get('form.button.Merge', ''):
42
+ if self.request.form.get("form.button.Merge", ""):
43
43
  if replacement:
44
44
  try:
45
45
  self.replace_term(schema, field, fkey, match)
46
46
  except Exception as e:
47
- api.portal.show_message(message='Failed to validate: %s' % e.__repr__(), request=self.request,
48
- type='error')
47
+ api.portal.show_message(
48
+ message=f"Failed to validate: {e.__repr__()}", request=self.request, type="error"
49
+ )
49
50
  else:
50
- api.portal.show_message(message='Please enter a replacement value.', request=self.request)
51
- elif self.request.form.get('form.button.Delete', ''):
51
+ api.portal.show_message(message="Please enter a replacement value.", request=self.request)
52
+ elif self.request.form.get("form.button.Delete", ""):
52
53
  try:
53
54
  self.delete_term(schema, field, fkey, match)
54
55
  except Exception as e:
55
- api.portal.show_message(message='Failed to validate: %s' % e.__repr__(), request=self.request,
56
- type='error')
56
+ api.portal.show_message(
57
+ message=f"Failed to validate: {e.__repr__()}", request=self.request, type="error"
58
+ )
57
59
 
58
60
  return self.template()
59
61
 
@@ -64,14 +66,14 @@ class MassEditForm(BrowserView):
64
66
  :return: dotted name of interfaces
65
67
  """
66
68
  behaviors = tuple([behav[1].interface.__identifier__ for behav in getUtilitiesFor(IBehavior)])
67
- catalog = api.portal.get_tool('portal_catalog')
68
- interfaces = sorted(list(set(catalog.uniqueValuesFor('object_provides') + behaviors)),
69
- key=lambda term: term.split('.')[-1])
69
+ catalog = api.portal.get_tool("portal_catalog")
70
+ interfaces = sorted(set(catalog.uniqueValuesFor("object_provides") + behaviors),
71
+ key=lambda term: term.split(".")[-1])
70
72
  for interface in interfaces:
71
73
  if get_behav(interface).names():
72
74
  yield {
73
- 'id': interface,
74
- 'title': interface.split('.')[-1],
75
+ "id": interface,
76
+ "title": interface.split(".")[-1],
75
77
  }
76
78
 
77
79
  def schema_matches(self, schema):
@@ -80,45 +82,41 @@ class MassEditForm(BrowserView):
80
82
  :param schema: dotted name interface
81
83
  :return: int
82
84
  """
83
- catalog = api.portal.get_tool('portal_catalog')
84
- if schema in catalog.uniqueValuesFor('object_provides'):
85
+ catalog = api.portal.get_tool("portal_catalog")
86
+ if schema in catalog.uniqueValuesFor("object_provides"):
85
87
  return len(catalog(object_provides=schema))
86
88
  else:
87
- return 'unknown (cannot get a subset for behavior interfaces)'
89
+ return "unknown (cannot get a subset for behavior interfaces)"
88
90
 
89
91
  def get_fields(self):
90
92
  """
91
93
  Get all fields for a schema
92
94
  :return: fields
93
95
  """
94
- schema = self.request.get('schema', None)
96
+ schema = self.request.get("schema", None)
95
97
  if not schema:
96
98
  return
97
99
  interface = get_behav(schema)
98
100
  for name in interface.names():
99
- if interface[name] and hasattr(interface[name], 'title'):
100
- yield {
101
- 'id': name,
102
- 'title': '%s [%s]' % (interface[name].title, name)
103
- }
101
+ if interface[name] and hasattr(interface[name], "title"):
102
+ yield {"id": name, "title": f"{interface[name].title} [{name}]"}
104
103
 
105
104
  def is_dg(self):
106
105
  """
107
106
  DataGridField (collective.z3cform.datagridfield) support. Lists with dicts
108
107
  :return: bool
109
108
  """
110
- schema = self.request.get('schema', None)
111
- field = self.request.get('field', None)
109
+ schema = self.request.get("schema", None)
110
+ field = self.request.get("field", None)
112
111
  if not field or not schema:
113
112
  return
114
113
  interface = get_behav(schema)
115
- return hasattr(interface[field], 'value_type') and isinstance(interface[field].value_type, DictRow)
114
+ return hasattr(interface[field], "value_type") and isinstance(interface[field].value_type, DictRow)
116
115
 
117
116
  def get_dgschema(self):
118
- """ Look up the schema used for the dg field
119
- """
120
- schema = self.request.get('schema', None)
121
- field = self.request.get('field', None)
117
+ """Look up the schema used for the dg field"""
118
+ schema = self.request.get("schema", None)
119
+ field = self.request.get("field", None)
122
120
  if not field or not schema:
123
121
  return
124
122
  interface = get_behav(schema)
@@ -132,31 +130,27 @@ class MassEditForm(BrowserView):
132
130
  dg_schema = self.get_dgschema()
133
131
  for dg_field in dg_schema.names():
134
132
  yield {
135
- 'id': dg_field,
136
- 'title': dg_schema[dg_field].title,
133
+ "id": dg_field,
134
+ "title": dg_schema[dg_field].title,
137
135
  }
138
136
 
139
- def get_values(self):
137
+ def get_values(self): # noqa: C901
140
138
  """
141
- Find all of the current values for objects that provide this schema
139
+ Find all the current values for objects that provide this schema
142
140
 
143
141
  :return: values
144
142
  """
145
143
  self.unsupported = None
146
- schema = self.request.get('schema', None)
147
- field = self.request.get('field', None)
148
- fkey = self.request.get('fkey', None)
144
+ schema = self.request.get("schema", None)
145
+ field = self.request.get("field", None)
146
+ fkey = self.request.get("fkey", None)
149
147
 
150
- if self.is_dg() and not (schema and field and fkey):
151
- return
152
- elif not self.is_dg() and not (schema and field):
148
+ if (self.is_dg() and not (schema and field and fkey)) or (not self.is_dg() and not (schema and field)):
153
149
  return
154
150
  values = set()
155
- catalog = api.portal.get_tool('portal_catalog')
156
- if schema in catalog.uniqueValuesFor('object_provides'):
157
- query = catalog(object_provides=schema)
158
- else:
159
- query = catalog()
151
+ catalog = api.portal.get_tool("portal_catalog")
152
+ query = catalog(object_provides=schema) if schema in catalog.uniqueValuesFor("object_provides") else catalog()
153
+
160
154
  for brain in query:
161
155
  obj = brain.getObject()
162
156
  field_value = getattr(obj, field, None)
@@ -164,19 +158,19 @@ class MassEditForm(BrowserView):
164
158
  continue
165
159
  if field_value and isinstance(field_value, str):
166
160
  values.add(field_value)
167
- elif field_value and isinstance(field_value, tuple) or isinstance(field_value, list):
161
+ elif field_value and isinstance(field_value, tuple | list):
168
162
  for item_value in field_value:
169
- if fkey:
163
+ if fkey: # dg
170
164
  if item_value[fkey] and isinstance(item_value[fkey], str):
171
165
  values.add(item_value[fkey])
172
- else:
166
+ else: # regular list or tuple
173
167
  if item_value and isinstance(item_value, str):
174
168
  values.add(item_value)
175
- elif field_value and (isinstance(field_value, datetime.datetime) or isinstance(field_value, datetime.date)):
169
+ elif field_value and isinstance(field_value, datetime.datetime | datetime.date):
176
170
  values.add(field_value)
177
171
  else:
178
172
  self.unsupported = field_value.__class__.__name__
179
- return sorted(list(values))
173
+ return sorted(values)
180
174
 
181
175
  def results(self):
182
176
  """
@@ -184,10 +178,10 @@ class MassEditForm(BrowserView):
184
178
 
185
179
  :return: brains
186
180
  """
187
- schema = self.request.get('schema', None)
188
- field = self.request.get('field', None)
189
- fkey = self.request.get('fkey', None)
190
- match = self.request.get('match', None)
181
+ schema = self.request.get("schema", None)
182
+ field = self.request.get("field", None)
183
+ fkey = self.request.get("fkey", None)
184
+ match = self.request.get("match", None)
191
185
  if not schema or not field:
192
186
  return
193
187
  if self.is_dg() and not fkey:
@@ -195,24 +189,20 @@ class MassEditForm(BrowserView):
195
189
  if not match:
196
190
  return
197
191
 
198
- catalog = api.portal.get_tool('portal_catalog')
192
+ catalog = api.portal.get_tool("portal_catalog")
199
193
  _results = []
200
- if schema in catalog.uniqueValuesFor('object_provides'):
201
- query = catalog(object_provides=schema)
202
- else:
203
- query = catalog()
194
+ query = catalog(object_provides=schema) if schema in catalog.uniqueValuesFor("object_provides") else catalog()
204
195
  for brain in query:
205
196
  obj = brain.getObject()
206
197
  field_value = getattr(obj, field, None)
207
- if field_value == match and isinstance(field_value, str):
208
- _results.append(brain)
209
- elif (isinstance(field_value, tuple) or isinstance(field_value, list)) and match in field_value:
210
- _results.append(brain)
211
- elif fkey and match in [item_value[fkey] for item_value in field_value]:
212
- _results.append(brain)
213
- elif isinstance(field_value, datetime.date) and DateTime(match).asdatetime().date() == field_value:
214
- _results.append(brain)
215
- elif isinstance(field_value, datetime.date) and DateTime(match).asdatetime() == field_value:
198
+ checks = [
199
+ field_value == match and isinstance(field_value, str), # str
200
+ isinstance(field_value, tuple | list) and match in field_value, # iterator
201
+ fkey and match in [item_value[fkey] for item_value in field_value], # dg
202
+ isinstance(field_value, datetime.date) and DateTime(match).asdatetime().date() == field_value,
203
+ isinstance(field_value, datetime.date) and DateTime(match).asdatetime() == field_value
204
+ ]
205
+ if any(checks):
216
206
  _results.append(brain)
217
207
  return _results
218
208
 
@@ -237,31 +227,36 @@ class MassEditForm(BrowserView):
237
227
  # for some reason some things that should come in as unicode are coming in as strings
238
228
  replacement = IDataConverter(widget).toFieldValue(IDataConverter(widget).toWidgetValue(replacement))
239
229
  if not replacement or replacement is NO_VALUE:
240
- api.portal.show_message(message=_('No replacement value given'), request=self.request, type='error')
230
+ api.portal.show_message(message=_("No replacement value given"), request=self.request, type="error")
241
231
  return
242
232
 
243
233
  results = self.results()
244
234
  for brain in results:
245
- obj = brain.getObject()
246
- field_value = getattr(obj, field, None)
247
-
248
- if isinstance(field_value, str) or \
249
- isinstance(field_value, datetime.date) or isinstance(field_value, datetime.datetime):
250
- self.set_value(obj, schema, field, replacement)
251
- elif isinstance(field_value, tuple) or isinstance(field_value, list):
252
- if fkey:
253
- for item_value in field_value:
254
- if item_value[fkey] == match:
255
- item_value[fkey] = replacement
256
- self.set_value(obj, schema, field, field_value)
235
+ self.set_value_by_type(brain, schema, field, fkey, match, replacement)
236
+ api.portal.show_message(
237
+ message=_(f"Replaced term in {len(results)} records"), request=self.request, type="info"
238
+ )
239
+
240
+ def set_value_by_type(self, brain, schema, field, fkey, match, replacement):
241
+ """ Set value based on field value type """
242
+ obj = brain.getObject()
243
+
244
+ field_value = getattr(obj, field, None)
245
+ if isinstance(field_value, str | datetime.date | datetime.datetime):
246
+ self.set_value(obj, schema, field, replacement)
247
+ elif isinstance(field_value, tuple | list):
248
+ if fkey:
249
+ for item_value in field_value:
250
+ if item_value[fkey] == match:
251
+ item_value[fkey] = replacement
252
+ self.set_value(obj, schema, field, field_value)
253
+ else:
254
+ if replacement in field_value:
255
+ field_value = [item_value for item_value in field_value if item_value != match]
257
256
  else:
258
- if replacement in field_value:
259
- field_value = [item_value for item_value in field_value if item_value != match]
260
- else:
261
- field_value = [item_value == match and replacement or item_value for item_value in field_value]
262
- self.set_value(obj, schema, field, field_value)
263
- api.portal.show_message(message=_('Replaced term in {} records'.format(len(results))),
264
- request=self.request, type='info')
257
+ field_value = [(item_value == match and replacement) or item_value for item_value in
258
+ field_value]
259
+ self.set_value(obj, schema, field, field_value)
265
260
 
266
261
  def delete_term(self, schema, field, fkey, match):
267
262
  """
@@ -278,21 +273,23 @@ class MassEditForm(BrowserView):
278
273
  obj = brain.getObject()
279
274
  field_value = getattr(obj, field, None)
280
275
 
281
- if isinstance(field_value, tuple) or isinstance(field_value, list):
276
+ if isinstance(field_value, tuple | list):
282
277
  if fkey:
283
278
  for item_value in field_value:
284
279
  if item_value[fkey] == match:
285
280
  item_value[fkey] = None
286
281
  # if this was the only value in the row, delete the row
287
- field_value = [item_value for item_value in field_value if
288
- [i for i in list(item_value.values()) if i]]
282
+ field_value = [
283
+ item_value for item_value in field_value if [i for i in list(item_value.values()) if i]
284
+ ]
289
285
  else:
290
286
  field_value = [item_value for item_value in field_value if item_value != match]
291
287
  self.set_value(obj, schema, field, field_value)
292
288
  else:
293
289
  self.set_value(obj, schema, field, None)
294
- api.portal.show_message(message=_('Removed term in {} records'.format(len(self.results()))),
295
- request=self.request, type='info')
290
+ api.portal.show_message(
291
+ message=_(f"Removed term in {len(self.results())} records"), request=self.request, type="info"
292
+ )
296
293
 
297
294
  def set_value(self, obj, dottedname, field, field_value, attempts=0):
298
295
  """
@@ -318,8 +315,9 @@ class MassEditForm(BrowserView):
318
315
  field_value = str(field_value)
319
316
  return self.set_value(obj, dottedname, field, field_value, attempts)
320
317
  else:
321
- api.portal.show_message(message='Failed to validate: %s' % e.__repr__(), request=self.request,
322
- type='error')
318
+ api.portal.show_message(
319
+ message=f"Failed to validate: {e.__repr__()}", request=self.request, type="error"
320
+ )
323
321
  else:
324
322
  setattr(obj, field, field_value)
325
323
  notify(ObjectModifiedEvent(obj))
@@ -335,36 +333,30 @@ class MassEditForm(BrowserView):
335
333
  :return: widget
336
334
  """
337
335
  if self.is_dg():
338
- fkey = self.request['fkey']
336
+ fkey = self.request["fkey"]
339
337
  field = self.get_dgschema()[fkey]
340
338
  else:
341
- schema = self.request.get('schema', None)
339
+ schema = self.request.get("schema", None)
342
340
  schema = get_behav(schema)
343
- field = self.request.get('field', None)
341
+ field = self.request.get("field", None)
344
342
  field = schema[field]
345
- if hasattr(field, 'value_type'):
343
+ if hasattr(field, "value_type"):
346
344
  field = field.value_type
347
345
 
348
346
  widget = getMultiAdapter((field, self.request), IFieldWidget)
349
- widget.name = 'replacement'
347
+ widget.name = "replacement"
350
348
  widget.update()
351
349
  return widget
352
350
 
353
351
 
354
352
  class SchemaFinderForm(BrowserView):
355
353
  def get_types(self):
356
- catalog = api.portal.get_tool('portal_catalog')
357
- return sorted(catalog.uniqueValuesFor('portal_type'))
354
+ catalog = api.portal.get_tool("portal_catalog")
355
+ return sorted(catalog.uniqueValuesFor("portal_type"))
358
356
 
359
357
  def schemas(self):
360
- content_type = self.request['content_type']
361
- type_info = api.portal.get_tool('portal_types').getTypeInfo(content_type)
362
- yield {
363
- 'id': type_info.schema,
364
- 'title': type_info.schema.split('.')[-1]
365
- }
358
+ content_type = self.request["content_type"]
359
+ type_info = api.portal.get_tool("portal_types").getTypeInfo(content_type)
360
+ yield {"id": type_info.schema, "title": type_info.schema.split(".")[-1]}
366
361
  for behav in type_info.behaviors:
367
- yield {
368
- 'id': behav,
369
- 'title': behav.split('.')[-1]
370
- }
362
+ yield {"id": behav, "title": behav.split(".")[-1]}
@@ -1,39 +1,53 @@
1
- import ims.fieldupdater
2
1
  from plone.app.contenttypes.testing import PLONE_APP_CONTENTTYPES_FIXTURE
3
- from plone.app.testing import PloneSandboxLayer, IntegrationTesting, FunctionalTesting, applyProfile
2
+ from plone.app.robotframework.testing import REMOTE_LIBRARY_BUNDLE_FIXTURE
3
+ from plone.app.testing import FunctionalTesting
4
+ from plone.app.testing import IntegrationTesting
5
+ from plone.app.testing import PloneSandboxLayer
6
+ from plone.app.testing import applyProfile
7
+ from plone.protect import auto
8
+ from plone.testing.zope import WSGI_SERVER_FIXTURE
9
+
10
+ import ims.fieldupdater
4
11
 
5
- has_dgf = True
6
- try:
7
- import collective.z3cform.datagridfield
8
- except ImportError:
9
- has_dgf = False
12
+ ORIGINAL_CSRF_DISABLED = auto.CSRF_DISABLED
10
13
 
11
14
 
12
- class FieldUpdaterSiteLayer(PloneSandboxLayer):
15
+ class FieldUpdaterLayer(PloneSandboxLayer):
13
16
  defaultBases = (PLONE_APP_CONTENTTYPES_FIXTURE,)
14
17
 
15
- def setUpZope(self, app, configuration_context):
16
- # Load any other ZCML that is required for your tests.
17
- # The z3c.autoinclude feature is disabled in the Plone fixture base
18
- # layer.
19
- if has_dgf:
20
- self.loadZCML(package=collective.z3cform.datagridfield)
18
+ def setUpZope(self, app, configurationContext):
19
+ auto.CSRF_DISABLED = True
21
20
  self.loadZCML(package=ims.fieldupdater)
22
21
 
22
+ def tearDownZope(self, app):
23
+ auto.CSRF_DISABLED = ORIGINAL_CSRF_DISABLED
24
+
23
25
  def setUpPloneSite(self, portal):
24
- if has_dgf:
25
- applyProfile(portal, 'collective.z3cform.datagridfield:default')
26
- applyProfile(portal, 'ims.fieldupdater:default')
26
+ applyProfile(portal, "ims.fieldupdater:default")
27
27
 
28
28
 
29
- FIELD_UPDATER_SITE_FIXTURE = FieldUpdaterSiteLayer()
29
+ FIXTURE = FieldUpdaterLayer()
30
+
31
+ INTEGRATION_TESTING = IntegrationTesting(
32
+ bases=(FIXTURE,),
33
+ name="FieldUpdaterLayer:IntegrationTesting",
34
+ )
35
+
36
+ FUNCTIONAL_TESTING = FunctionalTesting(
37
+ bases=(FIXTURE, WSGI_SERVER_FIXTURE),
38
+ name="FieldUpdaterLayer:FunctionalTesting",
39
+ )
30
40
 
31
- INTEGRATION = IntegrationTesting(
32
- bases=(FIELD_UPDATER_SITE_FIXTURE,),
33
- name="ims.fieldupdater:Integration"
41
+ RESTAPI_TESTING = FunctionalTesting(
42
+ bases=(FIXTURE, WSGI_SERVER_FIXTURE),
43
+ name="FieldUpdaterLayer:RestAPITesting",
34
44
  )
35
45
 
36
- FUNCTIONAL = FunctionalTesting(
37
- bases=(FIELD_UPDATER_SITE_FIXTURE,),
38
- name="ims.fieldupdater:Functional"
46
+ ACCEPTANCE_TESTING = FunctionalTesting(
47
+ bases=(
48
+ FIXTURE,
49
+ REMOTE_LIBRARY_BUNDLE_FIXTURE,
50
+ WSGI_SERVER_FIXTURE,
51
+ ),
52
+ name="FieldUpdaterLayer:AcceptanceTesting",
39
53
  )
@@ -1,18 +1,20 @@
1
- Metadata-Version: 2.1
2
- Name: ims.fieldupdater
3
- Version: 3.0.0rc2
4
- Summary: Update all objects in Plone based on a schema/field strategy
5
- Author-email: Eric Wohnlich <wohnlice@imsweb.com>
6
- License: GPL
7
- Project-URL: homepage, https://git.imsweb.com/plone/ims.fieldupdater
8
- Project-URL: documentation, https://git.imsweb.com/plone/ims.fieldupdater
9
- Project-URL: repository, https://git.imsweb.com/plone/ims.fieldupdater
10
- Classifier: Framework :: Plone :: 6.0
11
- Classifier: Programming Language :: Python
12
- Requires-Python: >=3.8
13
- Requires-Dist: plone >=6.0.4
14
- Provides-Extra: test
15
- Requires-Dist: plone.app.testing ; extra == 'test'
16
- Requires-Dist: plone.mocktestcase ; extra == 'test'
17
- Requires-Dist: formencode ; extra == 'test'
18
-
1
+ Metadata-Version: 2.4
2
+ Name: ims.fieldupdater
3
+ Version: 3.0.1
4
+ Summary: Update all objects in Plone based on a schema/field strategy
5
+ Project-URL: homepage, https://git.imsweb.com/plone/ims.fieldupdater
6
+ Project-URL: documentation, https://git.imsweb.com/plone/ims.fieldupdater
7
+ Project-URL: repository, https://git.imsweb.com/plone/ims.fieldupdater
8
+ Author-email: Eric Wohnlich <wohnlice@imsweb.com>
9
+ License: GPL
10
+ Classifier: Framework :: Plone :: 6.0
11
+ Classifier: Framework :: Plone :: 6.1
12
+ Classifier: Programming Language :: Python
13
+ Requires-Python: >=3.8
14
+ Requires-Dist: plone>=6.0.4
15
+ Provides-Extra: test
16
+ Requires-Dist: formencode; extra == 'test'
17
+ Requires-Dist: plone-app-robotframework; extra == 'test'
18
+ Requires-Dist: plone-app-testing; extra == 'test'
19
+ Requires-Dist: plone-mocktestcase; extra == 'test'
20
+ Requires-Dist: pytest-plone; extra == 'test'
@@ -0,0 +1,15 @@
1
+ ims/fieldupdater/__init__.py,sha256=3yK8CS4fOpjH1mIHIfDsR-wtvzbphfkmZ8RVqPK09To,112
2
+ ims/fieldupdater/configure.zcml,sha256=eAIJlfutXffrwbVQ-lcLtdyCxaY5xWuZ_w1XzhXNYZ4,737
3
+ ims/fieldupdater/testing.py,sha256=kyBncg8or4YgYMjwRhp6w3u46Jg8nnhY0Zph1oEI0MA,1561
4
+ ims/fieldupdater/browser/__init__.py,sha256=_6Yl-eMBve0mGQA-aiFg4qvQ7GUCV5eGvIcoRf4mEPw,3
5
+ ims/fieldupdater/browser/configure.zcml,sha256=LHDCGWHqOWjSnU1E6PmZhr2iOjid_Y2T2QsHq_atagU,515
6
+ ims/fieldupdater/browser/mass.pt,sha256=WBl2U8tbKE3RglKk4_fI1tXQ6w_vLwrLBZxHfjUYRCM,11051
7
+ ims/fieldupdater/browser/mass.py,sha256=W0TbjUHvq03tMwWwJOsC5ZBI2HDXVZyx5Jwn7HC2iy0,15479
8
+ ims/fieldupdater/browser/schema.pt,sha256=o3AwxD_1Gh6EcTMivOHJ5Bn1yy5lEjxI588ZkDHZWi4,2434
9
+ ims/fieldupdater/profiles/default/controlpanel.xml,sha256=TLa6jqZhxlJI2_f1KYCngZDz6Qbui4weTq2a0WsnIAk,554
10
+ ims/fieldupdater/profiles/default/metadata.xml,sha256=hU9lnPsp-DKFzuIwKVuk8tG2nw2K5dFRD8JZWU8GT1s,72
11
+ ims/fieldupdater/profiles/uninstall/controlpanel.xml,sha256=Tv4FnIVdt-azQV-_h5G7eZfZNJJ6ZArQjCt1rqVFK6Y,241
12
+ ims.fieldupdater-3.0.1.dist-info/METADATA,sha256=218IxGHN0PBAthL1dyZDR8pR-8UxX0zfRAF9HL5YJY8,844
13
+ ims.fieldupdater-3.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
+ ims.fieldupdater-3.0.1.dist-info/entry_points.txt,sha256=ue9oriqwbY5mDverBYmB-21XfmR2FdG-YWncKEEp-pE,42
15
+ ims.fieldupdater-3.0.1.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.1)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
ims/__init__.py DELETED
@@ -1 +0,0 @@
1
- __import__("pkg_resources").declare_namespace(__name__)
@@ -1 +0,0 @@
1
- #
@@ -1,55 +0,0 @@
1
- import unittest
2
-
3
- import transaction
4
- from plone.app.testing import setRoles, TEST_USER_ID, SITE_OWNER_NAME, SITE_OWNER_PASSWORD
5
- from plone.testing.zope import Browser
6
- from zope.interface.declarations import directlyProvides
7
-
8
- from .interfaces import IMassEditTest
9
- from .. import testing
10
-
11
- try:
12
- from Products.CMFCore.indexing import processQueue
13
- except ImportError:
14
- def processQueue():
15
- pass
16
-
17
-
18
- class UnitTestCase(unittest.TestCase):
19
- def setUp(self):
20
- pass
21
-
22
-
23
- class IntegrationTestCase(unittest.TestCase):
24
- layer = testing.INTEGRATION
25
-
26
- def setUp(self):
27
- super(IntegrationTestCase, self).setUp()
28
- self.portal = self.layer['portal']
29
- self.request = self.layer
30
- setRoles(self.portal, TEST_USER_ID, ['Manager'])
31
- self.view = self.portal.restrictedTraverse('@@mass-edit')
32
- self.portal.invokeFactory('Document', 'page1')
33
- self.portal.invokeFactory('Document', 'page2')
34
-
35
- self.page1 = self.portal['page1']
36
- self.page2 = self.portal['page2']
37
- directlyProvides(self.page1, IMassEditTest)
38
- directlyProvides(self.page2, IMassEditTest)
39
- self.page1.reindexObject()
40
- self.page2.reindexObject()
41
- processQueue()
42
-
43
-
44
- class FunctionalTestCase(IntegrationTestCase):
45
- layer = testing.FUNCTIONAL
46
-
47
- def setUp(self):
48
- super(FunctionalTestCase, self).setUp()
49
- self.browser = Browser(self.layer['app'])
50
- self.browser.handleErrors = False
51
- self.browser.addHeader(
52
- 'Authorization',
53
- 'Basic %s:%s' % (SITE_OWNER_NAME, SITE_OWNER_PASSWORD,)
54
- )
55
- transaction.commit()
@@ -1,38 +0,0 @@
1
- from zope.interface import Interface
2
- from zope.schema import List, TextLine, Datetime, Date, Choice
3
- from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
4
-
5
- list_field_opts = SimpleVocabulary([
6
- SimpleTerm(value='fermi', title='Fermi'),
7
- SimpleTerm(value='einstein', title='Einstein'),
8
- SimpleTerm(value='bohr', title='Bohr'),
9
- SimpleTerm(value='heisenberg', title='Heisenberg'),
10
- SimpleTerm(value='hawking', title='Hawking'),
11
- ])
12
-
13
-
14
- class IMassEditTest(Interface):
15
- list_field = List(
16
- title='List field',
17
- value_type=TextLine(),
18
- )
19
- list_choice_field = List(
20
- title='List choice field',
21
- value_type=Choice(
22
- vocabulary=list_field_opts,
23
- )
24
- )
25
- text_field = TextLine(
26
- title='Text field',
27
- required=False,
28
- )
29
- text_field_required = TextLine(
30
- title='Text field',
31
- required=True
32
- )
33
- date_time_field = Datetime(
34
- title='Datetime field',
35
- )
36
- date_field = Date(
37
- title='Date field',
38
- )
@@ -1,145 +0,0 @@
1
- from zope.schema.interfaces import RequiredMissing
2
-
3
- from . import base
4
- from .interfaces import IMassEditTest
5
-
6
-
7
- class TestMassIntegration(base.IntegrationTestCase):
8
- def test_schemas(self):
9
- self.assertIn({'id': IMassEditTest.__identifier__, 'title': 'IMassEditTest'}, self.view.get_schemas())
10
-
11
- def test_list_replace(self):
12
- self.page1.list_field = ['einstein', 'bohr']
13
- self.page2.list_field = ['fermi', 'heisenberg']
14
- match = 'einstein'
15
- field = 'list_field'
16
- replacement = 'hawking'
17
- schema = IMassEditTest.__identifier__
18
- self.view.request['schema'] = schema
19
- self.view.request['field'] = field
20
- self.view.request['match'] = match
21
- self.view.request['replacement'] = replacement
22
- self.view.replace_term(schema, field, None, match)
23
- self.assertEqual(self.page1.list_field, ['hawking', 'bohr'])
24
- self.assertEqual(self.page2.list_field, ['fermi', 'heisenberg']) # sanity - no change
25
-
26
- def test_list_delete(self):
27
- self.page1.list_field = ['einstein', 'bohr']
28
- self.page2.list_field = ['fermi', 'heisenberg']
29
- match = 'einstein'
30
- field = 'list_field'
31
- schema = IMassEditTest.__identifier__
32
- self.view.request['schema'] = schema
33
- self.view.request['field'] = field
34
- self.view.request['match'] = match
35
- self.view.delete_term(schema, field, None, match)
36
- self.assertEqual(self.page1.list_field, ['bohr'])
37
- self.assertEqual(self.page2.list_field, ['fermi', 'heisenberg']) # sanity - no change
38
-
39
- def test_list_replace_wrong_type(self):
40
- """ str converted to unicode """
41
- self.page1.list_field = ['einstein', 'bohr']
42
- self.page2.list_field = ['fermi', 'heisenberg']
43
- match = 'einstein'
44
- field = 'list_field'
45
- replacement = 'hawking'
46
- schema = IMassEditTest.__identifier__
47
- self.view.request['schema'] = schema
48
- self.view.request['field'] = field
49
- self.view.request['match'] = match
50
- self.view.request['replacement'] = replacement
51
- self.view.replace_term(schema, field, None, match)
52
- self.assertEqual(self.page1.list_field, ['hawking', 'bohr'])
53
-
54
- def test_list_choice_replace(self):
55
- """ A term outside of vocab will come in as NO_VALUE and result in no change """
56
- self.page1.list_choice_field = ['einstein', 'bohr']
57
- self.page2.list_choice_field = ['fermi', 'heisenberg']
58
- match = 'einstein'
59
- field = 'list_choice_field'
60
- replacement = 'hawking'
61
- schema = IMassEditTest.__identifier__
62
- self.view.request['schema'] = schema
63
- self.view.request['field'] = field
64
- self.view.request['match'] = match
65
- self.view.request['replacement'] = replacement
66
- self.view.replace_term(schema, field, None, match)
67
- self.assertEqual(self.page1.list_choice_field, ['hawking', 'bohr'])
68
- self.assertEqual(self.page2.list_choice_field, ['fermi', 'heisenberg']) # sanity - no change
69
-
70
- def test_list_choice_replace_invalid(self):
71
- self.page1.list_choice_field = ['einstein', 'bohr']
72
- self.page2.list_choice_field = ['fermi', 'heisenberg']
73
- match = 'einstein'
74
- field = 'list_choice_field'
75
- replacement = 'dirac'
76
- schema = IMassEditTest.__identifier__
77
- self.view.request['schema'] = schema
78
- self.view.request['field'] = field
79
- self.view.request['match'] = match
80
- self.view.request['replacement'] = replacement
81
- self.view.replace_term(schema, field, None, match)
82
- self.assertNotIn('dirac', self.page1.list_choice_field)
83
-
84
- def test_textline_replace(self):
85
- self.page1.text_field = 'einstein'
86
- match = 'einstein'
87
- field = 'text_field'
88
- replacement = 'hawking'
89
- schema = IMassEditTest.__identifier__
90
- self.view.request['schema'] = schema
91
- self.view.request['field'] = field
92
- self.view.request['match'] = match
93
- self.view.request['replacement'] = replacement
94
- self.view.replace_term(schema, field, None, match)
95
- self.assertEqual(self.page1.text_field, 'hawking')
96
-
97
- def test_textline_delete(self):
98
- self.page1.text_field = 'einstein'
99
- match = 'einstein'
100
- field = 'text_field'
101
- schema = IMassEditTest.__identifier__
102
- self.view.request['schema'] = schema
103
- self.view.request['field'] = field
104
- self.view.request['match'] = match
105
- self.view.delete_term(schema, field, None, match)
106
- self.assertEqual(self.page1.text_field, None)
107
-
108
- def test_textline_delete_required(self):
109
- self.page1.text_field_required = 'einstein'
110
- match = 'einstein'
111
- field = 'text_field_required'
112
- schema = IMassEditTest.__identifier__
113
- self.view.request['schema'] = schema
114
- self.view.request['field'] = field
115
- self.view.request['match'] = match
116
- self.assertRaises(RequiredMissing, self.view.delete_term, schema, field, None, match)
117
-
118
- def test_unicode_conversion(self):
119
- """ The widget should really handle this, but we do have this as a failsafe """
120
- self.page1.text_field = 'einstein'
121
- match = 'einstein'
122
- field = 'text_field'
123
- replacement = 'hawking'
124
- schema = IMassEditTest.__identifier__
125
- self.view.request['schema'] = schema
126
- self.view.request['field'] = field
127
- self.view.request['match'] = match
128
- self.view.request['replacement'] = replacement
129
- self.view.replace_term(schema, field, None, match)
130
- self.assertEqual(self.page1.text_field, 'hawking')
131
- self.assertIsInstance(self.page1.text_field, str)
132
-
133
-
134
- class TestMassFunctional(base.FunctionalTestCase):
135
- def test_mass_edit(self):
136
- self.page1.list_choice_field = 'einstein'
137
- self.browser.open(self.portal.absolute_url() + '/@@mass-edit?schema=' +
138
- IMassEditTest.__identifier__ + '&field=list_choice_field&match=')
139
- # ctrl = self.browser.getControl
140
- # ctrl(name='form.buttons.search').click()
141
-
142
-
143
- def test_suite():
144
- import unittest
145
- return unittest.defaultTestLoader.loadTestsFromName(__name__)
@@ -1,23 +0,0 @@
1
- from Products.CMFPlone.utils import get_installer
2
- from plone import api
3
- from plone.app.testing import TEST_USER_ID
4
- from plone.app.testing import setRoles
5
-
6
- from . import base
7
- from .. import testing
8
-
9
-
10
- class TestUninstall(base.IntegrationTestCase):
11
- layer = testing.INTEGRATION
12
-
13
- def setUp(self):
14
- self.portal = self.layer['portal']
15
- roles_before = api.user.get_roles(TEST_USER_ID)
16
- setRoles(self.portal, TEST_USER_ID, ['Manager'])
17
- self.installer = get_installer(self.portal)
18
- self.installer.uninstall_product('ims.fieldupdater')
19
- setRoles(self.portal, TEST_USER_ID, roles_before)
20
-
21
- def test_product_uninstalled(self):
22
- """Test if ims.contacts is cleanly uninstalled."""
23
- self.assertFalse(self.installer.is_product_installed('ims.fieldupdater'))
@@ -1,22 +0,0 @@
1
- ims/__init__.py,sha256=Qb3VhaU4VgyrGoiGEEGc6oAe9RfM2n1kunHKQQJjU4g,57
2
- ims/fieldupdater/__init__.py,sha256=QALONVQPtJAt8ei-aEimCTaMO1oc0MdAJTUSo4DwcrY,87
3
- ims/fieldupdater/configure.zcml,sha256=eAIJlfutXffrwbVQ-lcLtdyCxaY5xWuZ_w1XzhXNYZ4,737
4
- ims/fieldupdater/testing.py,sha256=GWm5J-94p_3HyhiVfBCw7UgNTwi4HggBmmU5aTJvCEo,1273
5
- ims/fieldupdater/browser/__init__.py,sha256=_6Yl-eMBve0mGQA-aiFg4qvQ7GUCV5eGvIcoRf4mEPw,3
6
- ims/fieldupdater/browser/configure.zcml,sha256=LHDCGWHqOWjSnU1E6PmZhr2iOjid_Y2T2QsHq_atagU,515
7
- ims/fieldupdater/browser/mass.pt,sha256=6LxKYP5-021AWzYKyhwg4YjMeWZtu_dm4eAafENOxPE,11050
8
- ims/fieldupdater/browser/mass.py,sha256=yasL1Vm89-esFRzHTx4bqG_Lu7JiKl8H7Jj8TDtnfKY,15841
9
- ims/fieldupdater/browser/schema.pt,sha256=o3AwxD_1Gh6EcTMivOHJ5Bn1yy5lEjxI588ZkDHZWi4,2434
10
- ims/fieldupdater/profiles/default/controlpanel.xml,sha256=TLa6jqZhxlJI2_f1KYCngZDz6Qbui4weTq2a0WsnIAk,554
11
- ims/fieldupdater/profiles/default/metadata.xml,sha256=hU9lnPsp-DKFzuIwKVuk8tG2nw2K5dFRD8JZWU8GT1s,72
12
- ims/fieldupdater/profiles/uninstall/controlpanel.xml,sha256=Tv4FnIVdt-azQV-_h5G7eZfZNJJ6ZArQjCt1rqVFK6Y,241
13
- ims/fieldupdater/tests/__init__.py,sha256=_6Yl-eMBve0mGQA-aiFg4qvQ7GUCV5eGvIcoRf4mEPw,3
14
- ims/fieldupdater/tests/base.py,sha256=1N98TAz1NhCvw5VPxvadug39PDSq_E1lPJaAC5R6ZmI,1686
15
- ims/fieldupdater/tests/interfaces.py,sha256=dTXgau7piShgUjf-cPUqGSoqcs2BkpLh9cFupL2IkGg,1065
16
- ims/fieldupdater/tests/test_mass.py,sha256=9ccXajz58u8jDqRrs6yk86Uiy9mS3p8tTvtthetd9mk,6348
17
- ims/fieldupdater/tests/test_uninstall.py,sha256=Z36FqF1D4fIHahLixaAxAzG3MWXKzu0ezt4zWvm-n9I,832
18
- ims.fieldupdater-3.0.0rc2.dist-info/METADATA,sha256=H2qNo-6CHlp7s97TWjmPJRVsKKUb8b54ZhgHZMYPHc8,730
19
- ims.fieldupdater-3.0.0rc2.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
20
- ims.fieldupdater-3.0.0rc2.dist-info/entry_points.txt,sha256=ue9oriqwbY5mDverBYmB-21XfmR2FdG-YWncKEEp-pE,42
21
- ims.fieldupdater-3.0.0rc2.dist-info/top_level.txt,sha256=TB_6JwFRlehNqwLyPOVvJ5-lB8EgK51Ahw9Nq5hfoGY,4
22
- ims.fieldupdater-3.0.0rc2.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- ims