def _hydrate_point(self, srid, *coordinates): """ Create a new instance of a Point subclass from a raw set of fields. The subclass chosen is determined by the given SRID; a ValueError will be raised if no such subclass can be found. """ try: point_class, dim = Point.class_for_srid(srid) except KeyError: point = Point(coordinates) point.srid = srid return point else: if len(coordinates) != dim: raise ValueError("SRID %d requires %d coordinates (%d provided)" % (srid, dim, len(coordinates))) return point_class(coordinates)
def test_4d_point(): with raises(ValueError): _ = pack(Point((0, 0, 0, 0)), version=(2, 0))
def dehydrate(self, data, version=None): """ Dehydrate to PackStream. """ from datetime import date, time, datetime, timedelta from neotime import Duration, Date, Time, DateTime from pytz import utc from py2neo.data.spatial import Point unix_epoch_date = Date(1970, 1, 1) if version is None: v = (1, 0) elif isinstance(version, tuple): v = version else: v = (version, 0) def dehydrate_object(x): t = type(x) if t in functions: f = functions[t] return f(x) elif x is None or x is True or x is False or isinstance(x, float) or isinstance(x, string_types): return x elif isinstance(x, integer_types): if x < INT64_MIN or x > INT64_MAX: raise ValueError("Integers must be within the signed 64-bit range") return x elif isinstance(x, bytearray): return x elif isinstance(x, Mapping): d = {} for key in x: if not isinstance(key, string_types): raise TypeError("Dictionary keys must be strings") d[key] = dehydrate_object(x[key]) return d elif isinstance(x, Sequence): return list(map(dehydrate_object, x)) else: raise TypeError("PackStream parameters of type %s are not supported" % type(x).__name__) def dehydrate_date(value): """ Dehydrator for `date` values. :param value: :type value: Date :return: """ return Structure(b"D", value.toordinal() - unix_epoch_date.toordinal()) def dehydrate_time(value): """ Dehydrator for `time` values. :param value: :type value: Time :return: """ if isinstance(value, Time): nanoseconds = int(value.ticks * 1000000000) elif isinstance(value, time): nanoseconds = (3600000000000 * value.hour + 60000000000 * value.minute + 1000000000 * value.second + 1000 * value.microsecond) else: raise TypeError("Value must be a neotime.Time or a datetime.time") if value.tzinfo: return Structure(b"T", nanoseconds, value.tzinfo.utcoffset(value).seconds) else: return Structure(b"t", nanoseconds) def dehydrate_datetime(value): """ Dehydrator for `datetime` values. :param value: :type value: datetime :return: """ def seconds_and_nanoseconds(dt): if isinstance(dt, datetime): dt = DateTime.from_native(dt) zone_epoch = DateTime(1970, 1, 1, tzinfo=dt.tzinfo) t = dt.to_clock_time() - zone_epoch.to_clock_time() return t.seconds, t.nanoseconds tz = value.tzinfo if tz is None: # without time zone value = utc.localize(value) seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"d", seconds, nanoseconds) elif hasattr(tz, "zone") and tz.zone: # with named time zone seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"f", seconds, nanoseconds, tz.zone) else: # with time offset seconds, nanoseconds = seconds_and_nanoseconds(value) return Structure(b"F", seconds, nanoseconds, tz.utcoffset(value).seconds) def dehydrate_duration(value): """ Dehydrator for `duration` values. :param value: :type value: Duration :return: """ return Structure(b"E", value.months, value.days, value.seconds, int(1000000000 * value.subseconds)) def dehydrate_timedelta(value): """ Dehydrator for `timedelta` values. :param value: :type value: timedelta :return: """ months = 0 days = value.days seconds = value.seconds nanoseconds = 1000 * value.microseconds return Structure(b"E", months, days, seconds, nanoseconds) def dehydrate_point(value): """ Dehydrator for Point data. :param value: :type value: Point :return: """ dim = len(value) if dim == 2: return Structure(b"X", value.srid, *value) elif dim == 3: return Structure(b"Y", value.srid, *value) else: raise ValueError("Cannot dehydrate Point with %d dimensions" % dim) functions = {} # graph types cannot be used as parameters if v >= (2, 0): functions.update({ Date: dehydrate_date, date: dehydrate_date, Time: dehydrate_time, time: dehydrate_time, DateTime: dehydrate_datetime, datetime: dehydrate_datetime, Duration: dehydrate_duration, timedelta: dehydrate_timedelta, Point: dehydrate_point, }) functions.update({ cls: dehydrate_point for cls in Point.__subclasses__() }) return dehydrate_object(data)