Skip to content

Commit

Permalink
Added support for multi-value fields in formsets (#18)
Browse files Browse the repository at this point in the history
* Added support for multi-value fields in formsets

* Update README.md
  • Loading branch information
raratiru authored Oct 28, 2019
1 parent da6f836 commit ccd1725
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 64 deletions.
11 changes: 1 addition & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
dist: xenial
language: python
python:
- '3.5'
- '3.6'
- '3.7'
- '3.8'
Expand All @@ -13,13 +14,3 @@ script:
- pytest
after_success:
- coveralls
deploy:
provider: pypi
user: "raratiru"
password:
secure: "AGYeNOF6X4SrR5xAok8n76hbiVkekugS6wF6GtRq+0g7Dnob46SL7Aqsf4p2KGDTPPWG4MjiW/GF4mIyQ7IHDVhwGtlIJh2WKX0ggiQQ4oGMrDzMYj/ecv3LD3gJbfW3ozZ/bTDokoY8MTNAzVxN9X3/1HNAD0GYzjrqdtSwkGpD75lOvVc8uFgym7UfhRniid/ThajlWt7xjORY3VYrlpBsTDSF00/nf6RlvVakqofbiTojgmiG5NbK+LhYTgfxmcZLYJE1anVrdTiAe2wNNEPC3kSVEAoGPsr2LjRTEG8RDA7Ha3AyAeVOXtOWwgW1EPxpV7z5DSuF64daiGzodZbjfIO+rhYC3RhKs5pdicwliEozUBu7+SJx584ldkXkJVlscIlJ1tXT1I7VOURy9FaIhItf1e8QDNayQ+CWJNvzTXKZq6gZ1kjr8hSdTkSRq3JBjZT3o2/6hmUMjYuwVJhfv//dmoIoOfvzL/1xAiPgRzPQuKEsR0VMCeB3Ec3z0L3BngecqqeI4py9r4leQe3S0OTP6Lv9/iM/4Qoqo0v3qXDYQOU2riMaakm9G3K+92TLK41/H+XHBi+840FgZJBTjGR2rq5+4lfO9nQGMh8wCH9V/yG+/yaKNUdkb/DZ1MPihhVQ6ZU41XNZv4iREaJGctMQJub3/cD2vmgs5yQ="
skip_cleanup: true
skip_existing: true
distributions: "sdist bdist_wheel"
on:
tags: true
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[![Coverage Status](https://coveralls.io/repos/github/raratiru/thepysec/badge.svg?branch=master&service=github)](https://coveralls.io/github/raratiru/thepysec?branch=master)


A collection of tools that support a busy project based on Python >= 3.6.
A collection of tools that support a busy project based on Python >= 3.5.

John
----
Expand All @@ -15,10 +15,16 @@ Lia
Lia is here to take a detailed look at your strings.

* `pop_wsp`: Remove extra whitespace.
* `pop_i18n_wsp`: Remove extra whitespace from each field of django-translated-fields.
* `pre_slug`: Prepare a string to become a wise slug. 'r33a!bc' -> 'r 33 abc'.
* `fast_pre_slug`: Prepare a string to become a fast slug. 'r33a!bc' -> 'r 3 3 a bc'.

Matina
------

Matina performs operations on django model instances

* `pop_i18n_wsp`: Apply `pop_wsp` for a list of fields in a given model instance.

Myriam
------

Expand Down
6 changes: 4 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#
# Creation Date : Fri 28 Dec 2018 03:17:42 PM EET
#
# Last Modified : Sun 27 Oct 2019 01:55:23 PM EET (13:55)
# Last Modified : Mon 28 Oct 2019 06:49:18 PM EET (18:49)
#
# ==============================================================================

Expand All @@ -26,9 +26,10 @@ def read(fname):
setup(
name="thepysec",
version=version,
python_requires=">=3.6",
python_requires=">=3.5",
description="Python secretaries you call at will, for instant py-relief.",
long_description=read("README.md"),
long_description_content_type="text/markdown",
url="https://github.com/raratiru/thepysec",
author="Raratiru",
author_email="info@musicaloffering.gr",
Expand All @@ -41,6 +42,7 @@ def read(fname):
classifiers=[
"Development Status :: 1 - Planning",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
Expand Down
4 changes: 2 additions & 2 deletions thepysec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
#
# Creation Date : Fri 28 Dec 2018 03:36:03 PM EET
#
# Last Modified : Mon 28 Oct 2019 12:18:14 AM EET (00:18)
# Last Modified : Mon 28 Oct 2019 06:44:46 PM EET (18:44)
#
# ==============================================================================

from thepysec.john.version import get_version


VERSION = (2, 0, 0, "final", 0)
VERSION = (2, 0, 1, "final", 0)

__version__ = get_version(VERSION)
11 changes: 1 addition & 10 deletions thepysec/lia.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#
# Creation Date : Sat 16 Mar 2019 03:12:18 PM EET (15:12)
#
# Last Modified : Mon 28 Oct 2019 12:12:32 AM EET (00:12)
# Last Modified : Mon 28 Oct 2019 06:55:03 PM EET (18:55)
#
# ==============================================================================

Expand All @@ -20,15 +20,6 @@ def pop_wsp(lia_string):
return " ".join(lia_string.split())


def pop_i18n_wsp(instance, translated_fields):
"""
In a django model with translated attributes, it strips white space from all
fields of a translated attribute (attribute_en, attribute_fr, attribute_el).
"""
for field in translated_fields:
setattr(instance, field, pop_wsp(getattr(instance, field)))


def fast_pre_slug(lia_string):
"""
* Decode string to ASCII
Expand Down
24 changes: 24 additions & 0 deletions thepysec/matina.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


# ==============================================================================
#
# File Name : thepysec/matina.py
#
# Creation Date : Mon 28 Oct 2019 06:54:11 PM EET (18:54)
#
# Last Modified : Mon 28 Oct 2019 06:54:44 PM EET (18:54)
#
# ==============================================================================

from thepysec.lia import pop_wsp


def pop_i18n_wsp(instance, translated_fields):
"""
In a django model with translated attributes, it strips white space from all
fields of a translated attribute (attribute_en, attribute_fr, attribute_el).
"""
for field in translated_fields:
setattr(instance, field, pop_wsp(getattr(instance, field)))
26 changes: 1 addition & 25 deletions thepysec/tests/test_lia.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#
# Creation Date : Sat 16 Mar 2019 03:19:11 PM EET (15:19)
#
# Last Modified : Mon 28 Oct 2019 12:14:53 AM EET (00:14)
# Last Modified : Mon 28 Oct 2019 06:56:13 PM EET (18:56)
#
# ==============================================================================

Expand All @@ -20,30 +20,6 @@ def test_pop_whitespace():
assert obj == "dadd d r"


def test_django_pop_whitespace():
class A:
att1_en = "f r a"
att1_fr = "h b k"
att1_el = "h f b y k"
att2_en = "r r a"
att2_fr = "h f k"
att2_el = "h f b 1 k"

obj = A()
trans_fields = ("att1_en", "att1_el", "att1_fr", "att2_en", "att2_el", "att2_fr")
lia.pop_i18n_wsp(obj, trans_fields)
assert all(
(
obj.att1_en == "f r a",
obj.att1_fr == "h b k",
obj.att1_el == "h f b y k",
obj.att2_en == "r r a",
obj.att2_fr == "h f k",
obj.att2_el == "h f b 1 k",
)
)


def test_pre_slug():
raw_slug = "tr4e, 5435 (bili#go)"
assert lia.pre_slug(raw_slug) == "tr 4 e 5435 bili go"
Expand Down
39 changes: 39 additions & 0 deletions thepysec/tests/test_matina.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


# ==============================================================================
#
# File Name : thepysec/tests/test_matina.py
#
# Creation Date : Mon 28 Oct 2019 06:55:14 PM EET (18:55)
#
# Last Modified : Mon 28 Oct 2019 06:56:05 PM EET (18:56)
#
# ==============================================================================

from thepysec import matina


def test_django_pop_whitespace():
class A:
att1_en = "f r a"
att1_fr = "h b k"
att1_el = "h f b y k"
att2_en = "r r a"
att2_fr = "h f k"
att2_el = "h f b 1 k"

obj = A()
trans_fields = ("att1_en", "att1_el", "att1_fr", "att2_en", "att2_el", "att2_fr")
matina.pop_i18n_wsp(obj, trans_fields)
assert all(
(
obj.att1_en == "f r a",
obj.att1_fr == "h b k",
obj.att1_el == "h f b y k",
obj.att2_en == "r r a",
obj.att2_fr == "h f k",
obj.att2_el == "h f b 1 k",
)
)
19 changes: 11 additions & 8 deletions thepysec/tests/test_thanos.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#
# Creation Date : Sun 27 Oct 2019 02:17:45 PM EET (14:17)
#
# Last Modified : Sun 27 Oct 2019 02:47:43 PM EET (14:47)
# Last Modified : Mon 28 Oct 2019 07:00:19 PM EET (19:00)
#
# ==============================================================================

Expand All @@ -31,25 +31,25 @@ def __init__(self, data=None, initial=None, instance=None):
{
"field1": ["value11", "value12", "value13"],
"field2": "A value",
"field3": ["my_val1"],
"field3": {0: "my_val11", 1: "my_val12"},
},
{
"field1": ["value21", "value22", "value23"],
"field2": "Another value",
"field3": ["my_val2"],
"field3": {0: "my_val21", 1: "my_val22"},
},
{
"field1": ["value31", "value32", "value33"],
"field2": "A third value",
"field3": ["my_val3"],
"field3": {0: "my_val31", 1: "my_val32"},
},
]

initial = [
{
"field1": ["value11", "value12", "value13"],
"field2": "A value",
"field3": ["my_val1"],
"field3": {0: "my_val11", 1: "my_val12"},
}
]

Expand All @@ -59,13 +59,16 @@ def test_alive_formset():
assert formset.data == {
"myformset-0-field1": ["value11", "value12", "value13"],
"myformset-0-field2": "A value",
"myformset-0-field3": ["my_val1"],
"myformset-0-field3_0": "my_val11",
"myformset-0-field3_1": "my_val12",
"myformset-1-field1": ["value21", "value22", "value23"],
"myformset-1-field2": "Another value",
"myformset-1-field3": ["my_val2"],
"myformset-1-field3_0": "my_val21",
"myformset-1-field3_1": "my_val22",
"myformset-2-field1": ["value31", "value32", "value33"],
"myformset-2-field2": "A third value",
"myformset-2-field3": ["my_val3"],
"myformset-2-field3_0": "my_val31",
"myformset-2-field3_1": "my_val32",
"myformset-TOTAL_FORMS": 3,
"myformset-INITIAL_FORMS": 1,
}
Expand Down
15 changes: 10 additions & 5 deletions thepysec/thanos.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#
# Creation Date : Sun 27 Oct 2019 01:44:22 PM EET (13:44)
#
# Last Modified : Sun 27 Oct 2019 02:48:53 PM EET (14:48)
# Last Modified : Mon 28 Oct 2019 06:37:22 PM EET (18:37)
#
# ==============================================================================

Expand All @@ -20,27 +20,32 @@ def get_formset_alive(formset_class, data, instance=None, initial=None):
# Form 1
{
'foo': ['bar1', 'bar2'],
'multi_val': {0: 'val1', 1: 'val2'},
'baz': 'qux1',
},
# Form 2
{
'foo': ['cam1'],
'multi_val': {0: 'zoo1', 1: 'zoo2'},
'baz': 'eggs',
},
])
============================================================================
Many to many field is represented with a list:
'{}-{}-{}'.format(prefix, form_number, field_name) = ['val_1', 'val_2']
instead of the original:
'{}-{}-{}_{}'.format(prefix, form_number, field_name, value_number=1) = 'val_1'
'{}-{}-{}_{}'.format(prefix, form_number, field_name, value_number=2) = 'val_2'
Multivalue field is represented with a dict:
'{}-{}-{}_{}'.format(prefix, form_number, field_name, value_number=key) = value
============================================================================
"""
prefix = formset_class().prefix
formset_data = {}
for i, form_data in enumerate(data):
for name, value in form_data.items():
formset_data["{}-{}-{}".format(prefix, i, name)] = value
if isinstance(value, dict):
for k, v in value.items():
formset_data["{}-{}-{}_{}".format(prefix, i, name, k)] = v
else:
formset_data["{}-{}-{}".format(prefix, i, name)] = value
formset_data["{}-TOTAL_FORMS".format(prefix)] = len(data)
formset_data["{}-INITIAL_FORMS".format(prefix)] = len(initial) if initial else 0
if instance:
Expand Down

0 comments on commit ccd1725

Please sign in to comment.