PrEditor 1.1.0__py3-none-any.whl → 1.3.0__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.

Potentially problematic release.


This version of PrEditor might be problematic. Click here for more details.

Files changed (57) hide show
  1. preditor/__init__.py +4 -1
  2. preditor/about_module.py +6 -2
  3. preditor/dccs/.hab.json +10 -0
  4. preditor/dccs/maya/PrEditor_maya.mod +0 -1
  5. preditor/dccs/maya/README.md +22 -0
  6. preditor/dccs/maya/plug-ins/PrEditor_maya.py +32 -1
  7. preditor/dccs/studiomax/PackageContents.xml +32 -0
  8. preditor/dccs/studiomax/PrEditor-PrEditor_Show.mcr +8 -0
  9. preditor/dccs/studiomax/README.md +17 -0
  10. preditor/dccs/studiomax/preditor.ms +16 -0
  11. preditor/dccs/studiomax/preditor_menu.mnx +7 -0
  12. preditor/debug.py +7 -3
  13. preditor/excepthooks.py +1 -1
  14. preditor/gui/app.py +2 -2
  15. preditor/gui/codehighlighter.py +10 -24
  16. preditor/gui/completer.py +17 -6
  17. preditor/gui/console.py +94 -47
  18. preditor/gui/dialog.py +10 -7
  19. preditor/gui/drag_tab_bar.py +7 -7
  20. preditor/gui/errordialog.py +2 -2
  21. preditor/gui/find_files.py +7 -5
  22. preditor/gui/fuzzy_search/fuzzy_search.py +8 -4
  23. preditor/gui/group_tab_widget/__init__.py +32 -4
  24. preditor/gui/group_tab_widget/grouped_tab_models.py +4 -4
  25. preditor/gui/group_tab_widget/grouped_tab_widget.py +6 -4
  26. preditor/gui/level_buttons.py +16 -1
  27. preditor/gui/loggerwindow.py +48 -27
  28. preditor/gui/set_text_editor_path_dialog.py +3 -1
  29. preditor/gui/ui/loggerwindow.ui +11 -1
  30. preditor/gui/window.py +4 -4
  31. preditor/gui/workbox_mixin.py +43 -14
  32. preditor/gui/workbox_text_edit.py +7 -5
  33. preditor/gui/workboxwidget.py +25 -16
  34. preditor/logging_config.py +5 -2
  35. preditor/scintilla/__init__.py +19 -1
  36. preditor/scintilla/delayables/smart_highlight.py +7 -4
  37. preditor/scintilla/delayables/spell_check.py +5 -4
  38. preditor/scintilla/documenteditor.py +228 -135
  39. preditor/scintilla/finddialog.py +3 -3
  40. preditor/scintilla/lang/language.py +1 -1
  41. preditor/scintilla/lexers/cpplexer.py +3 -2
  42. preditor/scintilla/lexers/javascriptlexer.py +6 -4
  43. preditor/scintilla/lexers/maxscriptlexer.py +8 -7
  44. preditor/scintilla/lexers/mellexer.py +3 -2
  45. preditor/scintilla/lexers/mulexer.py +3 -2
  46. preditor/scintilla/lexers/pythonlexer.py +7 -6
  47. preditor/utils/cute.py +9 -8
  48. preditor/version.py +16 -3
  49. {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/METADATA +69 -32
  50. {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/RECORD +56 -47
  51. preditor-1.3.0.dist-info/top_level.txt +3 -0
  52. tests/find_files/test_find_files.py +74 -0
  53. tests/ide/test_delayable_engine.py +171 -0
  54. preditor-1.1.0.dist-info/top_level.txt +0 -1
  55. {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/WHEEL +0 -0
  56. {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/entry_points.txt +0 -0
  57. {preditor-1.1.0.dist-info → preditor-1.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,74 @@
1
+ import os
2
+
3
+ import pytest
4
+
5
+ from preditor.utils.text_search import RegexTextSearch, SimpleTextSearch
6
+
7
+
8
+ def text_for_test(filename):
9
+ dirname = os.path.dirname(__file__)
10
+ filename = os.path.join(dirname, filename)
11
+ with open(filename) as fle:
12
+ return fle.read()
13
+
14
+
15
+ @pytest.mark.parametrize(
16
+ "check_type,search_text,is_cs,context,is_re",
17
+ (
18
+ # Simple text search testing context and case
19
+ ("simple", "search term", False, 0, False),
20
+ ("simple", "search term", False, 1, False),
21
+ ("simple", "search term", False, 2, False),
22
+ ("simple", "search term", False, 3, False),
23
+ ("simple", "search term", True, 2, False),
24
+ # Regex search testing context and case
25
+ ("re_simple", "search term", False, 0, True),
26
+ ("re_simple", "search term", False, 2, True),
27
+ ("re_simple", "search term", False, 3, True),
28
+ ("re_simple", "search term", True, 2, True),
29
+ # Complex regex with a greedy search term
30
+ ("re_greedy", "search.+term", False, 0, True),
31
+ ("re_greedy", "search.+term", False, 2, True),
32
+ ("re_greedy", "search.+term", True, 2, True),
33
+ ("re_greedy_upper", "Search.+term", True, 2, True),
34
+ ),
35
+ )
36
+ def test_find_files(capsys, check_type, search_text, is_cs, context, is_re):
37
+ workbox_id = "1,2"
38
+ path = 'First Group/First Tab'
39
+ text = text_for_test("tab_text.txt")
40
+
41
+ if is_re:
42
+ TextSearch = RegexTextSearch
43
+ else:
44
+ TextSearch = SimpleTextSearch
45
+
46
+ search = TextSearch(search_text, case_sensitive=is_cs, context=context)
47
+ # Add the title to the printed output so title is tested when checking
48
+ # `captured.out` later.
49
+ print(search.title())
50
+
51
+ # Generate the search text and print it to `captured.out` so we can check
52
+ search.search_text(text, path, workbox_id)
53
+
54
+ captured = capsys.readouterr()
55
+ check_filename = "{}_{}_{}_{}.md".format(check_type, is_cs, context, is_re)
56
+ check = text_for_test(check_filename)
57
+
58
+ # To update tests, print text and save over top of the md. Then verify
59
+ # that it is actually rendered properly. You will need to add one trailing
60
+ # space after dot lines, two spaces after blank lines, and ensue the end of
61
+ # file newline is present. The default print callbacks use markdown links,
62
+ # but don't really render valid markdown. If you want to render to html,
63
+ # use regular markdown not github flavored.
64
+ # print(check_filename)
65
+ # print(captured.out)
66
+
67
+ # print('*' * 50)
68
+ # for line in check.rstrip().splitlines(keepends=True):
69
+ # print([line])
70
+ # print('*' * 50)
71
+ # for line in captured.out.splitlines(keepends=True):
72
+ # print([line])
73
+
74
+ assert captured.out == check
@@ -0,0 +1,171 @@
1
+ from __future__ import absolute_import, print_function
2
+
3
+ import sys
4
+
5
+ import pytest
6
+ from Qt.QtWidgets import QApplication
7
+
8
+ from preditor.delayable_engine import DelayableEngine
9
+ from preditor.delayable_engine.delayables import Delayable, RangeDelayable
10
+ from preditor.scintilla.documenteditor import DocumentEditor
11
+
12
+ # TODO: Re-enable these tests once they work on the github runners
13
+ pytestmark = pytest.mark.skipif(
14
+ sys.platform != "win32", reason="Test fails on gitrunner"
15
+ )
16
+
17
+
18
+ class RangeTestDelayable(RangeDelayable):
19
+ key = 'range_test'
20
+
21
+ def add_document(self, document):
22
+ try:
23
+ document.init_count += 1
24
+ except AttributeError:
25
+ document.init_count = 1
26
+
27
+ def loop(self, document, line_num, line_end, value):
28
+ return
29
+
30
+ def remove_document(self, document):
31
+ document.init_count -= 1
32
+
33
+
34
+ class ADelayable(Delayable):
35
+ key = 'a_delayable'
36
+
37
+ def add_document(self, document):
38
+ try:
39
+ document.init_count += 1
40
+ except AttributeError:
41
+ document.init_count = 1
42
+ # enqueue a command so we can verify that remove_delayable removes it
43
+ self.engine.enqueue(document, self.key)
44
+
45
+ def remove_document(self, document):
46
+ document.init_count -= 1
47
+
48
+
49
+ @pytest.fixture()
50
+ def engine():
51
+ """Creates a test DelayableEngine and DocumentEditor.
52
+ The DocumentEditor can be accessed by using `engine.test_doc`.
53
+ """
54
+ global app
55
+ if not QApplication.instance():
56
+ # These test require an initialized QApplication create one and ensure
57
+ # it doesn't get garbage collected. Creating the app here prevents
58
+ # segfaults when skipping this file on linux. We need to figure out
59
+ # how to run these tests in github actions.
60
+ app = QApplication([])
61
+
62
+ engine = DelayableEngine('test_engine')
63
+ engine.test_doc = DocumentEditor(None)
64
+ engine.add_document(engine.test_doc)
65
+
66
+ return engine
67
+
68
+
69
+ def test_add_delayable(engine):
70
+ assert len(engine.delayables) == 0
71
+
72
+ # Check that we can add a instance of Delayable
73
+ delayable = RangeTestDelayable(engine)
74
+ engine.add_delayable(delayable)
75
+ assert len(engine.delayables) == 1
76
+
77
+ # Adding a second delayable with the same key replaces the previous one
78
+ delayable1 = RangeTestDelayable(engine)
79
+ engine.add_delayable(delayable1)
80
+ assert len(engine.delayables) == 1
81
+ assert engine.delayables['range_test'] == delayable1
82
+
83
+ # Check that if a invalid delayable key is passed a exception is raised
84
+ with pytest.raises(KeyError):
85
+ engine.add_delayable('undefined_key')
86
+ assert len(engine.delayables) == 1
87
+
88
+ # We can add a new Delayable instance if a valid key is passed
89
+ engine.add_delayable('a_delayable')
90
+ assert len(engine.delayables) == 2
91
+
92
+
93
+ @pytest.mark.parametrize(
94
+ 'args1,args2,merged',
95
+ (
96
+ # Smallest start should be used
97
+ ((10, 100, 'a'), (25, 75, 'b'), (10, 100, 'b')),
98
+ ((50, 100, 'a'), (25, 75, 'b'), (25, 100, 'b')),
99
+ # Largest end should be used
100
+ ((50, 60, 'a'), (25, 75, 'b'), (25, 75, 'b')),
101
+ ((50, 100, 'a'), (60, 75, 'b'), (50, 100, 'b')),
102
+ # None should always be used for end if passed
103
+ ((50, 60, 'a'), (25, None, 'b'), (25, None, 'b')),
104
+ ((50, None, 'a'), (25, 75, 'b'), (25, None, 'b')),
105
+ ((50, None, 'a'), (25, None, 'b'), (25, None, 'b')),
106
+ ),
107
+ )
108
+ def test_merge_args(engine, args1, args2, merged):
109
+ delayable = RangeTestDelayable(engine)
110
+ engine.add_delayable(delayable)
111
+
112
+ engine.enqueue(engine.test_doc, 'range_test', *args1)
113
+ args = engine.test_doc.delayable_info['range_test']
114
+ # merge_args should not have been called yet, so args should be unchanged
115
+ assert args == args1
116
+
117
+ # Encueue the same key twice without looping will force a call of merge_args
118
+ engine.enqueue(engine.test_doc, 'range_test', *args2)
119
+ args = engine.test_doc.delayable_info['range_test']
120
+ assert args == merged
121
+
122
+
123
+ def test_remove_documents(engine):
124
+ """Check that a document can be removed and added correctly."""
125
+ delayable = RangeTestDelayable(engine)
126
+ engine.add_delayable(delayable)
127
+
128
+ # Check that add_document was called originally
129
+ assert len(engine.documents) == 1
130
+ assert engine.test_doc.init_count == 1
131
+ # Check that the delayable_engine was updated correctly
132
+ assert engine.test_doc.delayable_engine.name == 'test_engine'
133
+
134
+ # Check that remove_document was called
135
+ engine.remove_document(engine.test_doc)
136
+ assert len(engine.documents) == 0
137
+ assert engine.test_doc.init_count == 0
138
+ assert engine.test_doc.delayable_engine.name == 'default'
139
+
140
+ # Check that add_document is called again
141
+ engine.add_document(engine.test_doc)
142
+ assert len(engine.documents) == 1
143
+ assert engine.test_doc.init_count == 1
144
+ assert engine.test_doc.delayable_engine.name == 'test_engine'
145
+
146
+
147
+ def test_remove_delayables(engine):
148
+ """Check that a delayable can be added and removed correctly."""
149
+ delayable = ADelayable(engine)
150
+ engine.add_delayable(delayable)
151
+
152
+ # Check that add_document was called originally
153
+ assert len(engine.delayables) == 1
154
+ assert engine.test_doc.init_count == 1
155
+ assert 'a_delayable' in engine.test_doc.delayable_info
156
+ # Removing a delayable doesn't remove the delay engine
157
+ assert engine.test_doc.delayable_engine.name == 'test_engine'
158
+
159
+ # Check that remove_document was called
160
+ engine.remove_delayable(delayable)
161
+ assert len(engine.delayables) == 0
162
+ assert engine.test_doc.init_count == 0
163
+ assert 'a_delayable' not in engine.test_doc.delayable_info
164
+ assert engine.test_doc.delayable_engine.name == 'test_engine'
165
+
166
+ # Check that add_document is called again
167
+ engine.add_delayable(delayable)
168
+ assert len(engine.delayables) == 1
169
+ assert engine.test_doc.init_count == 1
170
+ assert 'a_delayable' in engine.test_doc.delayable_info
171
+ assert engine.test_doc.delayable_engine.name == 'test_engine'
@@ -1 +0,0 @@
1
- preditor