def test_struct_handles_missing_attributes(): """If an attribute is unset, raise an AttributeError appropriately""" t = MyStruct(1, 2) del t.y t2 = MyStruct(1, 2) match = "Struct field 'y' is unset" with pytest.raises(AttributeError, match=match): repr(t) with pytest.raises(AttributeError, match=match): copy.copy(t) with pytest.raises(AttributeError, match=match): t == t2 with pytest.raises(AttributeError, match=match): t2 == t with pytest.raises(AttributeError, match=match): pickle.dumps(t) with pytest.raises(AttributeError, match=match): quickle.dumps(t, registry=[MyStruct])
def test_pickle_struct_code_out_of_range(): x = MyStruct(1, 2) with pytest.raises(Exception) as exc: quickle.dumps(x, registry={MyStruct: 2**32}) if isinstance(exc.value, ValueError): assert "registry values must be between" in str(exc.value) else: assert isinstance(exc.value, OverflowError)
def test_dumps_and_loads_unpickleable_types(value): with pytest.raises(TypeError): quickle.dumps(value) o = pickle.dumps(value, protocol=5) with pytest.raises(quickle.DecodingError): quickle.loads(o)
def test_pickle_enum_code_out_of_range(): class Fruit(enum.IntEnum): APPLE = 1 with pytest.raises(Exception) as exc: quickle.dumps(Fruit.APPLE, registry={Fruit: 2**32}) if isinstance(exc.value, ValueError): assert "registry values must be between" in str(exc.value) else: assert isinstance(exc.value, OverflowError)
def test_pickle_memoize_function_settings(memoize): obj = [[1], [2]] res = quickle.dumps(obj, memoize=memoize) assert opcode_in_pickle(pickle.MEMOIZE, res) == memoize obj2 = quickle.loads(res) assert obj == obj2 obj = [[]] * 2 res = quickle.dumps(obj, memoize=memoize) assert opcode_in_pickle(pickle.MEMOIZE, res) == memoize obj2 = quickle.loads(res) assert obj == obj2 assert (obj2[0] is not obj2[1]) == (not memoize)
def test_unpickle_errors_intenum_missing_value(): class Fruit2(enum.IntEnum): APPLE = 1 s = quickle.dumps(Fruit.ORANGE, registry=[Fruit]) with pytest.raises(ValueError, match="Fruit2"): quickle.loads(s, registry=[Fruit2])
def test_unpickle_errors_enum_missing_attribute(): class PyObjects2(enum.Enum): LIST = [] s = quickle.dumps(PyObjects.OBJECT, registry=[PyObjects]) with pytest.raises(AttributeError, match="OBJECT"): quickle.loads(s, registry=[PyObjects2])
def set_pattern_cache(self, data, dont_save=False): if self != None and data != None: self.pattern_cache = quickle.dumps(data) if dont_save: return self self.save() return True return False
def test_pickle_enum_codes(code): p_registry = {Fruit: code} u_registry = {code: Fruit} s = quickle.dumps(Fruit.APPLE, registry=p_registry) x2 = quickle.loads(s, registry=u_registry) assert x2 == Fruit.APPLE
def test_pickle_struct_recursive(): x = MyStruct(1, None) x.y = x s = quickle.dumps(x, registry=[MyStruct]) x2 = quickle.loads(s, registry=[MyStruct]) assert x2.x == 1 assert x2.y is x2 assert type(x) is MyStruct
def test_struct_registry_mismatch_extra_args_are_ignored(): """Unpickling a struct with an older version that has fewer parameters works (the extra args are ignored).""" x = MyStruct2(1, 2) s = quickle.dumps(x, registry=[MyStruct2]) x2 = quickle.loads(s, registry=[MyStruct]) assert x2.x == 1 assert x2.y == 2
def test_unpickle_errors_obj_in_registry_is_not_struct_type(): class Foo(object): pass x = MyStruct(1, 2) s = quickle.dumps(x, registry=[MyStruct]) with pytest.raises(TypeError, match="Value for typecode"): quickle.loads(s, registry=[Foo])
def test_loads_buffers_errors(): obj = quickle.PickleBuffer(b"hello") res, _ = quickle.dumps(obj, collect_buffers=True) with pytest.raises(TypeError): quickle.loads(res, buffers=object()) with pytest.raises(quickle.DecodingError): quickle.loads(res, buffers=[])
def test_loads_timedelta_out_of_range(positive): s = quickle.dumps(datetime.timedelta(days=1234)) days = TIMEDELTA_MAX_DAYS + 1 if not positive: days = -days key = (1234).to_bytes(4, "little", signed=True) bad = s.replace(key, days.to_bytes(4, "little", signed=True)) with pytest.raises(OverflowError): quickle.loads(bad)
def test_pickle_struct_codes(code): x = MyStruct(1, 2) p_registry = {MyStruct: code} u_registry = {code: MyStruct} s = quickle.dumps(x, registry=p_registry) x2 = quickle.loads(s, registry=u_registry) assert x2 == x
def test_struct_registry_mismatch_fewer_args_default_parameters_respected(): """Unpickling a struct with a newer version that has additional default parameters at the end works (the defaults are used).""" x = MyStruct(1, 2) s = quickle.dumps(x, registry=[MyStruct]) x2 = quickle.loads(s, registry=[MyStruct2]) assert isinstance(x2, MyStruct2) assert x2.x == x.x assert x2.y == x.y assert x2.z == [] assert x2.z2 == 3
def test_objects_with_only_one_refcount_arent_memoized(): class Test(quickle.Struct): x: list y: str def rstr(): return str(uuid.uuid4().hex) data = [ (rstr(), ), (rstr(), rstr(), rstr(), rstr(), rstr()), ([[[rstr()]]], ), [rstr()], {rstr()}, frozenset([rstr()]), { rstr(): rstr() }, rstr(), rstr().encode(), bytearray(rstr().encode()), Test([rstr()], rstr()), ] s = quickle.dumps(data, registry=[Test]) # only initial arg is memoized, since its refcnt is 2 assert s.count(pickle.MEMOIZE) == 1 # Grab a reference to a tuple containing only non-container types a = data[1] s = quickle.dumps(data, registry=[Test]) # 2 memoize codes, 1 for data and 1 for the tuple assert s.count(pickle.MEMOIZE) == 2 del a # Grab a reference to a tuple containing container types a = data[2] s = quickle.dumps(data, registry=[Test]) # 5 memoize codes, 1 for data and 1 for the tuple, 1 for each list assert s.count(pickle.MEMOIZE) == 5 del a
def remove_user_from_roster_obj(tournament, user_id): roster_data = tournament.roster if roster_data != None: user_id = is_valid_uuid(user_id) if user_id != None: user_id = str(user_id) roster = quickle.loads(roster_data) new_roster = [] for user in roster: if user != user_id: new_roster.append(user) tournament.roster = quickle.dumps(new_roster)
def test_pickle_recursive_tuple(): obj = ([None], ) obj[0][0] = obj quick_res = quickle.dumps(obj) for loads in [quickle.loads, pickle.loads]: obj2 = loads(quick_res) assert isinstance(obj2, tuple) assert obj2[0][0] is obj2 # Fix the cycle so `==` works, then test obj2[0][0] = None assert obj2 == ([None], )
def test_struct_reference_counting(): """Test that struct operations that access fields properly decref""" class Test(Struct): value: list data = [1, 2, 3] t = Test(data) assert sys.getrefcount(data) == 3 repr(t) assert sys.getrefcount(data) == 3 t2 = t.__copy__() assert sys.getrefcount(data) == 4 assert t == t2 assert sys.getrefcount(data) == 4 quickle.dumps(t, registry=[Test]) assert sys.getrefcount(data) == 4
def test_quickle_pickle_collect_buffers_false_compatibility(cls): data = cls(b"hello") pbuf = quickle.PickleBuffer(data) # quickle -> pickle quick_res = quickle.dumps(pbuf) obj = pickle.loads(quick_res) assert obj == data # pickle -> quickle pickle_res = pickle.dumps(pbuf, protocol=5) obj = quickle.loads(pickle_res) assert obj == data
def test_struct_gc_set_on_unpickle(): """Unpickling doesn't go through the struct constructor""" class Test(quickle.Struct): x: object y: object ts = [Test(1, 2), Test(3, "hello"), Test([], ()), Test((), ())] a, b, c, d = quickle.loads(quickle.dumps(ts, registry=[Test]), registry=[Test]) assert not gc.is_tracked(a) assert not gc.is_tracked(b) assert gc.is_tracked(c) assert not gc.is_tracked(d)
def update_oil_pattern(pattern_db_id): oil_pattern = Oil_Pattern.objects.filter( pattern_db_id=pattern_db_id).first() if oil_pattern == None: oil_pattern = Oil_Pattern.create(pattern_db_id) with urlopen( 'http://patternlibrary.kegel.net/PatternLibraryPatternGraph.aspx?ID=' + str(pattern_db_id) + '&VIEW=COM') as response: soup = BeautifulSoup(response, 'lxml') if soup != None: # GET NAME name = get_oil_name(soup) if name is not None: oil_pattern.pattern_name = str(name) ## GET DISPLAY DATA display_data = get_display_data(soup) if display_data is not None: oil_pattern.pattern_cache = quickle.dumps(display_data) with urlopen( 'http://patternlibrary.kegel.net/PatternLibraryPatternLoadData.aspx?ID=' + str(pattern_db_id) + '&VIEW=COM') as response: soup = BeautifulSoup(response, 'lxml') if soup != None: ## GET OIL LENGTH length = get_oil_length(soup) if length is not None: oil_pattern.pattern_length = str(length) ## GET OIL VOLUME volume = get_oil_volume(soup) if volume is not None: oil_pattern.pattern_volume = str(volume) ## GET OIL FORWARD forward = get_oil_forward(soup) if forward is not None: oil_pattern.pattern_forward = str(forward) ## GET OIL BACKWARDS backward = get_oil_backward(soup) if backward is not None: oil_pattern.pattern_backward = str(backward) ## GET OIL RATIO ratio = get_oil_ratio(soup) if ratio is not None: oil_pattern.pattern_ratio = str(ratio) oil_pattern.save()
def test_pickle_recursive_dict(): # self referential obj = {} obj[0] = obj quick_res = quickle.dumps(obj) for loads in [quickle.loads, pickle.loads]: obj2 = loads(quick_res) assert isinstance(obj2, dict) assert obj2[0] is obj2 assert len(obj2) == 1 # one level removed obj = {0: []} obj[0].append(obj) quick_res = quickle.dumps(obj) for loads in [quickle.loads, pickle.loads]: obj2 = loads(quick_res) assert isinstance(obj2, dict) assert obj2[0][0] is obj2 # Fix the cycle so `==` works, then test obj2[0].pop() assert obj2 == {0: []}
def test_pickle_recursive_list(): # self referential obj = [] obj.append(obj) quick_res = quickle.dumps(obj) for loads in [quickle.loads, pickle.loads]: obj2 = loads(quick_res) assert isinstance(obj2, list) assert obj2[0] is obj2 assert len(obj2) == 1 # one level removed obj = [[None]] obj[0][0] = obj quick_res = quickle.dumps(obj) for loads in [quickle.loads, pickle.loads]: obj2 = loads(quick_res) assert isinstance(obj2, list) assert obj2[0][0] is obj2 # Fix the cycle so `==` works, then test obj2[0][0] = None assert obj2 == [[None]]
def test_quickle_pickle_collect_buffers_true_compatibility(cls): data = cls(b"hello") pbuf = quickle.PickleBuffer(data) # quickle -> pickle quick_res, quick_buffers = quickle.dumps(pbuf, collect_buffers=True) obj = pickle.loads(quick_res, buffers=quick_buffers) assert obj is pbuf # pickle -> quickle pickle_buffers = [] pickle_res = pickle.dumps(pbuf, buffer_callback=pickle_buffers.append, protocol=5) obj = quickle.loads(pickle_res, buffers=pickle_buffers) assert obj is pbuf
def add_user_to_roster_obj(tournament, user_id): roster_data = tournament.roster if roster_data != None: user_id = is_valid_uuid(user_id) if user_id != None: user_id = str(user_id) roster = quickle.loads(roster_data) roster_length = len(roster) if roster_length < tournament.spots_reserved: exists = False for user in roster: if user == user_id: exists = True if not exists: roster.append(user_id) tournament.roster = quickle.dumps(roster)
def check(obj, sol=None): if sol is None: sol = obj quick_res = quickle.dumps(obj) obj2 = quickle.loads(quick_res) assert obj2 == sol assert type(obj2) is type(sol) obj3 = pickle.loads(quick_res) assert obj3 == sol assert type(obj3) is type(sol) pickle_res = pickle.dumps(obj, protocol=5) obj4 = quickle.loads(pickle_res) assert obj4 == sol assert type(obj4) is type(sol)
def test_pickle_struct(registry_type, use_functions): if registry_type == "list": p_registry = u_registry = [MyStruct] else: p_registry = {MyStruct: 0} u_registry = {0: MyStruct} x = MyStruct(1, 2) if use_functions: s = quickle.dumps(x, registry=p_registry) x2 = quickle.loads(s, registry=u_registry) else: enc = quickle.Encoder(registry=p_registry) dec = quickle.Decoder(registry=u_registry) s = enc.dumps(x) x2 = dec.loads(s) assert x == x2
def raw_scores(self, raw_score_data): if raw_score_data: self.data_raw_scores = quickle.dumps(raw_score_data)