Skip to content

Commit 7a99631

Browse files
authored
Merge pull request #30 from rayokota/perf1
Minor perf improvements
2 parents bb1f8ab + 5d56b36 commit 7a99631

3 files changed

Lines changed: 25 additions & 32 deletions

File tree

src/jsonata/datetimeutils.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -637,14 +637,14 @@ def format_datetime(millis: int, picture: Optional[str], timezone: Optional[str]
637637

638638
offset_millis = (60 * offset_hours + offset_minutes) * 60 * 1000
639639
date_time = datetime.datetime.fromtimestamp((millis + offset_millis) / 1000.0, datetime.timezone.utc)
640-
result = ""
640+
parts = []
641641
for part in format_spec.parts:
642642
if part.type == "literal":
643-
result += part.value
643+
parts.append(part.value)
644644
else:
645-
result += DateTimeUtils._format_component(date_time, part, offset_hours, offset_minutes)
645+
parts.append(DateTimeUtils._format_component(date_time, part, offset_hours, offset_minutes))
646646

647-
return result
647+
return ''.join(parts)
648648

649649
@staticmethod
650650
def _format_component(date: datetime.datetime, marker_spec: SpecPart, offset_hours: int,

src/jsonata/functions.py

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -474,11 +474,7 @@ def left_pad(string: Optional[str], size: Optional[int], pad_str: Optional[str])
474474
pads = size - str_len
475475
if pads <= 0:
476476
return string
477-
padding = ""
478-
i = 0
479-
while i < pads + 1:
480-
padding += pad_str
481-
i += 1
477+
padding = pad_str * (pads // len(pad_str) + 1)
482478
return Functions.substr(padding, 0, pads) + string
483479

484480
# Source: Jsonata4Java PadFunction
@@ -501,11 +497,7 @@ def right_pad(string: Optional[str], size: Optional[int], pad_str: Optional[str]
501497
pads = size - str_len
502498
if pads <= 0:
503499
return string
504-
padding = ""
505-
i = 0
506-
while i < pads + 1:
507-
padding += pad_str
508-
i += 1
500+
padding = pad_str * (pads // len(pad_str) + 1)
509501
return string + Functions.substr(padding, 0, pads)
510502

511503
@dataclass
@@ -767,39 +759,39 @@ def replace(string: Optional[str], pattern: Union[str, re.Pattern], replacement:
767759
raise jexception.JException("Fourth argument of replace function must evaluate to a positive number", 0)
768760

769761
def string_replacer(match):
770-
result = ''
762+
parts = []
771763
position = 0
772764
repl = str(replacement)
773765
while position < len(repl):
774766
index = repl.find('$', position)
775767
if index == -1:
776-
result += repl[position:]
768+
parts.append(repl[position:])
777769
break
778-
result += repl[position:index]
770+
parts.append(repl[position:index])
779771
position = index + 1
780772
if position < len(repl):
781773
dollar_val = repl[position]
782774
if dollar_val == '$':
783-
result += '$'
775+
parts.append('$')
784776
position += 1
785777
elif dollar_val == '0':
786-
result += match.group(0)
778+
parts.append(match.group(0))
787779
position += 1
788780
else:
789781
max_digits = len(str(len(match.groups())))
790782
group_num = repl[position:position+max_digits]
791783
if group_num.isdigit():
792784
group_index = int(group_num)
793785
if 0 < group_index <= len(match.groups()):
794-
result += match.group(group_index) or ''
786+
parts.append(match.group(group_index) or '')
795787
position += len(group_num)
796788
else:
797-
result += '$'
789+
parts.append('$')
798790
else:
799-
result += '$'
791+
parts.append('$')
800792
else:
801-
result += '$'
802-
return result
793+
parts.append('$')
794+
return ''.join(parts)
803795

804796
if callable(replacement):
805797
replacer = lambda m: replacement(m.groupdict())
@@ -810,23 +802,23 @@ def string_replacer(match):
810802

811803
if isinstance(pattern, str):
812804
# Use string methods for literal string patterns
813-
result = ''
805+
parts = []
814806
position = 0
815807
count = 0
816808
while True:
817809
if limit is not None and count >= limit:
818-
result += string[position:]
810+
parts.append(string[position:])
819811
break
820812
index = string.find(pattern, position)
821813
if index == -1:
822-
result += string[position:]
814+
parts.append(string[position:])
823815
break
824-
result += string[position:index]
816+
parts.append(string[position:index])
825817
match = re.match(re.escape(pattern), string[index:])
826-
result += replacer(match)
818+
parts.append(replacer(match))
827819
position = index + len(pattern)
828820
count += 1
829-
return result
821+
return ''.join(parts)
830822
else:
831823
# Use regex for pattern objects
832824
if limit is None:

src/jsonata/tokenizer.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
from jsonata import jexception, utils
3434

35+
_NUMBER_PATTERN = re.compile(r"^-?(0|([1-9][0-9]*))(\.[0-9]+)?([Ee][-+]?[0-9]+)?")
36+
3537

3638
class Tokenizer:
3739
operators = {
@@ -264,8 +266,7 @@ def next(self, prefix: bool) -> Optional[Token]:
264266
self.position += 1
265267
raise jexception.JException("S0101", self.position)
266268
# test for numbers
267-
numregex = re.compile("^-?(0|([1-9][0-9]*))(\\.[0-9]+)?([Ee][-+]?[0-9]+)?")
268-
match_ = numregex.search(self.path[self.position:])
269+
match_ = _NUMBER_PATTERN.search(self.path[self.position:])
269270
if match_ is not None:
270271
num = float(match_.group(0))
271272
if not math.isnan(num) and math.isfinite(num):

0 commit comments

Comments
 (0)