def test_multiprocessing_lock(): '''Test `describe` works for `multiprocessing.Lock()`.''' if not import_tools.exists('multiprocessing'): raise nose.SkipTest('`multiprocessing` not installed') import multiprocessing lock = multiprocessing.Lock() describe(lock)
def test_function_in_something(): '''Test `describe` doesn't fail when describing `{1: sum}`.''' if garlicsim.__version_info__ <= (0, 6, 3): raise nose.SkipTest("This test doesn't pass in `garlicsim` version " "0.6.3 and below.") assert describe({1: sum}) == '{1: sum}' assert describe((sum, sum, list, chr)) == '(sum, sum, list, chr)'
def test_bad_module_name(): ''' Test `describe` works for methods with bad `__module__` attribute. The `__module__` attribute usually says where an object can be reached. But in some cases, like when working in a shell, you can't really access the objects from that non-existant module. So `describe` must not fail for these cases. ''' raise nose.SkipTest("Can't handle methods yet.") non_sensical_module_name = '__whoop_dee_doo___rrrar' my_locals = locals().copy() my_locals['__name__'] = non_sensical_module_name exec('def f(): pass', my_locals) exec(('class A(object):\n' ' def m(self): pass'), my_locals) assert describe(A.m) == \ '.'.join((non_sensical_module_name, 'A.m')) assert describe(A.m, shorten=True, root=email, namespace={}) == \ '.'.join((non_sensical_module_name, 'A.m'))
def test_locally_defined_class(): ########################################################################### # Testing for locally defined class: if garlicsim.__version_info__ <= (0, 6, 3): raise nose.SkipTest("This test doesn't pass in `garlicsim` version " "0.6.3 and below, because `describe` doesn't " "support nested classes yet.") result = describe(A.B) assert result == prefix + 'A.B' assert resolve(result) is A.B result = describe(A.C.D.deeper_method) assert result == prefix + 'A.C.D.deeper_method' assert resolve(result) == A.C.D.deeper_method result = describe(A.C.D.deeper_method, root=A.C) assert result == 'C.D.deeper_method' assert resolve(result, root=A.C) == A.C.D.deeper_method result = describe(A.C.D.deeper_method, root='A.C.D') assert result == 'D.deeper_method' assert resolve(result, root='A.C.D') == A.C.D.deeper_method
def test_address_in_expression(): '''Test `describe` works for an address inside an expression.''' import email.encoders import marshal assert describe([object, email.encoders, marshal]) == \ '[object, email.encoders, marshal]' assert describe([email.encoders, 7, (1, 3), marshal]) == \ '[email.encoders, 7, (1, 3), marshal]'
def __repr__(self): ''' Get a string representation of the project. Example output: <garlicsim.Project containing 101 nodes and employing 4 crunchers at 0x1f668d0> ''' # Todo: better have the simpack mentioned here # todo: show cruncher types, even listing for different types if there # are different types. Length is not a problem because this is a rare # condition. nodes_count = len(self.tree.nodes) crunchers_count = len(self.crunching_manager.crunchers) return '<%s containing %s nodes and employing %s crunchers at %s>' % \ ( address_tools.describe(type(self), shorten=True), nodes_count, crunchers_count, hex(id(self)) )
def __repr__(self): ''' Get a string representation of the node range. Example output: <garlicsim.data_structures.NodeRange, from node with clock 2 to block that ends at clock 102, containing 101 nodes total, at 0x291c550> ''' return '<%s, from %s %s to %s %s, containing %s nodes total, at %s>' \ % ( address_tools.describe(type(self), shorten=True), 'block that starts at clock' if isinstance(self.head, Block) else 'node with clock', self.head[0].state.clock if isinstance(self.head, Block) else self.head.state.clock, 'block that ends at clock' if \ isinstance(self.tail, Block) else 'node with clock', self.tail[-1].state.clock if isinstance(self.tail, Block) \ else self.tail.state.clock, cute_iter_tools.get_length(self), hex(id(self)) )
def describe(self, step_function): '''Describe `step_function` as a string.''' return address_tools.describe( step_function, shorten=True, root=self.simpack, namespace=self.gui_project.namespace )
def test_garlicsim(): '''Test `describe` for various `garlicsim` modules.''' import garlicsim result = describe(garlicsim.data_structures.state.State) assert result == 'garlicsim.data_structures.state.State' assert resolve(result) is garlicsim.data_structures.state.State result = describe(garlicsim.data_structures.state.State, shorten=True) assert result == 'garlicsim.data_structures.State' assert resolve(result) is garlicsim.data_structures.state.State result = describe(garlicsim.Project, shorten=True) assert result == 'garlicsim.Project' assert resolve(result) is garlicsim.Project # When a root or namespace is given, it's top priority to use it, even if # it prevents shorterning and results in an overall longer address: result = describe(garlicsim.Project, shorten=True, root=garlicsim.asynchronous_crunching) assert result == 'asynchronous_crunching.Project' assert resolve(result, root=garlicsim.asynchronous_crunching) is \ garlicsim.Project result = describe(garlicsim.Project, shorten=True, namespace=garlicsim) assert result == 'Project' assert resolve(result, namespace=garlicsim) is garlicsim.Project result = describe(garlicsim.Project, shorten=True, namespace=garlicsim.__dict__) assert result == 'Project' assert resolve(result, namespace=garlicsim.__dict__) is \ garlicsim.Project result = describe(garlicsim.Project, shorten=True, namespace='garlicsim') assert result == 'Project' assert resolve(result, namespace='garlicsim') is garlicsim.Project result = describe(garlicsim.Project, shorten=True, namespace='garlicsim.__dict__') assert result == 'Project' assert resolve(result, namespace='garlicsim.__dict__') is \ garlicsim.Project result = describe(garlicsim.data_structures.state.State, root=garlicsim) assert result == 'garlicsim.data_structures.state.State' assert resolve(result, root=garlicsim) is \ garlicsim.data_structures.state.State
def test_function_in_main(): '''Test that a function defined in `__main__` is well-described.''' ########################################################################### # We can't really define a function in `__main__` in this test, so we # emulate it: with TempValueSetter((globals(), '__name__'), '__main__'): def f(x): pass assert f.__module__ == '__main__' import __main__ __main__.f = f del __main__ # ########################################################################### assert describe(f) == '__main__.f' assert resolve(describe(f)) is f
def test_ignore_confusing_namespace(): '''Test that `describe` doesn't use a confusing namespace item.''' import email.encoders import marshal result = describe(email, shorten=True, namespace={'e': email}) assert result == 'email' # Not shortening to 'e', that would be confusing. result = describe(email.encoders, namespace={'e': email, 'email': email}) assert result == 'email.encoders' result = describe(email.encoders, root=marshal, namespace={ 'e': email, 'email': email }) assert result == 'email.encoders'
def test_stdlib(): '''Test `describe` for various stdlib modules.''' import email.encoders result = describe(email.encoders) assert result == 'email.encoders' assert resolve(result) is email.encoders result = describe(email.encoders, root=email.encoders) assert result == 'encoders' assert resolve(result, root=email.encoders) is email.encoders result = describe(email.encoders, namespace=email) assert result == 'encoders' assert resolve(result, namespace=email) is email.encoders result = describe(email.encoders, root=email.encoders, namespace=email) assert result == 'encoders' assert resolve(result, root=email.encoders, namespace=email) is \ email.encoders
def persistent_id(self, obj): if self.pre_filter: passed_pre_filter = self.pre_filter(obj) else: passed_pre_filter = True if passed_pre_filter and is_atomically_pickleable(obj): return None else: return 'Filtered by pickle_tools (%s)' % \ address_tools.describe(obj)
def test_local_modules(): '''Test `describe` on local, relatively-imported modules.''' import garlicsim from .sample_module_tree import w z = resolve('w.x.y.z', root=w) result = describe(z, root=w) assert result == 'w.x.y.z' result = describe(z, shorten=True, root=w) assert result == 'w.y.z' result = describe(z, shorten=True, root=w) assert result == 'w.y.z' result = describe(z, shorten=True, root=w, namespace='email') assert result == 'w.y.z' result = describe(z, shorten=True, root=garlicsim, namespace=w) assert result == 'y.z' result = describe(z, shorten=True, root=w.x) assert result == 'x.y.z'
def __repr__(self): ''' Get a string representation of the path. Example output: <garlicsim.data_structures.Path of length 43 at 0x1c822d0> ''' return '<%s of length %s at %s>' % \ ( address_tools.describe(type(self), shorten=True), len(self), hex(id(self)) )
def __repr__(self): ''' Get a string representation of the emitter. Example output: <garlicsim_wx.general_misc.emitters.emitter.Emitter 'tree_modified' at 0x1c013d0> ''' return '<%s %sat %s>' % ( address_tools.describe(type(self), shorten=True), ''.join(("'", self.name, "' ")) if self.name else '', hex(id(self)) )
def __repr__(self): ''' Get a string representation of the state. Example output: <garlicsim.data_structures.State with clock 32.3 at 0x1c822d0> ''' return '<%s %sat %s>' % \ ( address_tools.describe(type(self), shorten=True), ('with clock %s ' % self.clock) if hasattr(self, 'clock') else '', hex(id(self)) )
def test_garlicsim_method(): raise nose.SkipTest("Can't handle methods yet.") import garlicsim_lib.simpacks.life result = describe(garlicsim_lib.simpacks.life.state.State.step) assert result == 'garlicsim_lib.simpacks.life.state.State.step' result = describe(garlicsim_lib.simpacks.life.state.State.step, shorten=True) assert result == 'garlicsim_lib.simpacks.life.State.step' result = describe(garlicsim_lib.simpacks.life.state.State.step, root=garlicsim_lib.simpacks.life) assert result == 'life.state.State.step' result = describe(garlicsim_lib.simpacks.life.state.State.step, namespace=garlicsim_lib.simpacks) assert result == 'life.state.State.step' result = describe(garlicsim_lib.simpacks.life.state.State.step, root=garlicsim_lib.simpacks.life, shorten=True) assert result == 'life.State.step'
def test_ignore_confusing_namespace(): '''Test that `describe` doesn't use a confusing namespace item.''' import email.encoders import marshal result = describe( email, shorten=True, namespace={'e': email} ) assert result == 'email' # Not shortening to 'e', that would be confusing. result = describe( email.encoders, namespace={'e': email, 'email': email} ) assert result == 'email.encoders' result = describe( email.encoders, root=marshal, namespace={'e': email, 'email': email} ) assert result == 'email.encoders'
def __repr__(self): ''' Get a string representation of the tree. Example output: <garlicsim.data_structures.Tree with 1 roots, 233 nodes and 3 possible paths at 0x1f6ae70> ''' return '<%s with %s roots, %s nodes and %s possible paths at %s>' % \ ( address_tools.describe(type(self), shorten=True), len(self.roots), len(self.nodes), len(self.all_possible_paths()), hex(id(self)) )
def __repr__(self): ''' Get a string representation of the end. Example output: <garlicsim.data_structures.End from state with clock 6.5, crunched with life.State.step(<state>), at 0x1ffde70> ''' return '<%s from state with clock %s, crunched with %s, at %s>' % \ ( address_tools.describe(type(self), shorten=True), self.parent.state.clock, self.step_profile, hex(id(self)) )
def __repr__(self): ''' Get a string representation of the crunching manager. Example output: <garlicsim.asynchronous_crunching.CrunchingManager currently employing 2 crunchers to handle 2 jobs at 0x1f699b0> ''' crunchers_count = len(self.crunchers) job_count = len(self.jobs) return ( '<%s currently employing %s crunchers to handle %s jobs at %s>' % (address_tools.describe(type(self), shorten=True), crunchers_count, job_count, hex(id(self))))
def _get_from_state_class(state_class): ''' Find the simpack that a state class belongs to. Internal use. ''' assert state_class.__name__ == 'State' # remove this limitation short_address = address_tools.describe(state_class, shorten=True) simpack_name = '.'.join(short_address.split('.')[:-1]) simpack = import_tools.normal_import(simpack_name) garlicsim.misc.simpack_grokker.SimpackGrokker(simpack) # Not saving the reference: But it'll get cached because `SimpackGrokker` # is a `CachedType`. return simpack
def __repr__(self): ''' Get a string representation of the block. Example output: <garlicsim.data_structures.Block of length 40 crunched with life.State.step(<state>), t=0.1) at 0x1c84d70> ''' assert self.alive # todo: say "Dead block" return '<%s of length %s, crunched with %s at %s>' % \ ( address_tools.describe(type(self), shorten=True), len(self), self.step_profile.__repr__(short_form=True), hex(id(self)) )
def __repr__(self): """ Get a string representation of the node range. Example output: <garlicsim.data_structures.NodeRange, from node with clock 2 to block that ends at clock 102, containing 101 nodes total, at 0x291c550> """ return "<%s, from %s %s to %s %s, containing %s nodes total, at %s>" % ( address_tools.describe(type(self), shorten=True), "block that starts at clock" if isinstance(self.head, Block) else "node with clock", self.head[0].state.clock if isinstance(self.head, Block) else self.head.state.clock, "block that ends at clock" if isinstance(self.tail, Block) else "node with clock", self.tail[-1].state.clock if isinstance(self.tail, Block) else self.tail.state.clock, cute_iter_tools.get_length(self), hex(id(self)), )
def __repr__(self): ''' Get a string representation of the node. Example output: <garlicsim.data_structures.Node with clock 6.5, untouched, blockful, crunched with life.State.step(<state>), at 0x1ffde70> ''' return '<%s%s, %s%s%s, %s, %sat %s>' % ( address_tools.describe( type(self), shorten=True), ' with clock %s' % self.state.clock if hasattr(self.state, 'clock') else '', 'root, ' if (self.parent is None) else '', 'leaf, ' if (len(self.children) == 0) else '', 'touched' if self.touched else 'untouched', 'blockful' if self.block else 'blockless', 'crunched with %s, ' % self.step_profile.__repr__(short_form=True) if self.step_profile else '', hex(id(self)))
def __repr__(self, short_form=False, root=None, namespace={}): ''' Get a string representation of the step profile. Example output with `short_form=False`: StepProfile(<unbound method State.step>, 'billinear', t=7) Use `short_form=True` for the shorter form: my_simpack.State.step(<state>, 'billinear', t=7) `root` and `namespace` will be used for shortening the function address. ''' if short_form: if root is None: # Let's try to guess the simpack to have a shorter result: root = self._guess_simpack() # (When `_guess_simpack` fails, it returns `None`, so we're # safe.) describe = lambda thing: address_tools.describe( thing, shorten=True, root=root, namespace=namespace) else: # not short_form describe = repr args_string = ', '.join((describe(thing) for thing in self.args)) kwargs_string = ', '.join( ('='.join((str(key), describe(value))) for (key, value) in self.kwargs.iteritems())) strings = filter(None, (args_string, kwargs_string)) big_string = ', '.join(strings) if short_form: step_function_address = describe(self.step_function) final_big_string = ', '.join(filter(None, ('<state>', big_string))) return '%s(%s)' % (step_function_address, final_big_string) else: final_big_string = ', '.join( filter(None, (describe(self.step_function), big_string))) return '%s(%s)' % (type(self).__name__, final_big_string)
def __repr__(self): ''' Get a string representation of the node. Example output: <garlicsim.data_structures.Node with clock 6.5, untouched, blockful, crunched with life.State.step(<state>), at 0x1ffde70> ''' return '<%s%s, %s%s%s, %s, %sat %s>' % ( address_tools.describe(type(self), shorten=True), ' with clock %s' % self.state.clock if hasattr(self.state, 'clock') else '', 'root, ' if (self.parent is None) else '', 'leaf, ' if (len(self.children) == 0) else '', 'touched' if self.touched else 'untouched', 'blockful' if self.block else 'blockless', 'crunched with %s, ' % self.step_profile.__repr__(short_form=True) if self.step_profile else '', hex(id(self)) )
def __repr__(self): ''' Get a string representation of the crunching manager. Example output: <garlicsim.asynchronous_crunching.CrunchingManager currently employing 2 crunchers to handle 2 jobs at 0x1f699b0> ''' crunchers_count = len(self.crunchers) job_count = len(self.jobs) return ( '<%s currently employing %s crunchers to handle %s jobs at %s>' % ( address_tools.describe(type(self), shorten=True), crunchers_count, job_count, hex(id(self)) ) )
def test_bad_module_name(): ''' Test `describe` works for objects with bad `__module__` attribute. The `__module__` attribute usually says where an object can be reached. But in some cases, like when working in a shell, you can't really access the objects from that non-existant module. So `describe` must not fail for these cases. ''' import email non_sensical_module_name = '__whoop_dee_doo___rrrar' my_locals = locals().copy() my_locals['__name__'] = non_sensical_module_name exec 'def f(): pass' in my_locals exec ('class A(object):\n' ' def m(self): pass\n') in my_locals f, A = my_locals['f'], my_locals['A'] assert describe(f) == \ '.'.join((non_sensical_module_name, 'f')) assert describe(f, shorten=True, root=email, namespace={}) == \ '.'.join((non_sensical_module_name, 'f')) assert describe(A) == \ '.'.join((non_sensical_module_name, 'A')) assert describe(A, shorten=True, root=email, namespace={}) == \ '.'.join((non_sensical_module_name, 'A')) assert describe(A.m) == \ '.'.join((non_sensical_module_name, 'A.m')) assert describe(A.m, shorten=True, root=email, namespace={}) == \ '.'.join((non_sensical_module_name, 'A.m'))
def test_bad_module_name(): ''' Test `describe` works for objects with bad `__module__` attribute. The `__module__` attribute usually says where an object can be reached. But in some cases, like when working in a shell, you can't really access the objects from that non-existant module. So `describe` must not fail for these cases. ''' import email non_sensical_module_name = '__whoop_dee_doo___rrrar' my_locals = locals().copy() my_locals['__name__'] = non_sensical_module_name exec 'def f(): pass' in my_locals exec('class A(object):\n' ' def m(self): pass\n') in my_locals f, A = my_locals['f'], my_locals['A'] assert describe(f) == \ '.'.join((non_sensical_module_name, 'f')) assert describe(f, shorten=True, root=email, namespace={}) == \ '.'.join((non_sensical_module_name, 'f')) assert describe(A) == \ '.'.join((non_sensical_module_name, 'A')) assert describe(A, shorten=True, root=email, namespace={}) == \ '.'.join((non_sensical_module_name, 'A')) assert describe(A.m) == \ '.'.join((non_sensical_module_name, 'A.m')) assert describe(A.m, shorten=True, root=email, namespace={}) == \ '.'.join((non_sensical_module_name, 'A.m'))
def check(simpack, cruncher_type): my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack) assert my_simpack_grokker is garlicsim.misc.SimpackGrokker(simpack) # Ensuring caching works. assert garlicsim.misc.simpack_grokker.step_type.StepType.get_step_type( my_simpack_grokker.default_step_function ) == simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE step_profile = my_simpack_grokker.build_step_profile() deterministic = \ my_simpack_grokker.settings.DETERMINISM_FUNCTION(step_profile) state = simpack.State.create_root() project = garlicsim.Project(simpack) project.crunching_manager.cruncher_type = cruncher_type assert project.tree.lock._ReadWriteLock__writer is None root = project.root_this_state(state) def run_sync_crunchers_until_we_get_at_least_one_node(): while not project.sync_crunchers(): time.sleep(0.1) ### Test changing clock target on the fly: ################################ # # huge_number = 10**20 different_huge_number = huge_number + 1 assert different_huge_number - huge_number == 1 job = project.begin_crunching(root, huge_number) run_sync_crunchers_until_we_get_at_least_one_node() (cruncher, ) = project.crunching_manager.crunchers.values() ## An interlude to test `__repr__` methods: ############################### step_profile_description = repr(job.crunching_profile.step_profile) assert step_profile_description == \ 'StepProfile(%s)' % simpack._test_settings.DEFAULT_STEP_FUNCTION short_step_profile_description = \ job.crunching_profile.step_profile.__repr__(short_form=True) assert short_step_profile_description == \ '%s(<state>)' % address_tools.describe( simpack._test_settings.DEFAULT_STEP_FUNCTION, shorten=True, root=simpack, ) crunching_profile_description = repr(job.crunching_profile) assert crunching_profile_description == \ 'CrunchingProfile(clock_target=%d, step_profile=%s)' % \ (huge_number, short_step_profile_description) job_description = repr(job) assert job_description == 'Job(node=%s, crunching_profile=%s)' % \ (repr(job.node), crunching_profile_description) crunching_manager_description = repr(project.crunching_manager) assert re.match( ('^<.*?CrunchingManager currently employing 1 crunchers to ' 'handle 1 jobs at .*?>$'), crunching_manager_description) project_description = repr(project) assert re.match( '<.*?Project containing .*? nodes and employing 1 crunchers at .*?>', project_description) # Assert the job cruncher is not unequal to itself: assert not job.crunching_profile.__ne__(job.crunching_profile) ## Finished interlude to test `__repr__` methods. ######################### job.crunching_profile.raise_clock_target(different_huge_number) # Letting our crunching manager update our cruncher about the new clock # target: project.sync_crunchers() assert not job.is_done() (same_cruncher, ) = project.crunching_manager.crunchers.values() # todo: On slow machines cruncher doesn't get created fast enough for the # above assert to work. Probably make some function that waits for it. assert same_cruncher is cruncher # Deleting jobs so the cruncher will stop: del project.crunching_manager.jobs[:] project.sync_crunchers() assert not project.crunching_manager.jobs assert not project.crunching_manager.crunchers # # ### Finish testing changing clock target on the fly. ###################### ### Test changing step profile on the fly: ################################ # # # For simpacks providing more than one step function, we'll test changing # between them. This will exercise the crunching manager's policy of # switching crunchers immediately when the step profile for a job gets # changed. if simpack._test_settings.N_STEP_FUNCTIONS >= 2: default_step_function, alternate_step_function = \ my_simpack_grokker.all_step_functions[:2] job = project.begin_crunching(root, infinity) assert job.crunching_profile.step_profile.step_function == \ default_step_function run_sync_crunchers_until_we_get_at_least_one_node() (cruncher, ) = project.crunching_manager.crunchers.values() alternate_step_profile = \ garlicsim.misc.StepProfile(alternate_step_function) job.crunching_profile.step_profile = alternate_step_profile # Letting our crunching manager get a new cruncher for our new step # profile: project.sync_crunchers() (new_cruncher, ) = project.crunching_manager.crunchers.values() assert new_cruncher is not cruncher last_node_with_default_step_profile = job.node assert not last_node_with_default_step_profile.children # It's a leaf assert last_node_with_default_step_profile.\ step_profile.step_function == default_step_function # Another `sync_crunchers`: run_sync_crunchers_until_we_get_at_least_one_node() # And now we have some new nodes with the alternate step profile. (first_node_with_alternate_step_profile,) = \ last_node_with_default_step_profile.children path = last_node_with_default_step_profile.make_containing_path() nodes_with_alternate_step_profile = list( path.__iter__(head=first_node_with_alternate_step_profile)) for node in nodes_with_alternate_step_profile: assert node.step_profile == alternate_step_profile # Deleting jobs so the cruncher will stop: del project.crunching_manager.jobs[:] project.sync_crunchers() assert not project.crunching_manager.jobs assert not project.crunching_manager.crunchers # # ### Finished testing changing step profile on the fly. #################### ### Testing cruncher type switching: ###################################### # # job_1 = project.begin_crunching(root, clock_buffer=infinity) job_2 = project.begin_crunching(root, clock_buffer=infinity) assert len(project.crunching_manager.crunchers) == 0 assert project.sync_crunchers() == 0 assert len(project.crunching_manager.crunchers) == 2 (cruncher_1, cruncher_2) = project.crunching_manager.crunchers.values() assert type(cruncher_1) is cruncher_type assert type(cruncher_2) is cruncher_type time.sleep(0.2) # Letting the crunchers start working project.crunching_manager.cruncher_type = MustachedThreadCruncher project.sync_crunchers() assert len(project.crunching_manager.crunchers) == 2 (cruncher_1, cruncher_2) = project.crunching_manager.crunchers.values() assert type(cruncher_1) is MustachedThreadCruncher assert type(cruncher_2) is MustachedThreadCruncher project.crunching_manager.cruncher_type = cruncher_type project.sync_crunchers() assert len(project.crunching_manager.crunchers) == 2 (cruncher_1, cruncher_2) = project.crunching_manager.crunchers.values() assert type(cruncher_1) is cruncher_type assert type(cruncher_2) is cruncher_type # Deleting jobs so the crunchers will stop: del project.crunching_manager.jobs[:] project.sync_crunchers() assert not project.crunching_manager.jobs assert not project.crunching_manager.crunchers
def test_garlicsim(): '''Test `describe` for various `garlicsim` modules.''' import garlicsim result = describe(garlicsim.data_structures.state.State) assert result == 'garlicsim.data_structures.state.State' assert resolve(result) is garlicsim.data_structures.state.State result = describe(garlicsim.data_structures.state.State, shorten=True) assert result == 'garlicsim.data_structures.State' assert resolve(result) is garlicsim.data_structures.state.State result = describe(garlicsim.Project, shorten=True) assert result == 'garlicsim.Project' assert resolve(result) is garlicsim.Project # When a root or namespace is given, it's top priority to use it, even if # it prevents shorterning and results in an overall longer address: result = describe(garlicsim.Project, shorten=True, root=garlicsim.asynchronous_crunching) assert result == 'asynchronous_crunching.Project' assert resolve(result, root=garlicsim.asynchronous_crunching) is \ garlicsim.Project result = describe(garlicsim.Project, shorten=True, namespace=garlicsim) assert result == 'Project' assert resolve(result, namespace=garlicsim) is garlicsim.Project result = describe(garlicsim.Project, shorten=True, namespace=garlicsim.__dict__) assert result == 'Project' assert resolve(result, namespace=garlicsim.__dict__) is \ garlicsim.Project result = describe(garlicsim.Project, shorten=True, namespace='garlicsim') assert result == 'Project' assert resolve(result, namespace='garlicsim') is garlicsim.Project result = describe(garlicsim.Project, shorten=True, namespace='garlicsim.__dict__') assert result == 'Project' assert resolve(result, namespace='garlicsim.__dict__') is \ garlicsim.Project result = describe(garlicsim.data_structures.state.State, root=garlicsim) assert result == 'garlicsim.data_structures.state.State' assert resolve(result, root=garlicsim) is \ garlicsim.data_structures.state.State import garlicsim_lib.simpacks.life result = describe(garlicsim_lib.simpacks.life.state.State.step) assert result == 'garlicsim_lib.simpacks.life.state.State.step' result = describe(garlicsim_lib.simpacks.life.state.State.step, shorten=True) assert result == 'garlicsim_lib.simpacks.life.State.step' result = describe(garlicsim_lib.simpacks.life.state.State.step, root=garlicsim_lib.simpacks.life) assert result == 'life.state.State.step' result = describe(garlicsim_lib.simpacks.life.state.State.step, namespace=garlicsim_lib.simpacks) assert result == 'life.state.State.step' result = describe(garlicsim_lib.simpacks.life.state.State.step, root=garlicsim_lib.simpacks.life, shorten=True) assert result == 'life.State.step'
def __repr__(self, short_form=False, root=None, namespace={}): ''' Get a string representation of the step profile. Example output with `short_form=False`: StepProfile(<unbound method State.step>, 'billinear', t=7) Use `short_form=True` for the shorter form: my_simpack.State.step(<state>, 'billinear', t=7) `root` and `namespace` will be used for shortening the function address. ''' if short_form: if root is None: # Let's try to guess the simpack to have a shorter result: root = self._guess_simpack() # (When `_guess_simpack` fails, it returns `None`, so we're # safe.) describe = lambda thing: address_tools.describe( thing, shorten=True, root=root, namespace=namespace ) else: # not short_form describe = repr args_string = ', '.join((describe(thing) for thing in self.args)) kwargs_string = ', '.join( ('='.join((str(key), describe(value))) for (key, value) in self.kwargs.items()) ) strings = [_f for _f in (args_string, kwargs_string) if _f] big_string = ', '.join(strings) if short_form: step_function_address = describe(self.step_function) final_big_string = ', '.join( [_f for _f in ( '<state>', big_string ) if _f] ) return '%s(%s)' % ( step_function_address, final_big_string ) else: final_big_string = ', '.join( [_f for _f in ( describe(self.step_function), big_string ) if _f] ) return '%s(%s)' % (type(self).__name__, final_big_string)
def describe(self, step_function): '''Describe `step_function` as a string.''' return address_tools.describe(step_function, shorten=True, root=self.simpack, namespace=self.gui_project.namespace)
def check(simpack, cruncher_type): my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack) assert my_simpack_grokker is garlicsim.misc.SimpackGrokker(simpack) # Ensuring caching works. assert garlicsim.misc.simpack_grokker.step_type.StepType.get_step_type( my_simpack_grokker.default_step_function ) == simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE step_profile = my_simpack_grokker.build_step_profile() deterministic = \ my_simpack_grokker.settings.DETERMINISM_FUNCTION(step_profile) state = simpack.State.create_root() project = garlicsim.Project(simpack) project.crunching_manager.cruncher_type = cruncher_type assert project.tree.lock._ReadWriteLock__writer is None root = project.root_this_state(state) def run_sync_crunchers_until_we_get_at_least_one_node(): while not project.sync_crunchers(): time.sleep(0.1) ### Test changing clock target on the fly: ################################ # # huge_number = 10 ** 20 different_huge_number = huge_number + 1 assert different_huge_number - huge_number == 1 job = project.begin_crunching(root, huge_number) run_sync_crunchers_until_we_get_at_least_one_node() (cruncher,) = project.crunching_manager.crunchers.values() ## An interlude to test `__repr__` methods: ############################### step_profile_description = repr(job.crunching_profile.step_profile) assert step_profile_description == \ 'StepProfile(%s)' % simpack._test_settings.DEFAULT_STEP_FUNCTION short_step_profile_description = \ job.crunching_profile.step_profile.__repr__(short_form=True) assert short_step_profile_description == \ '%s(<state>)' % address_tools.describe( simpack._test_settings.DEFAULT_STEP_FUNCTION, shorten=True, root=simpack, ) crunching_profile_description = repr(job.crunching_profile) assert crunching_profile_description == \ 'CrunchingProfile(clock_target=%d, step_profile=%s)' % \ (huge_number, short_step_profile_description) job_description = repr(job) assert job_description == 'Job(node=%s, crunching_profile=%s)' % \ (repr(job.node), crunching_profile_description) crunching_manager_description = repr(project.crunching_manager) assert re.match( ('^<.*?CrunchingManager currently employing 1 crunchers to ' 'handle 1 jobs at .*?>$'), crunching_manager_description ) project_description = repr(project) assert re.match( '<.*?Project containing .*? nodes and employing 1 crunchers at .*?>', project_description ) # Assert the job cruncher is not unequal to itself: assert not job.crunching_profile.__ne__(job.crunching_profile) ## Finished interlude to test `__repr__` methods. ######################### job.crunching_profile.raise_clock_target(different_huge_number) # Letting our crunching manager update our cruncher about the new clock # target: project.sync_crunchers() assert not job.is_done() (same_cruncher,) = project.crunching_manager.crunchers.values() # todo: On slow machines cruncher doesn't get created fast enough for the # above assert to work. Probably make some function that waits for it. assert same_cruncher is cruncher # Deleting jobs so the cruncher will stop: del project.crunching_manager.jobs[:] project.sync_crunchers() assert not project.crunching_manager.jobs assert not project.crunching_manager.crunchers # # ### Finish testing changing clock target on the fly. ###################### ### Test changing step profile on the fly: ################################ # # # For simpacks providing more than one step function, we'll test changing # between them. This will exercise the crunching manager's policy of # switching crunchers immediately when the step profile for a job gets # changed. if simpack._test_settings.N_STEP_FUNCTIONS >= 2: default_step_function, alternate_step_function = \ my_simpack_grokker.all_step_functions[:2] job = project.begin_crunching(root, infinity) assert job.crunching_profile.step_profile.step_function == \ default_step_function run_sync_crunchers_until_we_get_at_least_one_node() (cruncher,) = project.crunching_manager.crunchers.values() alternate_step_profile = \ garlicsim.misc.StepProfile(alternate_step_function) job.crunching_profile.step_profile = alternate_step_profile # Letting our crunching manager get a new cruncher for our new step # profile: project.sync_crunchers() (new_cruncher,) = project.crunching_manager.crunchers.values() assert new_cruncher is not cruncher last_node_with_default_step_profile = job.node assert not last_node_with_default_step_profile.children # It's a leaf assert last_node_with_default_step_profile.\ step_profile.step_function == default_step_function # Another `sync_crunchers`: run_sync_crunchers_until_we_get_at_least_one_node() # And now we have some new nodes with the alternate step profile. (first_node_with_alternate_step_profile,) = \ last_node_with_default_step_profile.children path = last_node_with_default_step_profile.make_containing_path() nodes_with_alternate_step_profile = list( path.__iter__(head=first_node_with_alternate_step_profile) ) for node in nodes_with_alternate_step_profile: assert node.step_profile == alternate_step_profile # Deleting jobs so the cruncher will stop: del project.crunching_manager.jobs[:] project.sync_crunchers() assert not project.crunching_manager.jobs assert not project.crunching_manager.crunchers # # ### Finished testing changing step profile on the fly. #################### ### Testing cruncher type switching: ###################################### # # job_1 = project.begin_crunching(root, clock_buffer=infinity) job_2 = project.begin_crunching(root, clock_buffer=infinity) assert len(project.crunching_manager.crunchers) == 0 assert project.sync_crunchers() == 0 assert len(project.crunching_manager.crunchers) == 2 (cruncher_1, cruncher_2) = project.crunching_manager.crunchers.values() assert type(cruncher_1) is cruncher_type assert type(cruncher_2) is cruncher_type time.sleep(0.2) # Letting the crunchers start working project.crunching_manager.cruncher_type = MustachedThreadCruncher project.sync_crunchers() assert len(project.crunching_manager.crunchers) == 2 (cruncher_1, cruncher_2) = project.crunching_manager.crunchers.values() assert type(cruncher_1) is MustachedThreadCruncher assert type(cruncher_2) is MustachedThreadCruncher project.crunching_manager.cruncher_type = cruncher_type project.sync_crunchers() assert len(project.crunching_manager.crunchers) == 2 (cruncher_1, cruncher_2) = project.crunching_manager.crunchers.values() assert type(cruncher_1) is cruncher_type assert type(cruncher_2) is cruncher_type # Deleting jobs so the crunchers will stop: del project.crunching_manager.jobs[:] project.sync_crunchers() assert not project.crunching_manager.jobs assert not project.crunching_manager.crunchers # # ### Finished testing cruncher type switching. #############################