Pythonic way is to use with. In that case close is automatic as soon as we get outsude of the context:

ClassMethod ReadFileUsingPython(pFile As %String) [ Language = python ]
{
  from datetime import datetime
  import iris
  time1 = datetime.timestamp(datetime.now())
  print(time1)
  if pFile=="":
    raise Exception("filename is required.")

  with open(pFile,"r", encoding="utf-8", errors="ignore") as file:
    log = iris.cls('otw.log.Log')
    for line in file:
      status = log.ImportLine(line)

  time2 = datetime.timestamp(datetime.now())
  print(time2)
  print("Execution time: ",(time2-time1))
}

For cross-namespace queries the easiest way is to map packages/globals but that might not be a recommended approach for an audit table.

You can do this:

  1. In your production namespace create a new table with the same structure as your audit select query backed by PPG storage.
  2. Switch to the audit namespace.
  3. Run audit query, iterate the results and write them into the PPG.
  4. Switch into a production namespace.
  5. Run query against your PPG table, joining any local tables.

Enable %Ensemble/%Production/ModifyConfiguration in System Audit Events:

After that you should see these events:

Try to export the project with one deployed class. Open exported xml and check if the class is there and deployed.

Use args... to supply a variable number of parameters:

ClassMethod DoCleverStuf(args...) As %Status [ CodeMode = objectgenerator ]
{
    do %code.WriteLine("    For i=1:1:args {")
    do %code.WriteLine("        Write args(i)")
    do %code.WriteLine("    }")
    do %code.WriteLine("    Set tSC = $$$OK")
    ...
}

can I generate a whole method at compile time?

You can use projections to do that. Here's an example.

Assuming you have a sync mirror established, adding new db to mirror is as simple as:

  1. Create DB on Primary.
  2. Run SYS.Mirror:AddDatabase. It returns %Status, check that it's ok with $$$ISOK(sc). It should be equal to 1.
  3. Dismount database on Primary (using SYS.Database:DismountDatabase) OR Freeze IRIS (Backup.General:ExternalFreeze).
  4. Copy IRIS.DAT to Backup.
  5. Mount database on Primary (using SYS.Database:MountDatabase) OR Thaw IRIS (Backup.General:ExternalThaw).
  6. Mount database on Backup.
  7. Activate database on Backup (SYS.Mirror:ActivateMirroredDatabase).
  8. Catchup database on Backup (SYS.Mirror:CatchupDB).

Please note that some methods accept db name, most accept db directory, and others db sfn. Please keep that in mind.

Try: ##class(%Studio.Project).InstallFromFile( "/display=none /displaylog=0 /displayerror=0")

Database is a physical file containing globals.

Namespace is a logical combination of one or more databases.

By default Namespace has two databases:

  • GLOBALS - default location for globals
  • ROUTINES - default location for code (classes/routines/includes)

In addition to that, namespace can have any amount of mappings. Mappings map specified globals/code from a specified database.

When you try to access a global, first global mappings are searched for this global, if no mappings are found, the GLOBALS database is used.

When you try to access some code, first package/routine mappings are searched for this code, if no mappings are found, the ROUTINES database is used.

To split data innto a separate DB:

  1. Create target DB.
  2. Make source DB RO (by forcefully logging users out for example and/or marking it as RO).
  3. Copy data/code from the source to target DB (for globals use ^GBLOCKCOPY).
  4. Create mapping from the target DB to your namespace.
  5. Confirm that data is present.
  6. Delete data from a source DB.