diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index af2bdf9e..2e8b58e7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -51,7 +51,7 @@ jobs: - name: Install dependencies run: | source $HOME/.poetry/env - poetry install + poetry install -vvv - name: Test Pure Python run: | source $HOME/.poetry/env @@ -67,7 +67,7 @@ jobs: runs-on: macos-latest strategy: matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8, pypy2, pypy3] + python-version: [2.7, 3.5, 3.6, 3.7, 3.8, pypy3] steps: - uses: actions/checkout@v2 @@ -97,7 +97,7 @@ jobs: - name: Install dependencies run: | source $HOME/.poetry/env - poetry install + poetry install -vvv - name: Test Pure Python run: | source $HOME/.poetry/env @@ -142,7 +142,7 @@ jobs: - name: Install dependencies run: | $env:Path += ";$env:Userprofile\.poetry\bin" - poetry install + poetry install -vvv - name: Test Pure Python run: | $env:Path += ";$env:Userprofile\.poetry\bin" diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bb58a3e..02f24801 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## [2.1.2] - 2020-07-24 + +### Fixed + +- Fixed errors when trying to build Pendulum from source ([#489](https://github.com/sdispater/pendulum/pull/489)). + + ## [2.1.1] - 2020-07-13 ### Fixed @@ -143,7 +150,8 @@ -[Unreleased]: https://github.com/sdispater/pendulum/compare/2.1.1...master +[Unreleased]: https://github.com/sdispater/pendulum/compare/2.1.2...master +[2.1.2]: https://github.com/sdispater/pendulum/releases/tag/2.1.2 [2.1.1]: https://github.com/sdispater/pendulum/releases/tag/2.1.1 [2.1.0]: https://github.com/sdispater/pendulum/releases/tag/2.1.0 [2.0.5]: https://github.com/sdispater/pendulum/releases/tag/2.0.5 diff --git a/build.py b/build.py index cf561260..885b1c3b 100644 --- a/build.py +++ b/build.py @@ -1,7 +1,9 @@ import os +import shutil import sys from distutils.command.build_ext import build_ext +from distutils.core import Distribution from distutils.core import Extension from distutils.errors import CCompilerError from distutils.errors import DistutilsExecError @@ -33,27 +35,53 @@ class BuildFailed(Exception): class ExtBuilder(build_ext): # This class allows C extension building to fail. + built_extensions = [] + def run(self): try: build_ext.run(self) except (DistutilsPlatformError, FileNotFoundError): - print("************************************************************") - print("Cannot compile C accelerator module, use pure python version") - print("************************************************************") + print( + " Unable to build the C extensions, " + "Pendulum will use the pure python code instead." + ) def build_extension(self, ext): try: build_ext.build_extension(self, ext) except (CCompilerError, DistutilsExecError, DistutilsPlatformError, ValueError): - print("************************************************************") - print("Cannot compile C accelerator module, use pure python version") - print("************************************************************") + print( + ' Unable to build the "{}" C extension, ' + "Pendulum will use the pure python version of the extension.".format( + ext.name + ) + ) def build(setup_kwargs): """ This function is mandatory in order to build the extensions. """ - setup_kwargs.update( - {"ext_modules": extensions, "cmdclass": {"build_ext": ExtBuilder}} - ) + distribution = Distribution({"name": "pendulum", "ext_modules": extensions}) + distribution.package_dir = "pendulum" + + cmd = ExtBuilder(distribution) + cmd.ensure_finalized() + cmd.run() + + # Copy built extensions back to the project + for output in cmd.get_outputs(): + relative_extension = os.path.relpath(output, cmd.build_lib) + if not os.path.exists(output): + continue + + shutil.copyfile(output, relative_extension) + mode = os.stat(relative_extension).st_mode + mode |= (mode & 0o444) >> 2 + os.chmod(relative_extension, mode) + + return setup_kwargs + + +if __name__ == "__main__": + build({}) diff --git a/pendulum/__version__.py b/pendulum/__version__.py index 58039f50..4eabd0b3 100644 --- a/pendulum/__version__.py +++ b/pendulum/__version__.py @@ -1 +1 @@ -__version__ = "2.1.1" +__version__ = "2.1.2" diff --git a/pendulum/_extensions/_helpers.c b/pendulum/_extensions/_helpers.c index e6b926b7..b9310f25 100644 --- a/pendulum/_extensions/_helpers.c +++ b/pendulum/_extensions/_helpers.c @@ -30,41 +30,35 @@ // do not begin with a leap year and those that do respectively. const int64_t SECS_PER_100_YEARS[2] = { (uint64_t)(76L * DAYS_PER_N_YEAR + 24L * DAYS_PER_L_YEAR) * SECS_PER_DAY, - (uint64_t)(75L * DAYS_PER_N_YEAR + 25L * DAYS_PER_L_YEAR) * SECS_PER_DAY -}; + (uint64_t)(75L * DAYS_PER_N_YEAR + 25L * DAYS_PER_L_YEAR) * SECS_PER_DAY}; // The number of seconds in an aligned 4-year chunk, for those that // do not begin with a leap year and those that do respectively. const int32_t SECS_PER_4_YEARS[2] = { (4 * DAYS_PER_N_YEAR + 0 * DAYS_PER_L_YEAR) * SECS_PER_DAY, - (3 * DAYS_PER_N_YEAR + 1 * DAYS_PER_L_YEAR) * SECS_PER_DAY -}; + (3 * DAYS_PER_N_YEAR + 1 * DAYS_PER_L_YEAR) * SECS_PER_DAY}; // The number of seconds in non-leap and leap years respectively. const int32_t SECS_PER_YEAR[2] = { DAYS_PER_N_YEAR * SECS_PER_DAY, - DAYS_PER_L_YEAR * SECS_PER_DAY -}; + DAYS_PER_L_YEAR *SECS_PER_DAY}; #define MONTHS_PER_YEAR 12 // The month lengths in non-leap and leap years respectively. const int32_t DAYS_PER_MONTHS[2][13] = { {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {-1, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} -}; + {-1, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; // The day offsets of the beginning of each (1-based) month in non-leap // and leap years respectively. // For example, in a leap year there are 335 days before December. const int32_t MONTHS_OFFSETS[2][14] = { {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, - {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} -}; + {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}}; const int DAY_OF_WEEK_TABLE[12] = { - 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 -}; + 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; #define TM_SUNDAY 0 #define TM_MONDAY 1 @@ -89,19 +83,23 @@ const int DAY_OF_WEEK_TABLE[12] = { /* ------------------------------------------------------------------------- */ -int _p(int y) { - return y + y/4 - y/100 + y /400; +int _p(int y) +{ + return y + y / 4 - y / 100 + y / 400; } -int _is_leap(int year) { +int _is_leap(int year) +{ return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); } -int _is_long_year(int year) { +int _is_long_year(int year) +{ return (_p(year) % 7 == 4) || (_p(year - 1) % 7 == 3); } -int _week_day(int year, int month, int day) { +int _week_day(int year, int month, int day) +{ int y; int w; @@ -109,71 +107,75 @@ int _week_day(int year, int month, int day) { w = (_p(y) + DAY_OF_WEEK_TABLE[month - 1] + day) % 7; - if (!w) { + if (!w) + { w = 7; } return w; } -int _days_in_year(int year) { - if (_is_leap(year)) { +int _days_in_year(int year) +{ + if (_is_leap(year)) + { return DAYS_PER_L_YEAR; } return DAYS_PER_N_YEAR; } -int _day_number(int year, int month, int day) { +int _day_number(int year, int month, int day) +{ month = (month + 9) % 12; year = year - month / 10; return ( - 365 * year - + year / 4 - year / 100 + year / 400 - + (month * 306 + 5) / 10 - + (day - 1) - ); + 365 * year + year / 4 - year / 100 + year / 400 + (month * 306 + 5) / 10 + (day - 1)); } -int _get_offset(PyObject *dt) { +int _get_offset(PyObject *dt) +{ PyObject *tzinfo; PyObject *offset; tzinfo = ((PyDateTime_DateTime *)(dt))->tzinfo; - if (tzinfo != Py_None) { + if (tzinfo != Py_None) + { offset = PyObject_CallMethod(tzinfo, "utcoffset", "O", dt); - return - PyDateTime_DELTA_GET_DAYS(offset) * SECS_PER_DAY - + PyDateTime_DELTA_GET_SECONDS(offset); + return PyDateTime_DELTA_GET_DAYS(offset) * SECS_PER_DAY + PyDateTime_DELTA_GET_SECONDS(offset); } return 0; } -int _has_tzinfo(PyObject *dt) { +int _has_tzinfo(PyObject *dt) +{ return ((_PyDateTime_BaseTZInfo *)(dt))->hastzinfo; } -char* _get_tz_name(PyObject *dt) { +char *_get_tz_name(PyObject *dt) +{ PyObject *tzinfo; char *tz = ""; tzinfo = ((PyDateTime_DateTime *)(dt))->tzinfo; - if (tzinfo != Py_None) { - if (PyObject_HasAttrString(tzinfo, "name")) { + if (tzinfo != Py_None) + { + if (PyObject_HasAttrString(tzinfo, "name")) + { // Pendulum timezone - tz = PyUnicode_AsUTF8( - PyObject_GetAttrString(tzinfo, "name") - ); - } else if (PyObject_HasAttrString(tzinfo, "zone")) { + tz = (char *)PyUnicode_AsUTF8( + PyObject_GetAttrString(tzinfo, "name")); + } + else if (PyObject_HasAttrString(tzinfo, "zone")) + { // pytz timezone - tz = PyUnicode_AsUTF8( - PyObject_GetAttrString(tzinfo, "zone") - ); + tz = (char *)PyUnicode_AsUTF8( + PyObject_GetAttrString(tzinfo, "zone")); } } @@ -185,9 +187,9 @@ char* _get_tz_name(PyObject *dt) { /* * class Diff(): */ -typedef struct { - PyObject_HEAD - int years; +typedef struct +{ + PyObject_HEAD int years; int months; int days; int hours; @@ -202,7 +204,8 @@ typedef struct { * self.years = years * # ... */ -static int Diff_init(Diff *self, PyObject *args, PyObject *kwargs) { +static int Diff_init(Diff *self, PyObject *args, PyObject *kwargs) +{ int years; int months; int days; @@ -233,7 +236,8 @@ static int Diff_init(Diff *self, PyObject *args, PyObject *kwargs) { * self.years, self.months, self.days, self.minutes, self.hours, self.seconds, self.microseconds * ) */ -static PyObject *Diff_repr(Diff *self) { +static PyObject *Diff_repr(Diff *self) +{ char repr[82] = {0}; sprintf( @@ -245,8 +249,7 @@ static PyObject *Diff_repr(Diff *self) { self->hours, self->minutes, self->seconds, - self->microseconds - ); + self->microseconds); return PyUnicode_FromString(repr); } @@ -256,10 +259,12 @@ static PyObject *Diff_repr(Diff *self) { * Skip overhead of calling PyObject_New and PyObject_Init. * Directly allocate object. */ -static PyObject *new_diff_ex(int years, int months, int days, int hours, int minutes, int seconds, int microseconds, int total_days, PyTypeObject *type) { - Diff *self = (Diff *) (type->tp_alloc(type, 0)); +static PyObject *new_diff_ex(int years, int months, int days, int hours, int minutes, int seconds, int microseconds, int total_days, PyTypeObject *type) +{ + Diff *self = (Diff *)(type->tp_alloc(type, 0)); - if (self != NULL) { + if (self != NULL) + { self->years = years; self->months = months; self->days = days; @@ -270,7 +275,7 @@ static PyObject *new_diff_ex(int years, int months, int days, int hours, int min self->total_days = total_days; } - return (PyObject *) self; + return (PyObject *)self; } /* @@ -285,46 +290,44 @@ static PyMemberDef Diff_members[] = { {"seconds", T_INT, offsetof(Diff, seconds), 0, "seconds in diff"}, {"microseconds", T_INT, offsetof(Diff, microseconds), 0, "microseconds in diff"}, {"total_days", T_INT, offsetof(Diff, total_days), 0, "total days in diff"}, - {NULL} -}; + {NULL}}; static PyTypeObject Diff_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "PreciseDiff", /* tp_name */ - sizeof(Diff), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)Diff_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)Diff_repr, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - "Precise difference between two datetime objects", /* tp_doc */ + PyVarObject_HEAD_INIT(NULL, 0) "PreciseDiff", /* tp_name */ + sizeof(Diff), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_as_async */ + (reprfunc)Diff_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc)Diff_repr, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Precise difference between two datetime objects", /* tp_doc */ }; #define new_diff(years, months, days, hours, minutes, seconds, microseconds, total_days) new_diff_ex(years, months, days, hours, minutes, seconds, microseconds, total_days, &Diff_type) - /* -------------------------- Functions --------------------------*/ -PyObject* is_leap(PyObject *self, PyObject *args) { +PyObject *is_leap(PyObject *self, PyObject *args) +{ PyObject *leap; int year; - if (!PyArg_ParseTuple(args, "i", &year)) { + if (!PyArg_ParseTuple(args, "i", &year)) + { PyErr_SetString( - PyExc_ValueError, "Invalid parameters" - ); + PyExc_ValueError, "Invalid parameters"); return NULL; } @@ -333,14 +336,15 @@ PyObject* is_leap(PyObject *self, PyObject *args) { return leap; } -PyObject* is_long_year(PyObject *self, PyObject *args) { +PyObject *is_long_year(PyObject *self, PyObject *args) +{ PyObject *is_long; int year; - if (!PyArg_ParseTuple(args, "i", &year)) { + if (!PyArg_ParseTuple(args, "i", &year)) + { PyErr_SetString( - PyExc_ValueError, "Invalid parameters" - ); + PyExc_ValueError, "Invalid parameters"); return NULL; } @@ -349,16 +353,17 @@ PyObject* is_long_year(PyObject *self, PyObject *args) { return is_long; } -PyObject* week_day(PyObject *self, PyObject *args) { +PyObject *week_day(PyObject *self, PyObject *args) +{ PyObject *wd; int year; int month; int day; - if (!PyArg_ParseTuple(args, "iii", &year, &month, &day)) { + if (!PyArg_ParseTuple(args, "iii", &year, &month, &day)) + { PyErr_SetString( - PyExc_ValueError, "Invalid parameters" - ); + PyExc_ValueError, "Invalid parameters"); return NULL; } @@ -367,14 +372,15 @@ PyObject* week_day(PyObject *self, PyObject *args) { return wd; } -PyObject* days_in_year(PyObject *self, PyObject *args) { +PyObject *days_in_year(PyObject *self, PyObject *args) +{ PyObject *ndays; int year; - if (!PyArg_ParseTuple(args, "i", &year)) { + if (!PyArg_ParseTuple(args, "i", &year)) + { PyErr_SetString( - PyExc_ValueError, "Invalid parameters" - ); + PyExc_ValueError, "Invalid parameters"); return NULL; } @@ -383,18 +389,19 @@ PyObject* days_in_year(PyObject *self, PyObject *args) { return ndays; } -PyObject* timestamp(PyObject *self, PyObject *args) { +PyObject *timestamp(PyObject *self, PyObject *args) +{ int64_t result; - PyObject* dt; + PyObject *dt; - if (!PyArg_ParseTuple(args, "O", &dt)) { + if (!PyArg_ParseTuple(args, "O", &dt)) + { PyErr_SetString( - PyExc_ValueError, "Invalid parameters" - ); + PyExc_ValueError, "Invalid parameters"); return NULL; } - int year = (double) PyDateTime_GET_YEAR(dt); + int year = (double)PyDateTime_GET_YEAR(dt); int month = PyDateTime_GET_MONTH(dt); int day = PyDateTime_GET_DAY(dt); int hour = PyDateTime_DATE_GET_HOUR(dt); @@ -402,11 +409,12 @@ PyObject* timestamp(PyObject *self, PyObject *args) { int second = PyDateTime_DATE_GET_SECOND(dt); result = (year - 1970) * 365 + MONTHS_OFFSETS[0][month]; - result += (int) floor((double) (year - 1968) / 4); + result += (int)floor((double)(year - 1968) / 4); result -= (year - 1900) / 100; result += (year - 1600) / 400; - if (_is_leap(year) && month < 3) { + if (_is_leap(year) && month < 3) + { result -= 1; } @@ -421,7 +429,8 @@ PyObject* timestamp(PyObject *self, PyObject *args) { return PyLong_FromSsize_t(result); } -PyObject* local_time(PyObject *self, PyObject *args) { +PyObject *local_time(PyObject *self, PyObject *args) +{ double unix_time; int32_t utc_offset; int32_t year; @@ -438,23 +447,26 @@ PyObject* local_time(PyObject *self, PyObject *args) { int32_t minute; int32_t second; - if (!PyArg_ParseTuple(args, "dii", &unix_time, &utc_offset, µsecond)) { + if (!PyArg_ParseTuple(args, "dii", &unix_time, &utc_offset, µsecond)) + { PyErr_SetString( - PyExc_ValueError, "Invalid parameters" - ); + PyExc_ValueError, "Invalid parameters"); return NULL; } year = EPOCH_YEAR; - seconds = (int64_t) floor(unix_time); + seconds = (int64_t)floor(unix_time); // Shift to a base year that is 400-year aligned. - if (seconds >= 0) { + if (seconds >= 0) + { seconds -= 10957L * SECS_PER_DAY; - year += 30; // == 2000; - } else { + year += 30; // == 2000; + } + else + { seconds += (int64_t)(146097L - 10957L) * SECS_PER_DAY; - year -= 370; // == 1600; + year -= 370; // == 1600; } seconds += utc_offset; @@ -462,35 +474,39 @@ PyObject* local_time(PyObject *self, PyObject *args) { // Handle years in chunks of 400/100/4/1 year += 400 * (seconds / SECS_PER_400_YEARS); seconds %= SECS_PER_400_YEARS; - if (seconds < 0) { + if (seconds < 0) + { seconds += SECS_PER_400_YEARS; year -= 400; } - leap_year = 1; // 4-century aligned + leap_year = 1; // 4-century aligned sec_per_100years = SECS_PER_100_YEARS[leap_year]; - while (seconds >= sec_per_100years) { + while (seconds >= sec_per_100years) + { seconds -= sec_per_100years; year += 100; - leap_year = 0; // 1-century, non 4-century aligned + leap_year = 0; // 1-century, non 4-century aligned sec_per_100years = SECS_PER_100_YEARS[leap_year]; } sec_per_4years = SECS_PER_4_YEARS[leap_year]; - while (seconds >= sec_per_4years) { + while (seconds >= sec_per_4years) + { seconds -= sec_per_4years; year += 4; - leap_year = 1; // 4-year, non century aligned + leap_year = 1; // 4-year, non century aligned sec_per_4years = SECS_PER_4_YEARS[leap_year]; } sec_per_year = SECS_PER_YEAR[leap_year]; - while (seconds >= sec_per_year) { + while (seconds >= sec_per_year) + { seconds -= sec_per_year; year += 1; - leap_year = 0; // non 4-year aligned + leap_year = 0; // non 4-year aligned sec_per_year = SECS_PER_YEAR[leap_year]; } @@ -498,9 +514,11 @@ PyObject* local_time(PyObject *self, PyObject *args) { month = TM_DECEMBER + 1; day = seconds / SECS_PER_DAY + 1; seconds %= SECS_PER_DAY; - while (month != TM_JANUARY + 1) { + while (month != TM_JANUARY + 1) + { month_offset = MONTHS_OFFSETS[leap_year][month]; - if (day > month_offset) { + if (day > month_offset) + { day -= month_offset; break; } @@ -515,26 +533,25 @@ PyObject* local_time(PyObject *self, PyObject *args) { second = seconds % SECS_PER_MIN; return Py_BuildValue("NNNNNNN", - PyLong_FromLong(year), - PyLong_FromLong(month), - PyLong_FromLong(day), - PyLong_FromLong(hour), - PyLong_FromLong(minute), - PyLong_FromLong(second), - PyLong_FromLong(microsecond) - ); + PyLong_FromLong(year), + PyLong_FromLong(month), + PyLong_FromLong(day), + PyLong_FromLong(hour), + PyLong_FromLong(minute), + PyLong_FromLong(second), + PyLong_FromLong(microsecond)); } - // Calculate a precise difference between two datetimes. -PyObject* precise_diff(PyObject *self, PyObject *args) { - PyObject* dt1; - PyObject* dt2; +PyObject *precise_diff(PyObject *self, PyObject *args) +{ + PyObject *dt1; + PyObject *dt2; - if (!PyArg_ParseTuple(args, "OO", &dt1, &dt2)) { + if (!PyArg_ParseTuple(args, "OO", &dt1, &dt2)) + { PyErr_SetString( - PyExc_ValueError, "Invalid parameters" - ); + PyExc_ValueError, "Invalid parameters"); return NULL; } @@ -574,20 +591,20 @@ PyObject* precise_diff(PyObject *self, PyObject *args) { char *tz1 = ""; char *tz2 = ""; int in_same_tz = 0; - int total_days = ( - _day_number(dt2_year, dt2_month, dt2_day) - - _day_number(dt1_year, dt1_month, dt1_day) - ); + int total_days = (_day_number(dt2_year, dt2_month, dt2_day) - _day_number(dt1_year, dt1_month, dt1_day)); // If both dates are datetimes, we check // If we are in the same timezone - if (dt1_is_datetime && dt2_is_datetime) { - if (_has_tzinfo(dt1)) { + if (dt1_is_datetime && dt2_is_datetime) + { + if (_has_tzinfo(dt1)) + { tz1 = _get_tz_name(dt1); dt1_offset = _get_offset(dt1); } - if (_has_tzinfo(dt2)) { + if (_has_tzinfo(dt2)) + { tz2 = _get_tz_name(dt2); dt2_offset = _get_offset(dt2); } @@ -597,123 +614,117 @@ PyObject* precise_diff(PyObject *self, PyObject *args) { // If we have datetimes (and not only dates) // we get the information we need - if (dt1_is_datetime) { + if (dt1_is_datetime) + { dt1_hour = PyDateTime_DATE_GET_HOUR(dt1); dt1_minute = PyDateTime_DATE_GET_MINUTE(dt1); dt1_second = PyDateTime_DATE_GET_SECOND(dt1); dt1_microsecond = PyDateTime_DATE_GET_MICROSECOND(dt1); - if ((!in_same_tz && dt1_offset != 0) || total_days == 0) { + if ((!in_same_tz && dt1_offset != 0) || total_days == 0) + { dt1_hour -= dt1_offset / SECS_PER_HOUR; dt1_offset %= SECS_PER_HOUR; dt1_minute -= dt1_offset / SECS_PER_MIN; dt1_offset %= SECS_PER_MIN; dt1_second -= dt1_offset; - if (dt1_second < 0) { + if (dt1_second < 0) + { dt1_second += 60; dt1_minute -= 1; - } else if (dt1_second > 60) { + } + else if (dt1_second > 60) + { dt1_second -= 60; dt1_minute += 1; } - if (dt1_minute < 0) { + if (dt1_minute < 0) + { dt1_minute += 60; dt1_hour -= 1; - } else if (dt1_minute > 60) { + } + else if (dt1_minute > 60) + { dt1_minute -= 60; dt1_hour += 1; } - if (dt1_hour < 0) { + if (dt1_hour < 0) + { dt1_hour += 24; dt1_day -= 1; - } else if (dt1_hour > 24) { + } + else if (dt1_hour > 24) + { dt1_hour -= 24; dt1_day += 1; } } - dt1_total_seconds = ( - dt1_hour * SECS_PER_HOUR - + dt1_minute * SECS_PER_MIN - + dt1_second - ); + dt1_total_seconds = (dt1_hour * SECS_PER_HOUR + dt1_minute * SECS_PER_MIN + dt1_second); } - if (dt2_is_datetime) { + if (dt2_is_datetime) + { dt2_hour = PyDateTime_DATE_GET_HOUR(dt2); dt2_minute = PyDateTime_DATE_GET_MINUTE(dt2); dt2_second = PyDateTime_DATE_GET_SECOND(dt2); dt2_microsecond = PyDateTime_DATE_GET_MICROSECOND(dt2); - if ((!in_same_tz && dt2_offset != 0) || total_days == 0) { + if ((!in_same_tz && dt2_offset != 0) || total_days == 0) + { dt2_hour -= dt2_offset / SECS_PER_HOUR; dt2_offset %= SECS_PER_HOUR; dt2_minute -= dt2_offset / SECS_PER_MIN; dt2_offset %= SECS_PER_MIN; dt2_second -= dt2_offset; - if (dt2_second < 0) { + if (dt2_second < 0) + { dt2_second += 60; dt2_minute -= 1; - } else if (dt2_second > 60) { + } + else if (dt2_second > 60) + { dt2_second -= 60; dt2_minute += 1; } - if (dt2_minute < 0) { + if (dt2_minute < 0) + { dt2_minute += 60; dt2_hour -= 1; - } else if (dt2_minute > 60) { + } + else if (dt2_minute > 60) + { dt2_minute -= 60; dt2_hour += 1; } - if (dt2_hour < 0) { + if (dt2_hour < 0) + { dt2_hour += 24; dt2_day -= 1; - } else if (dt2_hour > 24) { + } + else if (dt2_hour > 24) + { dt2_hour -= 24; dt2_day += 1; } } - dt2_total_seconds = ( - dt2_hour * SECS_PER_HOUR - + dt2_minute * SECS_PER_MIN - + dt2_second - ); + dt2_total_seconds = (dt2_hour * SECS_PER_HOUR + dt2_minute * SECS_PER_MIN + dt2_second); } // Direct comparison between two datetimes does not work // so we need to check by properties - int dt1_gt_dt2 = ( - dt1_year > dt2_year - || (dt1_year == dt2_year && dt1_month > dt2_month) - || ( - dt1_year == dt2_year - && dt1_month == dt2_month - && dt1_day > dt2_day - ) - || ( - dt1_year == dt2_year - && dt1_month == dt2_month - && dt1_day == dt2_day - && dt1_total_seconds > dt2_total_seconds - ) - || ( - dt1_year == dt2_year - && dt1_month == dt2_month - && dt1_day == dt2_day - && dt1_total_seconds == dt2_total_seconds - && dt1_microsecond > dt2_microsecond - ) - ); - - if (dt1_gt_dt2) { - PyObject* temp; + int dt1_gt_dt2 = (dt1_year > dt2_year || (dt1_year == dt2_year && dt1_month > dt2_month) || (dt1_year == dt2_year && dt1_month == dt2_month && dt1_day > dt2_day) || (dt1_year == dt2_year && dt1_month == dt2_month && dt1_day == dt2_day && dt1_total_seconds > dt2_total_seconds) || (dt1_year == dt2_year && dt1_month == dt2_month && dt1_day == dt2_day && dt1_total_seconds == dt2_total_seconds && dt1_microsecond > dt2_microsecond)); + + if (dt1_gt_dt2) + { + PyObject *temp; temp = dt1; dt1 = dt2; dt2 = temp; @@ -727,24 +738,23 @@ PyObject* precise_diff(PyObject *self, PyObject *args) { dt1_day = PyDateTime_GET_DAY(dt1); dt2_day = PyDateTime_GET_DAY(dt2); - if (dt2_is_datetime) { + if (dt2_is_datetime) + { dt1_hour = PyDateTime_DATE_GET_HOUR(dt1); dt1_minute = PyDateTime_DATE_GET_MINUTE(dt1); dt1_second = PyDateTime_DATE_GET_SECOND(dt1); dt1_microsecond = PyDateTime_DATE_GET_MICROSECOND(dt1); } - if (dt1_is_datetime) { + if (dt1_is_datetime) + { dt2_hour = PyDateTime_DATE_GET_HOUR(dt2); dt2_minute = PyDateTime_DATE_GET_MINUTE(dt2); dt2_second = PyDateTime_DATE_GET_SECOND(dt2); dt2_microsecond = PyDateTime_DATE_GET_MICROSECOND(dt2); } - total_days = ( - _day_number(dt2_year, dt2_month, dt2_day) - - _day_number(dt1_year, dt1_month, dt1_day) - ); + total_days = (_day_number(dt2_year, dt2_month, dt2_day) - _day_number(dt1_year, dt1_month, dt1_day)); } year_diff = dt2_year - dt1_year; @@ -755,36 +765,44 @@ PyObject* precise_diff(PyObject *self, PyObject *args) { second_diff = dt2_second - dt1_second; microsecond_diff = dt2_microsecond - dt1_microsecond; - if (microsecond_diff < 0) { + if (microsecond_diff < 0) + { microsecond_diff += 1e6; second_diff -= 1; } - if (second_diff < 0) { + if (second_diff < 0) + { second_diff += 60; minute_diff -= 1; } - if (minute_diff < 0) { + if (minute_diff < 0) + { minute_diff += 60; hour_diff -= 1; } - if (hour_diff < 0) { + if (hour_diff < 0) + { hour_diff += 24; day_diff -= 1; } - if (day_diff < 0) { + if (day_diff < 0) + { // If we have a difference in days, // we have to check if they represent months year = dt2_year; month = dt2_month; - if (month == 1) { + if (month == 1) + { month = 12; year -= 1; - } else { + } + else + { month -= 1; } @@ -793,20 +811,28 @@ PyObject* precise_diff(PyObject *self, PyObject *args) { days_in_last_month = DAYS_PER_MONTHS[leap][month]; days_in_month = DAYS_PER_MONTHS[_is_leap(dt2_year)][dt2_month]; - if (day_diff < days_in_month - days_in_last_month) { + if (day_diff < days_in_month - days_in_last_month) + { // We don't have a full month, we calculate days - if (days_in_last_month < dt1_day) { + if (days_in_last_month < dt1_day) + { day_diff += dt1_day; - } else { + } + else + { day_diff += days_in_last_month; } - } else if (day_diff == days_in_month - days_in_last_month) { + } + else if (day_diff == days_in_month - days_in_last_month) + { // We have exactly a full month // We remove the days difference // and add one to the months difference day_diff = 0; month_diff += 1; - } else { + } + else + { // We have a full month day_diff += days_in_last_month; } @@ -814,7 +840,8 @@ PyObject* precise_diff(PyObject *self, PyObject *args) { month_diff -= 1; } - if (month_diff < 0) { + if (month_diff < 0) + { month_diff += 12; year_diff -= 1; } @@ -827,57 +854,41 @@ PyObject* precise_diff(PyObject *self, PyObject *args) { minute_diff * sign, second_diff * sign, microsecond_diff * sign, - total_days * sign - ); + total_days * sign); } /* ------------------------------------------------------------------------- */ static PyMethodDef helpers_methods[] = { - { - "is_leap", - (PyCFunction) is_leap, - METH_VARARGS, - PyDoc_STR("Checks if a year is a leap year.") - }, - { - "is_long_year", - (PyCFunction) is_long_year, - METH_VARARGS, - PyDoc_STR("Checks if a year is a long year.") - }, - { - "week_day", - (PyCFunction) week_day, - METH_VARARGS, - PyDoc_STR("Returns the weekday number.") - }, - { - "days_in_year", - (PyCFunction) days_in_year, - METH_VARARGS, - PyDoc_STR("Returns the number of days in the given year.") - }, - { - "timestamp", - (PyCFunction) timestamp, - METH_VARARGS, - PyDoc_STR("Returns the timestamp of the given datetime.") - }, - { - "local_time", - (PyCFunction) local_time, - METH_VARARGS, - PyDoc_STR("Returns a UNIX time as a broken down time for a particular transition type.") - }, - { - "precise_diff", - (PyCFunction) precise_diff, - METH_VARARGS, - PyDoc_STR("Calculate a precise difference between two datetimes.") - }, - {NULL} -}; + {"is_leap", + (PyCFunction)is_leap, + METH_VARARGS, + PyDoc_STR("Checks if a year is a leap year.")}, + {"is_long_year", + (PyCFunction)is_long_year, + METH_VARARGS, + PyDoc_STR("Checks if a year is a long year.")}, + {"week_day", + (PyCFunction)week_day, + METH_VARARGS, + PyDoc_STR("Returns the weekday number.")}, + {"days_in_year", + (PyCFunction)days_in_year, + METH_VARARGS, + PyDoc_STR("Returns the number of days in the given year.")}, + {"timestamp", + (PyCFunction)timestamp, + METH_VARARGS, + PyDoc_STR("Returns the timestamp of the given datetime.")}, + {"local_time", + (PyCFunction)local_time, + METH_VARARGS, + PyDoc_STR("Returns a UNIX time as a broken down time for a particular transition type.")}, + {"precise_diff", + (PyCFunction)precise_diff, + METH_VARARGS, + PyDoc_STR("Calculate a precise difference between two datetimes.")}, + {NULL}}; /* ------------------------------------------------------------------------- */ diff --git a/pyproject.toml b/pyproject.toml index 1603d8d7..11ac22ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pendulum" -version = "2.1.1" +version = "2.1.2" description = "Python datetimes made easy" authors = ["Sébastien Eustace "] license = "MIT" @@ -10,13 +10,18 @@ repository = "https://github.com/sdispater/pendulum" documentation = "https://pendulum.eustace.io/docs" keywords = ['datetime', 'date', 'time'] -build = "build.py" - packages = [ {include = "pendulum"}, #{include = "tests", format = "sdist"}, ] -include = ["pendulum/py.typed"] +include = [ + {path = "pendulum/py.typed"}, + # C extensions must be included in the wheel distributions + {path = "pendulum/_extensions/*.so", format = "wheel"}, + {path = "pendulum/_extensions/*.pyd", format = "wheel"}, + {path = "pendulum/parsing/*.so", format = "wheel"}, + {path = "pendulum/parsing/*.pyd", format = "wheel"}, +] [tool.poetry.dependencies] @@ -43,6 +48,9 @@ pygments = "^2.2" markdown-include = "^0.5.1" freezegun = "^0.3.15" +[tool.poetry.build] +generate-setup-file = false +script = "build.py" [tool.isort] line_length = 88 @@ -69,5 +77,5 @@ known_third_party = [ [build-system] -requires = ["poetry>=1.0.0b1"] -build-backend = "poetry.masonry.api" +requires = ["poetry-core>=1.0.0a9"] +build-backend = "poetry.core.masonry.api"