blueloveTH 1 an în urmă
părinte
comite
04229f438f

+ 4 - 1
include/pocketpy/pocketpy.h

@@ -172,7 +172,7 @@ py_i64 py_toint(py_Ref);
 /// Convert a `float` object in python to `double`.
 py_f64 py_tofloat(py_Ref);
 /// Cast a `int` or `float` object in python to `double`.
-/// If successful, returns true and set the value to `out`.
+/// If successful, return true and set the value to `out`.
 /// Otherwise, return false and raise `TypeError`.
 bool py_castfloat(py_Ref, py_f64* out) PY_RAISE;
 /// Convert a `bool` object in python to `bool`.
@@ -203,6 +203,9 @@ void* py_touserdata(py_Ref);
 
 /// Get the type of the object.
 py_Type py_typeof(py_Ref self);
+/// Get type by module and name. e.g. `py_gettype("time", "struct_time")`.
+/// Return `0` if not found.
+py_Type py_gettype(const char* module, py_Name name);
 /// Check if the object is exactly the given type.
 bool py_istype(py_Ref, py_Type);
 /// Check if the object is an instance of the given type.

+ 46 - 62
python/datetime.py

@@ -1,4 +1,5 @@
 from time import localtime
+import operator
 
 class timedelta:
     def __init__(self, days=0, seconds=0):
@@ -13,25 +14,10 @@ class timedelta:
             return NotImplemented
         return (self.days, self.seconds) == (other.days, other.seconds)
 
-    def __lt__(self, other: 'timedelta') -> bool:
+    def __ne__(self, other: 'timedelta') -> bool:
         if type(other) is not timedelta:
             return NotImplemented
-        return (self.days, self.seconds) < (other.days, other.seconds)
-
-    def __le__(self, other: 'timedelta') -> bool:
-        if type(other) is not timedelta:
-            return NotImplemented
-        return (self.days, self.seconds) <= (other.days, other.seconds)
-
-    def __gt__(self, other: 'timedelta') -> bool:
-        if type(other) is not timedelta:
-            return NotImplemented
-        return (self.days, self.seconds) > (other.days, other.seconds)
-
-    def __ge__(self, other: 'timedelta') -> bool:
-        if type(other) is not timedelta:
-            return NotImplemented
-        return (self.days, self.seconds) >= (other.days, other.seconds)
+        return (self.days, self.seconds) != (other.days, other.seconds)
 
 
 class date:
@@ -44,31 +30,33 @@ class date:
     def today():
         t = localtime()
         return date(t.tm_year, t.tm_mon, t.tm_mday)
+    
+    def __cmp(self, other, op):
+        if not isinstance(other, date):
+            return NotImplemented
+        if self.year != other.year:
+            return op(self.year, other.year)
+        if self.month != other.month:
+            return op(self.month, other.month)
+        return op(self.day, other.day)
 
     def __eq__(self, other: 'date') -> bool:
-        if type(other) is not date:
-            return NotImplemented
-        return (self.year, self.month, self.day) == (other.year, other.month, other.day)
+        return self.__cmp(other, operator.eq)
+    
+    def __ne__(self, other: 'date') -> bool:
+        return self.__cmp(other, operator.ne)
 
     def __lt__(self, other: 'date') -> bool:
-        if type(other) is not date:
-            return NotImplemented
-        return (self.year, self.month, self.day) < (other.year, other.month, other.day)
+        return self.__cmp(other, operator.lt)
 
     def __le__(self, other: 'date') -> bool:
-        if type(other) is not date:
-            return NotImplemented
-        return (self.year, self.month, self.day) <= (other.year, other.month, other.day)
+        return self.__cmp(other, operator.le)
 
     def __gt__(self, other: 'date') -> bool:
-        if type(other) is not date:
-            return NotImplemented
-        return (self.year, self.month, self.day) > (other.year, other.month, other.day)
+        return self.__cmp(other, operator.gt)
 
     def __ge__(self, other: 'date') -> bool:
-        if type(other) is not date:
-            return NotImplemented
-        return (self.year, self.month, self.day) >= (other.year, other.month, other.day)
+        return self.__cmp(other, operator.ge)
 
     def __str__(self):
         return f"{self.year}-{self.month:02}-{self.day:02}"
