[chore] Drop py27 support and update lark dependency from lark-parser to lark>=1.3.1#82
Merged
Mikaayenson merged 18 commits intomasterfrom Nov 18, 2025
Merged
[chore] Drop py27 support and update lark dependency from lark-parser to lark>=1.3.1#82Mikaayenson merged 18 commits intomasterfrom
Mikaayenson merged 18 commits intomasterfrom
Conversation
- Migrated from deprecated lark-parser package to lark package - Updated dependency in setup.py from lark-parser~=0.12.0 to lark>=1.3.1 - Bumped version to 0.9.20 - Updated CHANGELOG.md with migration details The code already uses the correct import paths (from lark import ...), so no code changes were required. All functionality tested and verified.
Mikaayenson
commented
Nov 14, 2025
Collaborator
…to update_lark_dependency
Collaborator
Mikaayenson
commented
Nov 15, 2025
Contributor
|
I run the geneve tests with this preliminary eql branch, everything looks fine. Such tests are quite picky with the reproducibility of the data generation, if they do not complain it means that data that was generated (and therefore the corresponding eql rules ASTs) did not change of a single bit. |
terrancedejesus
approved these changes
Nov 17, 2025
Mikaayenson
commented
Nov 17, 2025
Collaborator
|
Nit. May want to remove Python 2.7 references from docs/_static/eql-crash-course.slides.html and CONTRIBUTING.md. |
Collaborator
|
Unit testing results 🟢 Details
========================================================================================================= test session starts ==========================================================================================================
platform linux -- Python 3.12.12, pytest-9.0.1, pluggy-1.6.0 -- /tmp/eql/env/eql-build/bin/python
cachedir: .pytest_cache
rootdir: /tmp/eql
configfile: setup.cfg
plugins: cov-7.0.0, typeguard-4.3.0
collected 616 items
------------------------------------------------------------------------------------------------ generated xml file: /tmp/eql/junit.xml ------------------------------------------------------------------------------------------------
============================================================================================================ tests coverage ============================================================================================================
___________________________________________________________________________________________ coverage: platform linux, python 3.12.12-final-0 ___________________________________________________________________________________________
Name Stmts Miss Branch BrPart Cover Missing
-----------------------------------------------------------------
eql/__init__.py 16 16 0 0 0% 2-70
eql/ast.py 691 331 204 20 58% 2-79, 85-99, 103, 107, 111, 127, 132, 136, 140, 146-152, 157, 161, 170-179, 185-187, 208, 229, 234-241, 247-248, 261-262, 267-277, 281-286, 290-294, 298-303, 307-325, 331-332, 343, 347-357, 361, 374-376, 381-387, 392, 396, 400-410, 421, 424->426, 428-429, 433-434, 442, 445, 456-464, 474-480, 484, 487, 493, 495->500, 502, 513-532, 542-555, 561, 565-566, 573-574, 579-592, 600-608, 610->618, 612->618, 620, 627-634, 639-646, 651-657, 663, 667-671, 685, 688->713, 698->713, 706->713, 710->713, 715, 718->730, 727->730, 732-748, 752, 765-771, 778, 781, 792-799, 806-821, 827-829, 833-853, 862, 870-875, 882, 886-891, 902-903, 906->911, 909->911, 913, 926-931, 940, 949-957, 964-978, 989-997, 1010-1017, 1022-1034, 1039, 1045-1050, 1059, 1064-1069, 1078-1079, 1083-1084, 1088-1096, 1100-1105, 1114-1120, 1126-1137, 1146, 1151-1166, 1178, 1213, 1221-1224, 1250, 1255, 1262->exit, 1264, 1267, 1279, 1288-1290
eql/build.py 70 35 18 4 49% 2-72, 79, 95, 105, 107, 123, 130->133
eql/engine.py 858 137 358 21 85% 2-23, 27, 36-39, 67, 79-83, 89, 93, 99, 101->104, 105-109, 117-120, 124-125, 137-138, 145->exit, 152-153, 160->exit, 165, 195-196, 204, 230, 239-240, 247, 256, 266, 276, 280, 288, 294, 327, 343, 349-350, 354, 372, 389, 412, 424, 433, 437, 441, 459, 462-463, 468, 490, 513, 523-524, 531, 554-555, 568, 572, 583, 599, 612, 632, 647, 661-662, 687, 693, 703->707, 715-716, 732->735, 746-747, 751, 761, 808, 855, 894, 906, 937, 948-966, 980, 1029, 1038, 1071, 1086, 1119, 1147, 1151, 1155, 1160, 1165, 1170, 1176, 1194, 1199, 1208, 1217, 1238->exit, 1241, 1252, 1263, 1267-1272, 1277
eql/errors.py 22 11 2 0 54% 2-29, 45-57
eql/etc/__init__.py 9 8 0 0 11% 2-8, 13-17
eql/events.py 23 10 6 1 62% 2-12, 24->29, 31, 37-41
eql/functions.py 361 218 102 14 49% 2-22, 27-36, 41-49, 53-56, 59-68, 74-106, 108->exit, 112-122, 130-133, 147-176, 192-202, 207->214, 218-219, 221->231, 225->224, 233-234, 240, 263-273, 280-287, 295-304, 306->exit, 310-321, 333-342, 348-363, 374-375, 389-393, 396, 403-417, 419->exit, 423-430, 432->exit, 436-454, 460-469, 473-486, 492-499, 501->exit, 505-516, 518->exit, 523->exit, 527-536, 545-555, 573-574, 586-587, 593-594, 603
eql/loader.py 16 10 2 1 39% 2-13, 16->18, 21, 29-31
eql/main.py 100 31 20 4 66% 35-37, 44-52, 64, 72-74, 82-88, 93-104, 147, 149
eql/optimizer.py 120 31 58 3 81% 2-14, 19, 26-27, 41-42, 50-51, 59-60, 80-81, 89-90, 94-95, 120-121, 136-137, 140, 148, 151, 161-162, 178
eql/parser.py 943 223 460 53 78% 2-76, 81, 87, 91, 95-96, 99-100, 105-111, 116-122, 127-133, 138-147, 176, 201-202, 209-210, 220, 227-228, 232, 250, 278, 297->289, 303, 312-320, 327, 337, 363, 367, 373->exit, 388-393, 397, 401, 406, 444, 460, 471, 493->509, 522, 526, 535, 539, 543, 550, 555, 559, 571, 580, 583, 603, 611-612, 629, 637, 646, 662, 666, 682, 692, 707, 758->769, 771, 779, 794-797, 804, 809, 813, 817, 821->826, 823, 831, 837, 847, 853, 860, 874->882, 879->882, 884, 971->943, 996, 1015, 1018, 1033->1041, 1045, 1049, 1056, 1076, 1080, 1085, 1087, 1094, 1097, 1153, 1161, 1165, 1173, 1179, 1220, 1244-1289, 1296, 1300, 1304, 1307, 1334, 1339, 1344, 1346, 1353->1364, 1361-1362, 1369, 1379-1385, 1422->1425, 1439-1477, 1494, 1508, 1520, 1525, 1530, 1545, 1553->1555, 1558, 1571, 1585, 1608-1611, 1614, 1617, 1623-1625, 1630-1634
eql/pipes.py 75 51 16 5 38% 2-19, 24-39, 60-69, 73, 76-77, 80, 84-93, 97, 100-101, 104, 108-125, 129, 146-153
eql/schema.py 217 85 148 29 63% 2-40, 48, 52, 62, 64-66, 69, 74, 79, 82-83, 94-95, 103, 106-110, 115, 127, 133->exit, 135, 139, 141, 148-153, 166-167, 174, 180, 182-200, 206-208, 221, 232-233, 236, 239-240, 247, 251-252, 258->256, 263, 271-275, 278, 282, 286, 287->exit, 290-291, 298, 306-308
eql/signatures.py 15 7 6 0 67% 2-13
eql/transpilers.py 108 82 14 1 25% 2-52, 59-60, 64-88, 100, 110, 116, 122-129, 137-182
eql/types.py 73 35 24 3 61% 2-18, 22-38, 47, 51-59, 74, 84, 90, 103, 113, 118, 127-133
eql/utils.py 250 95 110 23 65% 2-34, 39, 44, 49, 54, 65, 72, 75, 79, 84, 89, 99, 103-104, 110-113, 136-140, 154-157, 167-174, 178->177, 182, 191->197, 194-195, 198-200, 209, 219-220, 226, 242, 253, 256, 269, 278, 281, 286, 292-295, 333, 342, 345, 350, 359, 362, 367, 376, 384, 396-404, 410-411, 415-416, 420-421, 425-426, 433, 436, 443, 449
eql/walkers.py 174 60 58 7 70% 2-28, 38, 44, 57-60, 66, 74-83, 86, 96, 99, 102, 105, 108, 111, 119, 122, 124->127, 146-157, 174, 181, 186, 193->exit, 198-201, 206, 211-214, 222->exit, 229-237, 248, 258-261, 267, 273
-----------------------------------------------------------------
TOTAL 4141 1476 1606 189 69%
Coverage HTML written to dir htmlcov
Coverage XML written to file coverage.xml
=================================================================================================== 616 passed in 853.89s (0:14:13) ====================================================================================================
Search CLI functions 🟢 Details
eql> search
..> any where host.os.type == "linux" and event.dataset == "kubernetes.audit_logs" and kubernetes.audit.verb == "delete"
..> and kubernetes.audit.objectRef.resource == "events" and kubernetes.audit.stage == "ResponseComplete"
..>
eql>
|
eric-forte-elastic
approved these changes
Nov 17, 2025
Collaborator
eric-forte-elastic
left a comment
There was a problem hiding this comment.
🟢 Manual review, spot testing queries 🟢 , new properties look good. LGTM! 👍
Nit in the changelog should there be a reference to the new properties of KvTree? Not sure if necessary or not.
Contributor
Author
|
@cavokz want to do a final test before closing this out? |
Contributor
|
👏 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Resolves #81
This PR updates the EQL library to use the modern
larkpackage (v1.3.1) instead of the deprecatedlark-parser(v0.12.0), fixes compatibility issues with the new Lark version, and drops support for Python 2.7 and Python < 3.8.Changes
Dependency Updates
lark-parser~=0.12.0tolark>=1.3.1lark-parserpackage has been deprecated and replaced bylarkCompatibility Fixes for Lark 1.3.1
Lark 1.3.1 handles optional grammar rules differently than
lark-parser0.12.0. When optional rules (marked with[...]in the grammar) are empty, Lark 1.3.1 includes them in the parse tree asNonevalues, whereas the old version would omit them entirely. This required fixes to:macro TRUE()) now parse correctly. The implementation filters outNonevalues before visiting parameter nodes, resulting in cleaner, more maintainable code.| count) now handle empty argument lists correctly using theor []pattern for cleaner null handling.Schema.current(): Ensures it always returns a valid Schema object, neverNone, by falling back toEMPTY_SCHEMAwhen both the stack and default areNone.KvTreeposition information: Added compatibility properties (line,end_line,column,end_column) to access position information from Lark 1.3.1'smetaattribute, with fallback to token-based position information.Python Version Support
eql/ast.pyeql/shell.py(removedraw_inputfallback)eql/utils.pyCI/CD Updates
actions/checkoutfrom v2 to v5actions/setup-pythonfrom v4 to v5.github/workflows/pythonpackage27.yml)setuptoolsto dependency installation (required for Python 3.12)Testing
endpoint-rulesanddetection-rulesrepositories:Technical Details
Why the Changes Were Needed
Lark 1.3.1 handles optional grammar rules differently than
lark-parser0.12.0. When optional rules (marked with[...]in the grammar) are empty, Lark 1.3.1 includes them in the parse tree asNonevalues, whereas the old version would omit them entirely. This required fixes to:[None]instead of[][None]instead of[]Schema.current()never returnsNonenode.metainstead of directly on the nodeImplementation Approach
The fixes for Lark 1.3.1 compatibility follow a consistent pattern:
Filter
Nonebefore visiting: Instead of visiting nodes that may containNoneand filtering afterward, we filterNonevalues from the children list before callingvisit(). This results in cleaner code and better performance.Use
or []pattern: For cases wherevisit()may returnNone, we use theor []pattern to provide a default empty list, making the code more Pythonic and concise.Position information compatibility: The
KvTreeclass now checks for position information in Lark 1.3.1'smetaattribute first, then falls back to inspecting child tokens, ensuring compatibility with both old and new Lark versions.Files Changed
Core Changes:
eql/parser.py: Fixed macro and pipe parsing, addedKvTreecompatibility propertieseql/schema.py: FixedSchema.current()to always return a valid schemasetup.py: Updated dependencies, removed Python 2.7 support, fixed deprecated APIseql/__init__.py: Updated version to 0.9.20Cleanup:
eql/ast.py: Removed Python 2.7 encoding checkeql/shell.py: Simplified input functioneql/utils.py: Removed Python 2/3 compatibility codetests/test_python_engine.py: Removed Python 2 support codetests/test_cli.py: Updatedmockimport to useunittest.mockDocumentation:
CHANGELOG.md: Added comprehensive changelog entryREADME.md: Updated Python version requirement and version exampledocs/index.rst: Updated Python version requirementdocs/cli.rst: Removed Python 2.7 notesCI/CD:
.github/workflows/pythonpackage.yml: Updated to Python 3.8+, newer actions, removed deprecation warnings.github/workflows/pythonpackage27.yml: Deleted (Python 2.7 no longer supported)Configuration:
setup.cfg: Added linting exemptions for style issues (W504, E241, etc.)Testing
EQL Unit Tests
Integration Testing
endpoint-rulesdetection-rulesendpoint-rulesdetection-rules(KvTree, LarkToEQL, NodeInfo, TypeHint)Breaking Changes
Important
Python 2.7 and Python < 3.8 are no longer supported
Users must upgrade to Python 3.8 or higher
Migration Guide
If you're using Python 2.7 or Python < 3.8, you must upgrade to Python 3.8+ before using eql 0.9.20.
No code changes are required for existing Python 3.8+ users - the API remains the same.
Related Issues
lark-parserpackage tolark