From b72d15bed72e8418ce7c90af5b977d84de3dd8cf Mon Sep 17 00:00:00 2001 From: Evan Dempsey Date: Fri, 27 Jun 2014 21:58:07 +0100 Subject: [PATCH 1/8] add_text() on paragraph --- .gitignore | 2 ++ docx/text.py | 17 +++++++++++++ features/par-add-text.feature | 25 +++++++++++++++++++ features/steps/paragraph.py | 46 +++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 features/par-add-text.feature diff --git a/.gitignore b/.gitignore index de25a6f76..e94adf371 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ _scratch/ Session.vim /.tox/ +.idea + diff --git a/docx/text.py b/docx/text.py index 69adf1c21..b74430c40 100644 --- a/docx/text.py +++ b/docx/text.py @@ -75,6 +75,23 @@ def add_run(self, text=None, style=None): run.style = style return run + def add_text(self, text, style=None): + """ + Provides an easy way to add text to a paragraph, preserving the style + of the previously inserted text, unless a different style is specified. + If the paragraph has no runs, a new run is created with the given text + and style. Otherwise, if the given style is the same as the last run, + the text is appended to it. If the styles differ, a new run is created. + """ + if len(self._p.r_lst) == 0: + self.add_run(text, style) + else: + run = self.runs[-1] + if run.style == style: + run.add_text(text) + else: + self.add_run(text, style) + @property def alignment(self): """ diff --git a/features/par-add-text.feature b/features/par-add-text.feature new file mode 100644 index 000000000..61dde5b61 --- /dev/null +++ b/features/par-add-text.feature @@ -0,0 +1,25 @@ +Feature: Add text to a paragraph, preserving the style of the last text + In order to easily add new text to the end of a paragraph + As a python-docx programmer + I want an easy way to add text to the last run + + Scenario: Add text to an empty paragraph + Given a paragraph + Then the paragraph has no content + When I add text to the paragraph + Then the paragraph has one run + And the paragraph has the text I set + + Scenario: Add text of the same style to a non-empty paragraph + Given a paragraph with some text + When I add text to the paragraph + Then the paragraph has one run + And the paragraph ends with the text I added + And the initial text is still there + + Scenario: Add text of a different style to a non-empty paragraph + Given a paragraph with some text + When I add text of a different style to the paragraph + Then the paragraph has two runs + And the second run contains the text I added + And the second run has the style I specified diff --git a/features/steps/paragraph.py b/features/steps/paragraph.py index 6f106b862..83ed31f71 100644 --- a/features/steps/paragraph.py +++ b/features/steps/paragraph.py @@ -57,6 +57,13 @@ def given_a_paragraph_with_content_and_formatting(context): context.paragraph = Paragraph(p) +@given('a paragraph with some text') +def given_a_paragraph_with_some_text(context): + context.document = Document() + context.paragraph = context.document.add_paragraph() + context.paragraph.text = 'Lorem ipsum ' + + # when ==================================================== @when('I add a run to the paragraph') @@ -85,6 +92,15 @@ def when_I_set_the_paragraph_style(context): def when_I_set_the_paragraph_text(context): context.paragraph.text = 'bar\tfoo\r' +@when('I add text to the paragraph') +def when_I_add_text_to_the_paragraph(context): + context.paragraph.add_text('bar\tfoo\r') + + +@when('I add text of a different style to the paragraph') +def when_I_add_different_style_text_to_paragraph(context): + context.paragraph.add_text('dolor sit amet', 'Heading1') + # then ===================================================== @@ -140,6 +156,36 @@ def then_the_style_of_the_second_paragraph_matches_the_style_I_set(context): assert second_paragraph.style == 'Heading1' +@then('the paragraph has one run') +def then_the_paragraph_has_one_run(context): + assert len(context.paragraph.runs) == 1 + + +@then('the paragraph has two runs') +def then_the_paragraph_has_two_runs(context): + assert len(context.paragraph.runs) == 2 + + +@then('the paragraph ends with the text I added') +def then_the_paragraph_ends_with_the_text_I_added(context): + assert context.paragraph.text.endswith('bar\tfoo\r') + + +@then('the initial text is still there') +def then_the_initial_text_is_still_there(context): + assert context.paragraph.text.startswith('Lorem ipsum ') + + +@then('the second run contains the text I added') +def then_second_run_contains_text_I_added(context): + context.paragraph.runs[1].text = 'dolor sit amet' + + +@then('the second run has the style I specified') +def then_second_run_has_specified_style(context): + context.paragraph.runs[1].style = 'Heading1' + + @then('the text of the second paragraph matches the text I set') def then_the_text_of_the_second_paragraph_matches_the_text_I_set(context): second_paragraph = context.document.paragraphs[1] From f483a90236868dcd191fa8760bee7fc1f90fe316 Mon Sep 17 00:00:00 2001 From: Evan Dempsey Date: Fri, 27 Jun 2014 22:06:38 +0100 Subject: [PATCH 2/8] more pythonic --- docx/text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docx/text.py b/docx/text.py index b74430c40..6b5ef1d06 100644 --- a/docx/text.py +++ b/docx/text.py @@ -83,7 +83,7 @@ def add_text(self, text, style=None): and style. Otherwise, if the given style is the same as the last run, the text is appended to it. If the styles differ, a new run is created. """ - if len(self._p.r_lst) == 0: + if not self._p.r_lst: self.add_run(text, style) else: run = self.runs[-1] From 20534d1e4787af71ce28e28e576ed95c0a742f49 Mon Sep 17 00:00:00 2001 From: Evan Dempsey Date: Fri, 27 Jun 2014 22:11:17 +0100 Subject: [PATCH 3/8] Clearer docstring --- docx/text.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docx/text.py b/docx/text.py index 6b5ef1d06..195d96dae 100644 --- a/docx/text.py +++ b/docx/text.py @@ -81,7 +81,8 @@ def add_text(self, text, style=None): of the previously inserted text, unless a different style is specified. If the paragraph has no runs, a new run is created with the given text and style. Otherwise, if the given style is the same as the last run, - the text is appended to it. If the styles differ, a new run is created. + the text is appended to it. If the style specified for the new text is + different to the style of the last run, a new run is created. """ if not self._p.r_lst: self.add_run(text, style) From 9f2fc4a490c7965ba4f6df59b44970d7b6ed77cc Mon Sep 17 00:00:00 2001 From: Evan Dempsey Date: Fri, 27 Jun 2014 22:22:43 +0100 Subject: [PATCH 4/8] Added blank line to make flake8 be quiet. --- features/steps/paragraph.py | 1 + 1 file changed, 1 insertion(+) diff --git a/features/steps/paragraph.py b/features/steps/paragraph.py index 83ed31f71..f243eb358 100644 --- a/features/steps/paragraph.py +++ b/features/steps/paragraph.py @@ -92,6 +92,7 @@ def when_I_set_the_paragraph_style(context): def when_I_set_the_paragraph_text(context): context.paragraph.text = 'bar\tfoo\r' + @when('I add text to the paragraph') def when_I_add_text_to_the_paragraph(context): context.paragraph.add_text('bar\tfoo\r') From 3dcc5eb418d1daf0dbef5bc9521bebf1cb8100f3 Mon Sep 17 00:00:00 2001 From: Evan Dempsey Date: Fri, 27 Jun 2014 23:23:25 +0100 Subject: [PATCH 5/8] Simpler version. --- docx/text.py | 18 ++++++---------- features/par-add-text.feature | 17 +++++---------- features/steps/paragraph.py | 39 ++++++++++++++--------------------- 3 files changed, 26 insertions(+), 48 deletions(-) diff --git a/docx/text.py b/docx/text.py index 195d96dae..2ab521c71 100644 --- a/docx/text.py +++ b/docx/text.py @@ -75,23 +75,17 @@ def add_run(self, text=None, style=None): run.style = style return run - def add_text(self, text, style=None): + def add_text(self, text): """ Provides an easy way to add text to a paragraph, preserving the style - of the previously inserted text, unless a different style is specified. - If the paragraph has no runs, a new run is created with the given text - and style. Otherwise, if the given style is the same as the last run, - the text is appended to it. If the style specified for the new text is - different to the style of the last run, a new run is created. + of the previously inserted text, If the paragraph has no runs, a new + run is created with the given text. Otherwise, the text is appended + to the last run and takes on its style. """ if not self._p.r_lst: - self.add_run(text, style) + self.add_run(text, style=None) else: - run = self.runs[-1] - if run.style == style: - run.add_text(text) - else: - self.add_run(text, style) + self.runs[-1].add_text(text) @property def alignment(self): diff --git a/features/par-add-text.feature b/features/par-add-text.feature index 61dde5b61..cac90a89b 100644 --- a/features/par-add-text.feature +++ b/features/par-add-text.feature @@ -7,19 +7,12 @@ Feature: Add text to a paragraph, preserving the style of the last text Given a paragraph Then the paragraph has no content When I add text to the paragraph - Then the paragraph has one run - And the paragraph has the text I set + Then the paragraph has the text I added - Scenario: Add text of the same style to a non-empty paragraph - Given a paragraph with some text + Scenario: Add text to a non-empty paragraph with a style on the last run + Given a paragraph with some text and a style on the last run When I add text to the paragraph - Then the paragraph has one run + Then the paragraph has the same amount of runs And the paragraph ends with the text I added And the initial text is still there - - Scenario: Add text of a different style to a non-empty paragraph - Given a paragraph with some text - When I add text of a different style to the paragraph - Then the paragraph has two runs - And the second run contains the text I added - And the second run has the style I specified + And the last run still has the same style diff --git a/features/steps/paragraph.py b/features/steps/paragraph.py index f243eb358..3b331a915 100644 --- a/features/steps/paragraph.py +++ b/features/steps/paragraph.py @@ -57,11 +57,12 @@ def given_a_paragraph_with_content_and_formatting(context): context.paragraph = Paragraph(p) -@given('a paragraph with some text') -def given_a_paragraph_with_some_text(context): +@given('a paragraph with some text and a style on the last run') +def given_a_paragraph_with_some_text_and_style_on_last_run(context): context.document = Document() context.paragraph = context.document.add_paragraph() context.paragraph.text = 'Lorem ipsum ' + context.paragraph.runs[-1].style = 'Heading1' # when ==================================================== @@ -95,12 +96,7 @@ def when_I_set_the_paragraph_text(context): @when('I add text to the paragraph') def when_I_add_text_to_the_paragraph(context): - context.paragraph.add_text('bar\tfoo\r') - - -@when('I add text of a different style to the paragraph') -def when_I_add_different_style_text_to_paragraph(context): - context.paragraph.add_text('dolor sit amet', 'Heading1') + context.paragraph.add_text('dolor sit amet') # then ===================================================== @@ -157,19 +153,19 @@ def then_the_style_of_the_second_paragraph_matches_the_style_I_set(context): assert second_paragraph.style == 'Heading1' -@then('the paragraph has one run') -def then_the_paragraph_has_one_run(context): +@then('the paragraph has the same amount of runs') +def then_the_paragraph_has_same_runs(context): assert len(context.paragraph.runs) == 1 -@then('the paragraph has two runs') -def then_the_paragraph_has_two_runs(context): - assert len(context.paragraph.runs) == 2 - - @then('the paragraph ends with the text I added') def then_the_paragraph_ends_with_the_text_I_added(context): - assert context.paragraph.text.endswith('bar\tfoo\r') + assert context.paragraph.text.endswith('dolor sit amet') + + +@then('the paragraph has the text I added') +def then_the_paragraph_has_the_text_I_added(context): + assert context.paragraph.text == 'dolor sit amet' @then('the initial text is still there') @@ -177,14 +173,9 @@ def then_the_initial_text_is_still_there(context): assert context.paragraph.text.startswith('Lorem ipsum ') -@then('the second run contains the text I added') -def then_second_run_contains_text_I_added(context): - context.paragraph.runs[1].text = 'dolor sit amet' - - -@then('the second run has the style I specified') -def then_second_run_has_specified_style(context): - context.paragraph.runs[1].style = 'Heading1' +@then('the last run still has the same style') +def then_last_run_still_has_same_style(context): + assert context.paragraph.runs[-1].style == 'Heading1' @then('the text of the second paragraph matches the text I set') From 387d67bbf6f686d8c199747846eab29bf4ae73b7 Mon Sep 17 00:00:00 2001 From: Evan Dempsey Date: Sat, 28 Jun 2014 01:10:40 +0100 Subject: [PATCH 6/8] Removed silly None argument. --- docx/text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docx/text.py b/docx/text.py index 2ab521c71..fcb052d82 100644 --- a/docx/text.py +++ b/docx/text.py @@ -83,7 +83,7 @@ def add_text(self, text): to the last run and takes on its style. """ if not self._p.r_lst: - self.add_run(text, style=None) + self.add_run(text) else: self.runs[-1].add_text(text) From e0c72f2236d62c09aefc75be9148d645f8078ede Mon Sep 17 00:00:00 2001 From: Evan Dempsey Date: Sat, 28 Jun 2014 15:41:45 +0100 Subject: [PATCH 7/8] Right way round. --- docx/text.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docx/text.py b/docx/text.py index fcb052d82..b6ab9035c 100644 --- a/docx/text.py +++ b/docx/text.py @@ -82,10 +82,10 @@ def add_text(self, text): run is created with the given text. Otherwise, the text is appended to the last run and takes on its style. """ - if not self._p.r_lst: - self.add_run(text) - else: + if self._p.r_lst: self.runs[-1].add_text(text) + else: + self.add_run(text) @property def alignment(self): From 032b94b9ef0534c4ad535575350158ab0a0f97a8 Mon Sep 17 00:00:00 2001 From: Evan Dempsey Date: Tue, 8 Jul 2014 08:09:57 +0100 Subject: [PATCH 8/8] Removed .idea --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index e94adf371..de25a6f76 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,3 @@ _scratch/ Session.vim /.tox/ -.idea -