@@ -108,41 +96,37 @@ class datetime(date):
     def __repr__(self):
         return f"datetime.datetime({self.year}, {self.month}, {self.day}, {self.hour}, {self.minute}, {self.second})"
 
-    def __eq__(self, other) -> bool:
-        if type(other) is not datetime:
+    def __cmp(self, other, op):
+        if not isinstance(other, datetime):
             return NotImplemented
-        return (self.year, self.month, self.day, self.hour, self.minute, self.second) ==\
-            (other.year, other.month, other.day,
-             other.hour, other.minute, other.second)
+        if self.year != other.year:
+            return op(self.year, other.year)
+        if self.month != other.month:
+            return op(self.month, other.month)
+        if self.day != other.day:
+            return op(self.day, other.day)
+        if self.hour != other.hour:
+            return op(self.hour, other.hour)
+        if self.minute != other.minute:
+            return op(self.minute, other.minute)
+        return op(self.second, other.second)
 
+    def __eq__(self, other) -> bool:
+        return self.__cmp(other, operator.eq)
+    
+    def __ne__(self, other) -> bool:
+        return self.__cmp(other, operator.ne)
+    
     def __lt__(self, other) -> bool:
-        if type(other) is not datetime:
-            return NotImplemented
-        return (self.year, self.month, self.day, self.hour, self.minute, self.second) <\
-            (other.year, other.month, other.day,
-             other.hour, other.minute, other.second)
-
+        return self.__cmp(other, operator.lt)
+    
     def __le__(self, other) -> bool:
-        if type(other) is not datetime:
-            return NotImplemented
-        return (self.year, self.month, self.day, self.hour, self.minute, self.second) <=\
-            (other.year, other.month, other.day,
-             other.hour, other.minute, other.second)
-
+        return self.__cmp(other, operator.le)
+    
     def __gt__(self, other) -> bool:
-        if type(other) is not datetime:
-            return NotImplemented
-        return (self.year, self.month, self.day, self.hour, self.minute, self.second) >\
-            (other.year, other.month, other.day,
-             other.hour, other.minute, other.second)
-
+        return self.__cmp(other, operator.gt)
+    
     def __ge__(self, other) -> bool:
-        if type(other) is not datetime:
-            return NotImplemented
-        return (self.year, self.month, self.day, self.hour, self.minute, self.second) >=\
-            (other.year, other.month, other.day,
-             other.hour, other.minute, other.second)
+        return self.__cmp(other, operator.ge)
 
-    def timestamp(self) -> float:
-        raise NotImplementedError
 

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
src/common/_generated.c


+ 3 - 1
src/interpreter/vm.c

@@ -330,7 +330,9 @@ py_Type pk_newtype(const char* name,
 }
 
 py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*)) {
-    return pk_newtype(name, base, module, dtor, false, false);
+    py_Type type = pk_newtype(name, base, module, dtor, false, false);
+    if(module) py_setdict(module, py_name(name), py_tpobject(type));
+    return type;
 }
 
 static bool

+ 44 - 1
src/modules/time.c

@@ -1,6 +1,6 @@
 #include "pocketpy/pocketpy.h"
+#include "pocketpy/interpreter/vm.h"
 #include "time.h"
-#include <stdint.h>
 
 #define NANOS_PER_SEC 1000000000
 
@@ -51,10 +51,53 @@ static bool time_sleep(int argc, py_Ref argv) {
     return true;
 }
 
