Skip to content

Commit b80b1aa

Browse files
author
Ram Rachum
committed
picking stuff from cute_life
1 parent 05c2fbd commit b80b1aa

File tree

14 files changed

+193
-103
lines changed

14 files changed

+193
-103
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
*.pyc
2+
*.pyo
23

34
*.wpu
45

garlicsim/garlicsim/general_misc/math_tools.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,20 @@
33

44
'''This module defines math-related tools.'''
55

6+
from __future__ import division
7+
68
def sign(x):
79
'''Get the sign of a number.'''
810
if x > 0:
911
return 1
1012
if x == 0:
1113
return 0
1214
assert x < 0
13-
return -1
15+
return -1
16+
17+
def round_to_int(x, up=False):
18+
rounded_down = int(x // 1)
19+
if up:
20+
return int(x) if x.is_integer() else rounded_down + 1
21+
else:
22+
return rounded_down

garlicsim/garlicsim/misc/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from base_history_browser import BaseHistoryBrowser
1616
from step_iterator import StepIterator
1717
import persistent
18-
from persistent import Persistent
18+
from persistent import Persistent, CrossProcessPersistent
1919
from step_profile import StepProfile
2020
from nodes_added import NodesAdded
2121
from simpack_grokker import SimpackGrokker

garlicsim/garlicsim/misc/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
'''Defines a collection of exceptions.'''
55

66

7-
class SmartException(Exception):
7+
class SmartException(Exception):# tododoc: move to general_misc
88
'''
99
Exception that uses its first line of documentation in lieu of a message.
1010
'''

garlicsim/garlicsim/misc/persistent/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88
'''
99

1010
from persistent import Persistent
11+
from cross_process_persistent import CrossProcessPersistent
1112
from personality import Personality
1213
from copy_modes import DontCopyPersistent
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Copyright 2009-2010 Ram Rachum.
2+
# This program is distributed under the LGPL2.1 license.
3+
4+
'''
5+
This module defines the Persistent class.
6+
7+
See its documentation for more information.
8+
9+
10+
11+
Note: This module is still experimental.
12+
13+
todo: need to lock library to avoid thread trouble?
14+
15+
todo: need to raise an exception if we're getting pickled with
16+
an old protocol?
17+
18+
todo: make it polite to other similar classes
19+
'''
20+
21+
22+
import uuid
23+
import weakref
24+
import colorsys
25+
26+
from copy_modes import DontCopyPersistent
27+
from garlicsim.general_misc import copy_tools
28+
29+
from persistent import Persistent
30+
# Doing `from personality import Personality` at bottom of file
31+
32+
33+
library = weakref.WeakValueDictionary()
34+
35+
36+
class UuidToken(object):
37+
'''Token which contains a uuid with its attribute `.uuid`'''
38+
def __init__(self, uuid):
39+
self.uuid = uuid
40+
41+
class CrossProcessPersistent(Persistent):
42+
'''
43+
Object that sometimes shouldn't really be duplicated.
44+
45+
Say some plain object references a Persistent object. Then that plain object
46+
gets deepcopied with the DontCopyPersistent copy mode. The plain object will
47+
get deepcopied, but the Persistent object under it will not! The new copy of
48+
the plain object will refer to the same old copy of the Persistent object.
49+
50+
This is useful for objects which are read-only and possibly heavy. You may
51+
use Persistent as a base class for these kinds of objects.
52+
53+
When copying a Persistent, it is not really copied; The new "copy" is just
54+
the same object. When a Persistent is passed around between processes in
55+
queues, each process retains only one copy of it.
56+
57+
Keep in mind that a Persistent is read-only. This means that starting from the
58+
first time that it is copied or put in a queue, it should not be changed.
59+
60+
There is no mechanism that enforces that the user doesn't change the object,
61+
so the user must remember not to change it.
62+
63+
Note: This class is still experimental.
64+
'''
65+
def __new__(cls, *args, **kwargs):
66+
67+
# Here we need to check in what context __new__ was called.
68+
# There are two options:
69+
# 1. The object is being created.
70+
# 2. The object is being unpickled.
71+
# We check whether we are getting a uuid token. If we are, it's
72+
# unpickling. If we don't, it's creation.
73+
74+
if len(args)==1 and len(kwargs)==0 and isinstance(args[0], UuidToken):
75+
received_uuid = args[0].uuid
76+
else:
77+
received_uuid = None
78+
79+
if received_uuid: # The object is being unpickled
80+
thing = library.pop(received_uuid, None)
81+
if thing:
82+
thing._CrossProcessPersistent__skip_setstate = True
83+
return thing
84+
else: # This object does not exist in our library yet; Let's add it
85+
thing = super(CrossProcessPersistent, cls).__new__(cls)
86+
thing._CrossProcessPersistent__uuid = received_uuid
87+
library[received_uuid] = thing
88+
return thing
89+
90+
else: # The object is being created
91+
thing = super(CrossProcessPersistent, cls).__new__(cls)
92+
new_uuid = uuid.uuid4()
93+
thing._CrossProcessPersistent__uuid = new_uuid
94+
library[new_uuid] = thing
95+
return thing
96+
97+
def __getstate__(self):
98+
my_dict = dict(self.__dict__)
99+
del my_dict["_CrossProcessPersistent__uuid"]
100+
return my_dict
101+
102+
def __getnewargs__(self):
103+
return (UuidToken(self._CrossProcessPersistent__uuid),)
104+
105+
def __setstate__(self, state):
106+
if self.__dict__.pop("_CrossProcessPersistent__skip_setstate", None):
107+
return
108+
else:
109+
self.__dict__.update(state)
110+
111+
def __deepcopy__(self, memo):
112+
'''
113+
Deepcopy the object. If DontCopyPersistent is given, only mock-copy.
114+
115+
When this method receieves an instance of DontCopyPersistent as a memo
116+
dictionary, it will not actually deepcopy the object but only return a
117+
reference to the original object.
118+
'''
119+
if isinstance(memo, DontCopyPersistent):
120+
memo[id(self)] = self
121+
return self
122+
else:
123+
new_copy = copy_tools.deepcopy_as_simple_object(self, memo)
124+
new_copy._Persistent__uuid = uuid.uuid4()
125+
if hasattr(new_copy, '_CrossProcessPersistent__personality'):
126+
del new_copy._Persistent__personality
127+
return new_copy
128+
129+
def get_personality(self):
130+
'''
131+
Get the personality of this persistent object.
132+
133+
See documentation of class garlicsim.misc.persistent.Personality for
134+
more information.
135+
'''
136+
# Todo: consider doing __getattr__ thing, maybe `cache`?
137+
personality_exists = hasattr(self, '_CrossProcessPersistent__personality')
138+
139+
if personality_exists is False:
140+
self.__personality = Personality(self)
141+
142+
return self.__personality
143+
144+
145+
146+
from personality import Personality

garlicsim/garlicsim/misc/persistent/persistent.py

Lines changed: 1 addition & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,11 @@
1919
'''
2020

2121

22-
import uuid
23-
import weakref
24-
import colorsys
25-
2622
from copy_modes import DontCopyPersistent
2723
from garlicsim.general_misc import copy_tools
2824

29-
# Doing `from personality import Personality` at bottom of file
30-
3125
__all__ = ['Persistent']
3226

33-
34-
library = weakref.WeakValueDictionary()
35-
36-
37-
class UuidToken(object):
38-
'''Token which contains a uuid with its attribute `.uuid`'''
39-
def __init__(self, uuid):
40-
self.uuid = uuid
41-
4227
class Persistent(object):
4328
'''
4429
Object that sometimes shouldn't really be duplicated.
@@ -63,51 +48,7 @@ class Persistent(object):
6348
6449
Note: This class is still experimental.
6550
'''
66-
def __new__(cls, *args, **kwargs):
67-
68-
# Here we need to check in what context __new__ was called.
69-
# There are two options:
70-
# 1. The object is being created.
71-
# 2. The object is being unpickled.
72-
# We check whether we are getting a uuid token. If we are, it's
73-
# unpickling. If we don't, it's creation.
74-
75-
if len(args)==1 and len(kwargs)==0 and isinstance(args[0], UuidToken):
76-
received_uuid = args[0].uuid
77-
else:
78-
received_uuid = None
79-
80-
if received_uuid: # The object is being unpickled
81-
thing = library.pop(received_uuid, None)
82-
if thing:
83-
thing._Persistent__skip_setstate = True
84-
return thing
85-
else: # This object does not exist in our library yet; Let's add it
86-
thing = super(Persistent, cls).__new__(cls)
87-
thing._Persistent__uuid = received_uuid
88-
library[received_uuid] = thing
89-
return thing
90-
91-
else: # The object is being created
92-
thing = super(Persistent, cls).__new__(cls)
93-
new_uuid = uuid.uuid4()
94-
thing._Persistent__uuid = new_uuid
95-
library[new_uuid] = thing
96-
return thing
9751

98-
def __getstate__(self):
99-
my_dict = dict(self.__dict__)
100-
del my_dict["_Persistent__uuid"]
101-
return my_dict
102-
103-
def __getnewargs__(self):
104-
return (UuidToken(self._Persistent__uuid),)
105-
106-
def __setstate__(self, state):
107-
if self.__dict__.pop("_Persistent__skip_setstate", None):
108-
return
109-
else:
110-
self.__dict__.update(state)
11152

11253
def __deepcopy__(self, memo):
11354
'''
@@ -122,29 +63,8 @@ def __deepcopy__(self, memo):
12263
return self
12364
else:
12465
new_copy = copy_tools.deepcopy_as_simple_object(self, memo)
125-
new_copy._Persistent__uuid = uuid.uuid4()
126-
if hasattr(new_copy, '_Persistent__personality'):
127-
del new_copy._Persistent__personality
12866
return new_copy
12967

13068
def __copy__(self):
13169
return self
132-
133-
def get_personality(self):
134-
'''
135-
Get the personality of this persistent object.
136-
137-
See documentation of class garlicsim.misc.persistent.Personality for
138-
more information.
139-
'''
140-
# Todo: consider doing __getattr__ thing, maybe `cache`?
141-
personality_exists = hasattr(self, '_Persistent__personality')
142-
143-
if personality_exists is False:
144-
self.__personality = Personality(self)
145-
146-
return self.__personality
147-
148-
149-
150-
from personality import Personality
70+

garlicsim/garlicsim/misc/persistent/personality.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def __init__(self, persistent):
3434

3535
color_resolution = 100
3636

37-
u = int(persistent._Persistent__uuid)
37+
u = int(persistent._CrossProcessPersistent__uuid)
3838

3939
(u, human_name_seed) = divmod(u, 5494)
4040
self.human_name = human_names.name_list[human_name_seed]

garlicsim_lib/garlicsim_lib/simpacks/_prisoner_persistent_test/state.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212

1313
import garlicsim.data_structures
1414
from garlicsim.misc import StepCopy
15-
from garlicsim.misc import Persistent
15+
from garlicsim.misc import CrossProcessPersistent
1616

1717
ROUNDS = 7
1818
NUMBER_OF_PLAYERS = 70
1919

2020

21-
BaseForHandicap = [object, Persistent][1]
21+
BaseForHandicap = [object, CrossProcessPersistent][1]
2222

2323
class Handicap(BaseForHandicap):
2424
def __init__(self, thing, meow):
@@ -56,7 +56,7 @@ def create_messy_root():
5656
round=-1,
5757
match=0,
5858
player_pool=[
59-
random_strategy_player for \
59+
random_strategy_player() for \
6060
i in xrange(NUMBER_OF_PLAYERS)
6161
]
6262
)

garlicsim_lib/garlicsim_lib/simpacks/prisoner/state.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def create_messy_root():
4646
round=-1,
4747
match=0,
4848
player_pool=[
49-
random_strategy_player for \
49+
random_strategy_player() for \
5050
i in xrange(NUMBER_OF_PLAYERS)
5151
]
5252
)

0 commit comments

Comments
 (0)