def __init__(self, file, makeObjs=False): self.makeObjs = makeObjs file = File(file, quiet=True) file.mkparents() if not file: file.write("{}") file.backup() file.allow_autoload = True super().__init__(file) self.__dict__['file'] = self._d assert file.ext == 'json' file.backup()
class VagrantMachine(Host): def __init__( self, keep_up, restart, rebuild ): super().__init__( home='/home' ) self.vagrantfile = File('Vagrantfile') if not self.vagrantfile: self.myinit() self._isup = None self.keep_up = keep_up self.restart = restart self._destroy = rebuild def isup(self): if self._isup is not None: return self._isup else: status = self.status() self._isup = ('The VM is powered off' not in status) and ( 'The environment has not yet been created' not in status) return self._isup def init(self, box: str): self._shell(f'vagrant init {box}').interact() def myinit(self, box='singularityware/singularity-2.4', syncdir=True): assert not self.vagrantfile.exists self.vagrantfile.write(''' # -*- mode: ruby -*- # vi: set ft=ruby : ''') self.vagrantfile.appendln('Vagrant.configure("2") do |config|') self.vagrantfile.appendln(f'config.vm.box = "{box}"') if syncdir: self.vagrantfile.appendln(f'config.vm.synced_folder ".", "/home/{pwdf().name}"') self.vagrantfile.appendln("config.disksize.size = '10GB'") self.vagrantfile.appendln('end') # config.vm.synced_folder ".", "/home/dnn" def upifhalted(self): if not self.isup(): self.up() def up(self): assert not self.isup() self._eshell('vagrant up') self._isup = True __enter__ = up def haltifup(self, force=False): if self.isup(): self.halt(force=force) def halt(self, force=False): if (not self.keep_up) or force: assert self.isup() self._eshell('vagrant halt') self._isup = False def __exit__(self, exc_type, exc_val, exc_tb): self.halt() def destroy(self, force=False): force = ' -f' if force else '' self._eshell(f'vagrant destroy{force}') self._isup = False def _shell_output(self, command): return self._shell(command).all_output() def status(self): stat = self._shell_output('vagrant status') return stat def global_status(self): self._eshell('vagrant global_status') def _eshell(self, command): return self._shell(command).interact() def _shell(self, command): return shell(command) def _shell_do(self, command): return self._shell(command) def _shell_output(self, command): return self._shell(command).all_output() # vagrant ssh -- -t "{command}" def ssh_login(self): return SSHExpectProcess(f'vagrant ssh') def send(self, *files, project_name): for f in files: f: File # I am currently not sending vagrant files over scp because home dir is bound in vagrantfile assert f.parent.abspath == self.vagrantfile.parent.abspath def startup(self): if self.restart: self.haltifup() if self._destroy: self.destroy(force=True) # if self._remove: self.remove_box() self.upifhalted() def shutdown(self): self.halt()
class API(ABC): offline_mode: ClassVar[bool] = False apiFile: Union[str, File] def __post_init__(self): self.service = WolframService() self.build_api_fun(self.service) expression = APIFunction( [ APIRule("message", "String"), APIRule("index", "Integer"), APIRule("total", "Integer"), APIRule("messageID", "String"), ], Function( wlexprc('xx'), wlblock( wlexpr('CloudSymbol["APILog"] = "started api base"'), If( wl.Not( wl.FileExistsQ( wl.CloudObject("APIMessages", wlexpr("$CloudSymbolBase")))), wlexpr('CloudSymbol["APIMessages"]=<||>')), wl.For( wlexpr('i=1'), wlexpr('i<=Length@Keys[CloudSymbol["APIMessages"]]'), wlexpr('i++'), If( wlexpr( '((UnixTime[] * 1000) - ToExpression[StringSplit[(Keys[CloudSymbol["APIMessages"]])[[i]],"***"][[2]]]) > 60000' ), wlexpr( 'apiMessages = CloudSymbol["APIMessages"]; apiMessages = KeyDrop[apiMessages,Keys[CloudSymbol["APIMessages"]][[i]]]; CloudSymbol["APIMessages"] = apiMessages;' ))), If( wl.Not( wl.KeyExistsQ(wl.CloudSymbol("APIMessages"), wlexpr('xx["messageID"]'))), wlexpr( 'APIMessages=CloudSymbol["APIMessages"]; APIMessages[xx["messageID"]] = {}; CloudSymbol["APIMessages"] = APIMessages;' )), wlexpr( 'thisMessageData = <|"i"->xx["index"],"t"->xx["total"],"m"->xx["message"]|>; APIMessages=CloudSymbol["APIMessages"]; myMessages = APIMessages[xx["messageID"]]; myMessages = Append[myMessages,thisMessageData]; APIMessages[xx["messageID"]] = myMessages; CloudSymbol["APIMessages"] = APIMessages;' ), If( wlexpr('thisMessageData["i"]==thisMessageData["t"]'), wlblock( wlexpr( 'fullMessage = StringJoin[Map[Function[xxxx,xxxx["m"]],CloudSymbol["APIMessages"][xx["messageID"]]]]' ), wlexpr( 'fullMessage = ImportString[fullMessage,"RawJSON"]' ), *self.service.build_expressions(), )), ))) expression = FormatWLInput(inputForm(expression)) self.apiFile = File(self.apiFile) assert self.apiFile.ext == 'wl', f'extension of {self.apiFile} is {self.apiFile.ext}' self.apiURL = self.apiFile.wcurl self.apiFile.write(expression) if not self.offline_mode: MWL.cloud_deploy(expression, self.apiFile, PERMISSIONS.PUBLIC) else: warn(f'not deploying {self} because offline mode is switched one') log(f'{self.apiURL=}') def apiElements(self): return arg_tags(API_URL=self.apiURL) _GOT_CS = set() @classmethod @abstractmethod def cs(cls): # assert cls not in API._GOT_CS # was a good idea for single page sites. But I have a multi page site now and I don't have time to make all these sites use the same javascript from one location. API._GOT_CS.add(cls) @abstractmethod def build_api_fun(self, serv: WolframService): pass