+static bool time_localtime(int argc, py_Ref argv) {
+    PY_CHECK_ARGC(0);
+    py_Type tp_struct_time = py_gettype("time", py_name("struct_time"));
+    assert(tp_struct_time);
+    struct tm* ud = py_newobject(py_retval(), tp_struct_time, 0, sizeof(struct tm));
+    time_t t = time(NULL);
+    *ud = *localtime(&t);
+    return true;
+}
+
+#define DEF_STRUCT_TIME__PROPERTY(name, expr)                                                      \
+    static bool struct_time__##name(int argc, py_Ref argv) {                                       \
+        PY_CHECK_ARGC(1);                                                                          \
+        struct tm* tm = py_touserdata(argv);                                                       \
+        py_newint(py_retval(), expr);                                                              \
+        return true;                                                                               \
+    }
+
+DEF_STRUCT_TIME__PROPERTY(tm_year, tm->tm_year + 1900)
+DEF_STRUCT_TIME__PROPERTY(tm_mon, tm->tm_mon + 1)
+DEF_STRUCT_TIME__PROPERTY(tm_mday, tm->tm_mday)
+DEF_STRUCT_TIME__PROPERTY(tm_hour, tm->tm_hour)
+DEF_STRUCT_TIME__PROPERTY(tm_min, tm->tm_min)
+DEF_STRUCT_TIME__PROPERTY(tm_sec, tm->tm_sec)
+DEF_STRUCT_TIME__PROPERTY(tm_wday, (tm->tm_wday + 6) % 7)
+DEF_STRUCT_TIME__PROPERTY(tm_yday, tm->tm_yday + 1)
+DEF_STRUCT_TIME__PROPERTY(tm_isdst, tm->tm_isdst)
+
+#undef DEF_STRUCT_TIME__PROPERTY
+
 void pk__add_module_time() {
     py_Ref mod = py_newmodule("time");
 
+    py_Type tp_struct_time = py_newtype("struct_time", tp_object, mod, NULL);
+
+    py_bindproperty(tp_struct_time, "tm_year", struct_time__tm_year, NULL);
+    py_bindproperty(tp_struct_time, "tm_mon", struct_time__tm_mon, NULL);
+    py_bindproperty(tp_struct_time, "tm_mday", struct_time__tm_mday, NULL);
+    py_bindproperty(tp_struct_time, "tm_hour", struct_time__tm_hour, NULL);
+    py_bindproperty(tp_struct_time, "tm_min", struct_time__tm_min, NULL);
+    py_bindproperty(tp_struct_time, "tm_sec", struct_time__tm_sec, NULL);
+    py_bindproperty(tp_struct_time, "tm_wday", struct_time__tm_wday, NULL);
+    py_bindproperty(tp_struct_time, "tm_yday", struct_time__tm_yday, NULL);
+    py_bindproperty(tp_struct_time, "tm_isdst", struct_time__tm_isdst, NULL);
+
     py_bindfunc(mod, "time", time_time);
     py_bindfunc(mod, "time_ns", time_time_ns);
     py_bindfunc(mod, "sleep", time_sleep);
+    py_bindfunc(mod, "localtime", time_localtime);
 }

+ 9 - 1
src/public/cast.c

@@ -57,4 +57,12 @@ bool py_issubclass(py_Type derived, py_Type base) {
     return false;
 }
 
-py_Type py_typeof(py_Ref self) { return self->type; }
+py_Type py_typeof(py_Ref self) { return self->type; }
+
+py_Type py_gettype(const char* module, py_Name name) {
+    py_Ref mod = py_getmodule(module);
+    if(!mod) return 0;
+    py_Ref object = py_getdict(mod, name);
+    if(object && py_istype(object, tp_type)) return py_totype(object);
+    return 0;
+}

+ 0 - 7
tests/79_datetime.py

@@ -4,11 +4,6 @@ import datetime
 def test_timedelta():
     assert datetime.timedelta(days=1) == datetime.timedelta(days=1)
     assert datetime.timedelta(days=1) != datetime.timedelta(days=2)
-    assert datetime.timedelta(days=1, seconds=1) >= datetime.timedelta(days=1)
-    assert datetime.timedelta(days=0, seconds=1) <= datetime.timedelta(days=1)
-    assert datetime.timedelta(days=1, seconds=1) < datetime.timedelta(days=2)
-    assert datetime.timedelta(days=1, seconds=1) > datetime.timedelta(days=0)
-
 
 def test_date():
     assert datetime.date(2023, 8, 5) == datetime.date(2023, 8, 5)
@@ -18,7 +13,6 @@ def test_date():
     assert datetime.date(2024, 8, 5) > datetime.date(2023, 8, 6)
     assert datetime.date(2023, 8, 5) < datetime.date(2024, 8, 6)
 
-
 def test_datetime():
     assert datetime.datetime(
         2023, 8, 5, 12, 0, 0) == datetime.datetime(2023, 8, 5, 12, 0, 0)
@@ -33,7 +27,6 @@ def test_datetime():
     assert datetime.datetime(
         2023, 8, 5, 12, 0, 0) <= datetime.datetime(2023, 8, 5, 12, 1, 0)
 
-
 test_timedelta()
 test_date()
 test_datetime()

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff