From 9f5a8b4867d325ad855b1c078930f123d285be8d Mon Sep 17 00:00:00 2001 From: Mathias Reitinger Date: Sun, 10 Mar 2024 17:27:19 +0100 Subject: [PATCH] Implement support for __add__ and __sub__ and basic timedelta math --- p5lib/Python2/Internals.pm | 4 ++ .../Type/Object/StdLib/datetime/timedelta.pm | 37 +++++++++++++++++++ .../stdlib-datetime-timedelta-math.py | 14 +++++++ 3 files changed, 55 insertions(+) create mode 100644 t/output-comparison-python-interpreter/stdlib-datetime-timedelta-math.py diff --git a/p5lib/Python2/Internals.pm b/p5lib/Python2/Internals.pm index 31e5fb1..33d8fe2 100644 --- a/p5lib/Python2/Internals.pm +++ b/p5lib/Python2/Internals.pm @@ -128,6 +128,8 @@ my $arithmetic_operations = { '+' => sub { my ($left, $right) = @_; + return $left->__add__($right) if $left->can('__add__'); + if ($left->isa('Python2::Type::Scalar::Num') and ($right->isa('Python2::Type::Scalar::Num'))) { return \Python2::Type::Scalar::Num->new($left->__tonative__ + $right->__tonative__); } @@ -149,6 +151,8 @@ my $arithmetic_operations = { '-' => sub { my ($left, $right) = @_; + return $left->__sub__($right) if $left->can('__add__'); + $left = $left->__tonative__; $right = $right->__tonative__; diff --git a/p5lib/Python2/Type/Object/StdLib/datetime/timedelta.pm b/p5lib/Python2/Type/Object/StdLib/datetime/timedelta.pm index b410e29..5108cb2 100644 --- a/p5lib/Python2/Type/Object/StdLib/datetime/timedelta.pm +++ b/p5lib/Python2/Type/Object/StdLib/datetime/timedelta.pm @@ -13,6 +13,17 @@ use Scalar::Util::Numeric qw(isfloat); sub new { bless({}, shift); } +sub new_from_duration { + my ($self, $duration) = @_; + + die Python2::Type::Exception->new('TypeError', 'new_from_duration() expects a DateTime::Duration object, got ' . ref($duration)) + unless ref($duration) eq 'DateTime::Duration'; + + return \bless({ + duration => $duration + }, ref($self)); +} + sub __call__ { my $self = shift; my $named_arguments = pop; @@ -103,4 +114,30 @@ sub __print__ { return sprintf("%s:%s:%s", $h, $m, $s); } +sub __tonative__ { shift->{duration} } + +sub __add__ { + my ($self, $other) = @_; + + die Python2::Type::Exception->new('TypeError', 'Unsupported type for addition to timedelta: ' . $other->__type__ . ', expected timedelta.') + unless ref($other) eq ref($self); + + return $self->new_from_duration( + $self->__tonative__ + $other->__tonative__ + ); +} + +sub __sub__ { + my ($self, $other) = @_; + + die Python2::Type::Exception->new('TypeError', 'Unsupported type for subtraction to timedelta: ' . $other->__type__ . ', expected timedelta.') + unless ref($other) eq ref($self); + + return $self->new_from_duration( + $self->__tonative__ - $other->__tonative__ + ); +} + + + 1; \ No newline at end of file diff --git a/t/output-comparison-python-interpreter/stdlib-datetime-timedelta-math.py b/t/output-comparison-python-interpreter/stdlib-datetime-timedelta-math.py new file mode 100644 index 0000000..68e6786 --- /dev/null +++ b/t/output-comparison-python-interpreter/stdlib-datetime-timedelta-math.py @@ -0,0 +1,14 @@ +from datetime import timedelta + +print(timedelta(1) + timedelta(2)) +print(timedelta(2) - timedelta(1)) + +try: + timedelta(1) + 'a' +except TypeError: + print "timedelta addition with invalid type raises TypeError, as expected." + +try: + timedelta(1) - 'a' +except TypeError: + print "timedelta subtraction with invalid type raises TypeError, as expected."