codrone-edu 2.8__tar.gz → 2.9__tar.gz
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.
- {codrone_edu-2.8 → codrone_edu-2.9}/PKG-INFO +1 -1
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/drone.py +12 -4
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/system.py +3 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/tools/transformer.py +135 -130
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu.egg-info/PKG-INFO +1 -1
- {codrone_edu-2.8 → codrone_edu-2.9}/setup.py +1 -1
- {codrone_edu-2.8 → codrone_edu-2.9}/MANIFEST.in +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/README.md +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/__init__.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/__main__.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/crc.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/data/black.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/data/blue.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/data/green.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/data/lightblue.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/data/purple.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/data/red.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/data/white.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/data/yellow.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/errors.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/protocol.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/receiver.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/storage.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/swarm.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/tools/__init__.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/tools/interrupter.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/tools/module_loader.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/tools/parser.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/tools/scrubber.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu/tools/update.py +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu.egg-info/SOURCES.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu.egg-info/dependency_links.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu.egg-info/not-zip-safe +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu.egg-info/requires.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/codrone_edu.egg-info/top_level.txt +0 -0
- {codrone_edu-2.8 → codrone_edu-2.9}/setup.cfg +0 -0
|
@@ -182,6 +182,8 @@ class Drone:
|
|
|
182
182
|
self._cpuId = []
|
|
183
183
|
self._battery = 0
|
|
184
184
|
self._system = ModeSystem.Error
|
|
185
|
+
self._state_update_count = 0
|
|
186
|
+
self._last_state_update_time = 0.0
|
|
185
187
|
|
|
186
188
|
self.timeStartProgram = time.time() # Program Start Time Recording
|
|
187
189
|
|
|
@@ -1142,6 +1144,10 @@ class Drone:
|
|
|
1142
1144
|
self.state_data[6] = drone_type.battery
|
|
1143
1145
|
self.state_data[7] = drone_type.modeMovement
|
|
1144
1146
|
self.state_data[8] = drone_type.controlSpeed
|
|
1147
|
+
if sys.platform == 'emscripten':
|
|
1148
|
+
self._battery = drone_type.battery
|
|
1149
|
+
self._state_update_count += 1
|
|
1150
|
+
self._last_state_update_time = time.time()
|
|
1145
1151
|
|
|
1146
1152
|
def get_state_data(self, delay=0.01):
|
|
1147
1153
|
if sys.platform != 'emscripten' and not self._swarm:
|
|
@@ -1162,10 +1168,14 @@ class Drone:
|
|
|
1162
1168
|
return self.state_data
|
|
1163
1169
|
|
|
1164
1170
|
async def _get_state_data_emscripten(self, delay=0.01):
|
|
1171
|
+
prev_count = self._state_update_count
|
|
1165
1172
|
await self.sendRequest(DeviceType.Drone, DataType.State)
|
|
1166
1173
|
await asyncio.sleep(delay)
|
|
1167
1174
|
self._system = self.state_data[1]
|
|
1168
|
-
self.
|
|
1175
|
+
if self._state_update_count == prev_count:
|
|
1176
|
+
# No response this call — only zero battery if data is genuinely stale
|
|
1177
|
+
if time.time() - self._last_state_update_time > 2.0:
|
|
1178
|
+
self._battery = 0
|
|
1169
1179
|
self.state_data[1] = ModeSystem.Error
|
|
1170
1180
|
self.state_data[6] = 0
|
|
1171
1181
|
return self.state_data
|
|
@@ -1192,9 +1202,7 @@ class Drone:
|
|
|
1192
1202
|
|
|
1193
1203
|
async def _get_battery_emscripten(self):
|
|
1194
1204
|
await self.get_state_data(delay=0.02)
|
|
1195
|
-
|
|
1196
|
-
self._battery = 0
|
|
1197
|
-
return battery
|
|
1205
|
+
return self._battery
|
|
1198
1206
|
|
|
1199
1207
|
def get_system_state(self):
|
|
1200
1208
|
if sys.platform != 'emscripten' and not self._swarm:
|
|
@@ -77,7 +77,10 @@ class ModelNumber(Enum):
|
|
|
77
77
|
|
|
78
78
|
Drone_12_Controller_P1 = 0x000C2001 # Drone_12_Controller_P1 (CDE JROTC ed.)
|
|
79
79
|
Drone_12_Drone_P1 = 0x000C1002 # Drone_12_Drone_P1 (CDE JROTC ed.)
|
|
80
|
+
Drone_8_Drone_P3 = 0x00081003 # Drone_8_Drone_P3 CoDrone EDU (IMU)
|
|
80
81
|
|
|
82
|
+
Drone_12_Controller_P10 = 0x000C200A # CDEP Controller
|
|
83
|
+
Drone_12_Drone_P10 = 0x000C100A # CDEP Drone
|
|
81
84
|
|
|
82
85
|
|
|
83
86
|
class DeviceType(Enum):
|
|
@@ -369,6 +369,141 @@ class AsyncTransformer(ast.NodeTransformer):
|
|
|
369
369
|
return self.copy_location(new_node, node)
|
|
370
370
|
return node
|
|
371
371
|
|
|
372
|
+
class ModuleAsyncTransformer(ast.NodeTransformer):
|
|
373
|
+
"""
|
|
374
|
+
Transforms imported user modules to async without wrapping in a _wrapper function.
|
|
375
|
+
Unlike AsyncTransformer, this does not restructure the module body — it only converts
|
|
376
|
+
functions to async and adds await to drone/custom calls in-place.
|
|
377
|
+
Used by transform_imported_module() for user modules loaded via the custom import hook.
|
|
378
|
+
"""
|
|
379
|
+
def __init__(self, custom_functions, drone_instance_name, function_aliases=None):
|
|
380
|
+
self.custom_functions = custom_functions
|
|
381
|
+
self.drone_instance_name = drone_instance_name
|
|
382
|
+
self.function_aliases = function_aliases if function_aliases else {}
|
|
383
|
+
self.time_alias = None # Track what 'time' is imported as
|
|
384
|
+
self.custom_modules = set() # Track modules from custom imports
|
|
385
|
+
|
|
386
|
+
def copy_location(self, new_node, old_node):
|
|
387
|
+
ast.copy_location(new_node, old_node)
|
|
388
|
+
if hasattr(old_node, 'end_lineno'):
|
|
389
|
+
new_node.end_lineno = old_node.end_lineno
|
|
390
|
+
if hasattr(old_node, 'end_col_offset'):
|
|
391
|
+
new_node.end_col_offset = old_node.end_col_offset
|
|
392
|
+
return new_node
|
|
393
|
+
|
|
394
|
+
def visit_Import(self, node):
|
|
395
|
+
"""Track time module imports and custom module imports"""
|
|
396
|
+
for alias in node.names:
|
|
397
|
+
if alias.name == 'time':
|
|
398
|
+
self.time_alias = alias.asname if alias.asname else 'time'
|
|
399
|
+
else:
|
|
400
|
+
# Track custom module imports (not library modules)
|
|
401
|
+
module_name = alias.name.split('.')[0] # Get root module name
|
|
402
|
+
if module_name not in LIBRARY_MODULES:
|
|
403
|
+
local_name = alias.asname if alias.asname else alias.name
|
|
404
|
+
self.custom_modules.add(local_name)
|
|
405
|
+
return self.generic_visit(node)
|
|
406
|
+
|
|
407
|
+
def visit_ImportFrom(self, node):
|
|
408
|
+
"""Track ImportFrom statements for both time and custom modules"""
|
|
409
|
+
if node.module == 'time':
|
|
410
|
+
self.time_alias = 'time'
|
|
411
|
+
elif node.module:
|
|
412
|
+
# Track custom module imports
|
|
413
|
+
module_name = node.module.split('.')[0] # Get root module name
|
|
414
|
+
if module_name not in LIBRARY_MODULES:
|
|
415
|
+
# For "from module import x", track imported names
|
|
416
|
+
for alias in node.names:
|
|
417
|
+
local_name = alias.asname if alias.asname else alias.name
|
|
418
|
+
if local_name != '*': # Skip import *
|
|
419
|
+
self.custom_modules.add(local_name)
|
|
420
|
+
return self.generic_visit(node)
|
|
421
|
+
|
|
422
|
+
def visit_FunctionDef(self, node):
|
|
423
|
+
new_node = ast.AsyncFunctionDef(
|
|
424
|
+
name=node.name,
|
|
425
|
+
args=node.args,
|
|
426
|
+
body=node.body,
|
|
427
|
+
decorator_list=node.decorator_list,
|
|
428
|
+
returns=node.returns
|
|
429
|
+
)
|
|
430
|
+
new_node = self.copy_location(new_node, node)
|
|
431
|
+
self.generic_visit(new_node)
|
|
432
|
+
return new_node
|
|
433
|
+
|
|
434
|
+
def visit_Call(self, node):
|
|
435
|
+
# First, visit all arguments and keywords to ensure nested calls are transformed
|
|
436
|
+
node = self.generic_visit(node)
|
|
437
|
+
|
|
438
|
+
if isinstance(node.func, ast.Attribute):
|
|
439
|
+
# Handle attribute calls (e.g., drone.takeoff(), helper.do_something(), np.array())
|
|
440
|
+
if isinstance(node.func.value, ast.Name):
|
|
441
|
+
module_name = node.func.value.id
|
|
442
|
+
method_name = node.func.attr
|
|
443
|
+
|
|
444
|
+
# Check if this is a drone method call (by method name, not variable name)
|
|
445
|
+
# This allows imported modules to use drone instances with any parameter name
|
|
446
|
+
if method_name in awaitable_drone_methods:
|
|
447
|
+
if method_name in ['pair', 'open', 'connect', 'disconnect', 'close']:
|
|
448
|
+
# Replace with dummy_function()
|
|
449
|
+
new_node = ast.Call(
|
|
450
|
+
func=ast.Attribute(value=node.func.value, attr='dummy_function', ctx=ast.Load()),
|
|
451
|
+
args=[], keywords=[]
|
|
452
|
+
)
|
|
453
|
+
return self.copy_location(new_node, node)
|
|
454
|
+
elif method_name not in non_await_drone_functions:
|
|
455
|
+
new_node = ast.Await(value=node)
|
|
456
|
+
return self.copy_location(new_node, node)
|
|
457
|
+
elif module_name == self.drone_instance_name:
|
|
458
|
+
# Fallback: check if variable is named 'drone' (for any unlisted methods)
|
|
459
|
+
if node.func.attr in ['pair', 'open', 'connect', 'disconnect', 'close']:
|
|
460
|
+
# Replace with dummy_function()
|
|
461
|
+
new_node = ast.Call(
|
|
462
|
+
func=ast.Attribute(value=ast.Name(id=self.drone_instance_name, ctx=ast.Load()), attr='dummy_function', ctx=ast.Load()),
|
|
463
|
+
args=[], keywords=[]
|
|
464
|
+
)
|
|
465
|
+
return self.copy_location(new_node, node)
|
|
466
|
+
elif node.func.attr not in non_await_drone_functions:
|
|
467
|
+
new_node = ast.Await(value=node)
|
|
468
|
+
return self.copy_location(new_node, node)
|
|
469
|
+
elif module_name in self.custom_modules:
|
|
470
|
+
# Calls on custom imported modules (e.g., helper.do_something())
|
|
471
|
+
new_node = ast.Await(value=node)
|
|
472
|
+
return self.copy_location(new_node, node)
|
|
473
|
+
# Skip library module calls (e.g., np.array(), asyncio.sleep())
|
|
474
|
+
elif isinstance(node.func, ast.Name):
|
|
475
|
+
# Direct function calls (e.g., my_function(), some_utility_function())
|
|
476
|
+
func_name = node.func.id
|
|
477
|
+
|
|
478
|
+
# Check if it's a Python built-in function (don't await built-ins)
|
|
479
|
+
# EXCEPT for input() which is overridden with an async version in Pyodide
|
|
480
|
+
import builtins
|
|
481
|
+
if hasattr(builtins, func_name) and func_name != 'input':
|
|
482
|
+
builtin_obj = getattr(builtins, func_name)
|
|
483
|
+
# Check if it's callable (a function/class) and not async
|
|
484
|
+
# Exclude async built-ins like aiter, anext
|
|
485
|
+
if callable(builtin_obj) and func_name not in {'aiter', 'anext'}:
|
|
486
|
+
return node
|
|
487
|
+
|
|
488
|
+
# Look up the original function name if this is an alias
|
|
489
|
+
original_name = self.function_aliases.get(func_name, func_name)
|
|
490
|
+
|
|
491
|
+
# Await if it's NOT a known library function
|
|
492
|
+
# This handles:
|
|
493
|
+
# - Custom functions defined in the file
|
|
494
|
+
# - Functions imported from custom modules
|
|
495
|
+
# - Functions from 'import *' (which we can't track)
|
|
496
|
+
# - input() calls (overridden with async version in Pyodide)
|
|
497
|
+
if (func_name in self.custom_functions or
|
|
498
|
+
original_name in self.custom_functions or
|
|
499
|
+
func_name in self.custom_modules or
|
|
500
|
+
func_name == 'input' or
|
|
501
|
+
func_name not in LIBRARY_MODULES): # Await unknown functions (could be from import *)
|
|
502
|
+
new_node = ast.Await(value=node)
|
|
503
|
+
return self.copy_location(new_node, node)
|
|
504
|
+
return node
|
|
505
|
+
|
|
506
|
+
|
|
372
507
|
class SleepTransformer(ast.NodeTransformer):
|
|
373
508
|
def __init__(self, time_alias=None):
|
|
374
509
|
self.time_alias = time_alias if time_alias else 'time'
|
|
@@ -531,136 +666,6 @@ def transform_imported_module(code):
|
|
|
531
666
|
analyzer = CodeAnalyzer()
|
|
532
667
|
analyzer.visit(tree)
|
|
533
668
|
|
|
534
|
-
# Create a modified AsyncTransformer that doesn't wrap in _wrapper
|
|
535
|
-
class ModuleAsyncTransformer(ast.NodeTransformer):
|
|
536
|
-
def __init__(self, custom_functions, drone_instance_name, function_aliases=None):
|
|
537
|
-
self.custom_functions = custom_functions
|
|
538
|
-
self.drone_instance_name = drone_instance_name
|
|
539
|
-
self.function_aliases = function_aliases if function_aliases else {}
|
|
540
|
-
self.time_alias = None # Track what 'time' is imported as
|
|
541
|
-
self.custom_modules = set() # Track modules from custom imports
|
|
542
|
-
|
|
543
|
-
def copy_location(self, new_node, old_node):
|
|
544
|
-
ast.copy_location(new_node, old_node)
|
|
545
|
-
if hasattr(old_node, 'end_lineno'):
|
|
546
|
-
new_node.end_lineno = old_node.end_lineno
|
|
547
|
-
if hasattr(old_node, 'end_col_offset'):
|
|
548
|
-
new_node.end_col_offset = old_node.end_col_offset
|
|
549
|
-
return new_node
|
|
550
|
-
|
|
551
|
-
def visit_Import(self, node):
|
|
552
|
-
"""Track time module imports and custom module imports"""
|
|
553
|
-
for alias in node.names:
|
|
554
|
-
if alias.name == 'time':
|
|
555
|
-
self.time_alias = alias.asname if alias.asname else 'time'
|
|
556
|
-
else:
|
|
557
|
-
# Track custom module imports (not library modules)
|
|
558
|
-
module_name = alias.name.split('.')[0] # Get root module name
|
|
559
|
-
if module_name not in LIBRARY_MODULES:
|
|
560
|
-
local_name = alias.asname if alias.asname else alias.name
|
|
561
|
-
self.custom_modules.add(local_name)
|
|
562
|
-
return self.generic_visit(node)
|
|
563
|
-
|
|
564
|
-
def visit_ImportFrom(self, node):
|
|
565
|
-
"""Track ImportFrom statements for both time and custom modules"""
|
|
566
|
-
if node.module == 'time':
|
|
567
|
-
self.time_alias = 'time'
|
|
568
|
-
elif node.module:
|
|
569
|
-
# Track custom module imports
|
|
570
|
-
module_name = node.module.split('.')[0] # Get root module name
|
|
571
|
-
if module_name not in LIBRARY_MODULES:
|
|
572
|
-
# For "from module import x", track imported names
|
|
573
|
-
for alias in node.names:
|
|
574
|
-
local_name = alias.asname if alias.asname else alias.name
|
|
575
|
-
if local_name != '*': # Skip import *
|
|
576
|
-
self.custom_modules.add(local_name)
|
|
577
|
-
return self.generic_visit(node)
|
|
578
|
-
|
|
579
|
-
# Don't wrap module - just transform functions
|
|
580
|
-
def visit_FunctionDef(self, node):
|
|
581
|
-
new_node = ast.AsyncFunctionDef(
|
|
582
|
-
name=node.name,
|
|
583
|
-
args=node.args,
|
|
584
|
-
body=node.body,
|
|
585
|
-
decorator_list=node.decorator_list,
|
|
586
|
-
returns=node.returns
|
|
587
|
-
)
|
|
588
|
-
new_node = self.copy_location(new_node, node)
|
|
589
|
-
self.generic_visit(new_node)
|
|
590
|
-
return new_node
|
|
591
|
-
|
|
592
|
-
def visit_Call(self, node):
|
|
593
|
-
# First, visit all arguments and keywords to ensure nested calls are transformed
|
|
594
|
-
node = self.generic_visit(node)
|
|
595
|
-
|
|
596
|
-
if isinstance(node.func, ast.Attribute):
|
|
597
|
-
# Handle attribute calls (e.g., drone.takeoff(), helper.do_something(), np.array())
|
|
598
|
-
if isinstance(node.func.value, ast.Name):
|
|
599
|
-
module_name = node.func.value.id
|
|
600
|
-
method_name = node.func.attr
|
|
601
|
-
|
|
602
|
-
# Check if this is a drone method call (by method name, not variable name)
|
|
603
|
-
# This allows imported modules to use drone instances with any parameter name
|
|
604
|
-
if method_name in awaitable_drone_methods:
|
|
605
|
-
if method_name in ['pair', 'open', 'connect', 'disconnect', 'close']:
|
|
606
|
-
# Replace with dummy_function()
|
|
607
|
-
new_node = ast.Call(
|
|
608
|
-
func=ast.Attribute(value=node.func.value, attr='dummy_function', ctx=ast.Load()),
|
|
609
|
-
args=[], keywords=[]
|
|
610
|
-
)
|
|
611
|
-
return self.copy_location(new_node, node)
|
|
612
|
-
elif method_name not in non_await_drone_functions:
|
|
613
|
-
new_node = ast.Await(value=node)
|
|
614
|
-
return self.copy_location(new_node, node)
|
|
615
|
-
elif module_name == self.drone_instance_name:
|
|
616
|
-
# Fallback: check if variable is named 'drone' (for any unlisted methods)
|
|
617
|
-
if node.func.attr in ['pair', 'open', 'connect', 'disconnect', 'close']:
|
|
618
|
-
# Replace with dummy_function()
|
|
619
|
-
new_node = ast.Call(
|
|
620
|
-
func=ast.Attribute(value=ast.Name(id=self.drone_instance_name, ctx=ast.Load()), attr='dummy_function', ctx=ast.Load()),
|
|
621
|
-
args=[], keywords=[]
|
|
622
|
-
)
|
|
623
|
-
return self.copy_location(new_node, node)
|
|
624
|
-
elif node.func.attr not in non_await_drone_functions:
|
|
625
|
-
new_node = ast.Await(value=node)
|
|
626
|
-
return self.copy_location(new_node, node)
|
|
627
|
-
elif module_name in self.custom_modules:
|
|
628
|
-
# Calls on custom imported modules (e.g., helper.do_something())
|
|
629
|
-
new_node = ast.Await(value=node)
|
|
630
|
-
return self.copy_location(new_node, node)
|
|
631
|
-
# Skip library module calls (e.g., np.array(), asyncio.sleep())
|
|
632
|
-
elif isinstance(node.func, ast.Name):
|
|
633
|
-
# Direct function calls (e.g., my_function(), some_utility_function())
|
|
634
|
-
func_name = node.func.id
|
|
635
|
-
|
|
636
|
-
# Check if it's a Python built-in function (don't await built-ins)
|
|
637
|
-
# EXCEPT for input() which is overridden with an async version in Pyodide
|
|
638
|
-
import builtins
|
|
639
|
-
if hasattr(builtins, func_name) and func_name != 'input':
|
|
640
|
-
builtin_obj = getattr(builtins, func_name)
|
|
641
|
-
# Check if it's callable (a function/class) and not async
|
|
642
|
-
# Exclude async built-ins like aiter, anext
|
|
643
|
-
if callable(builtin_obj) and func_name not in {'aiter', 'anext'}:
|
|
644
|
-
return node
|
|
645
|
-
|
|
646
|
-
# Look up the original function name if this is an alias
|
|
647
|
-
original_name = self.function_aliases.get(func_name, func_name)
|
|
648
|
-
|
|
649
|
-
# Await if it's NOT a known library function
|
|
650
|
-
# This handles:
|
|
651
|
-
# - Custom functions defined in the file
|
|
652
|
-
# - Functions imported from custom modules
|
|
653
|
-
# - Functions from 'import *' (which we can't track)
|
|
654
|
-
# - input() calls (overridden with async version in Pyodide)
|
|
655
|
-
if (func_name in self.custom_functions or
|
|
656
|
-
original_name in self.custom_functions or
|
|
657
|
-
func_name in self.custom_modules or
|
|
658
|
-
func_name == 'input' or
|
|
659
|
-
func_name not in LIBRARY_MODULES): # Await unknown functions (could be from import *)
|
|
660
|
-
new_node = ast.Await(value=node)
|
|
661
|
-
return self.copy_location(new_node, node)
|
|
662
|
-
return node
|
|
663
|
-
|
|
664
669
|
# Transform the AST (without module wrapper)
|
|
665
670
|
module_transformer = ModuleAsyncTransformer(
|
|
666
671
|
analyzer.custom_functions,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|