Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b89ca28
Modify __init__.py to avoid conflicts with rel-v7r2
chrisburr Jan 14, 2021
0bd3288
Fix setup.py installation
chrisburr Dec 10, 2020
c161106
PY3: Modernise various imports
chrisburr Dec 10, 2020
009c7a9
PY3: Rename some scripts to have _ instead of - to ensure they're val…
chrisburr Dec 10, 2020
6f21685
PY3: Add DIRACScript object and DIRAC's extension_metadata entrypoint
chrisburr Dec 10, 2020
b711435
PY3: Add entrypoints for dirac-info, dirac-proxy-init and dirac-proxy…
chrisburr Dec 10, 2020
df5bae4
Replace _ with - when creating script documentation
chrisburr Dec 10, 2020
88d5a6e
PY3: Set DIRAC.__version__ using setuptools metadata
chrisburr Dec 10, 2020
1fa9f79
Apply review comments
chrisburr Dec 17, 2020
105d82a
Review comment
chrisburr Jan 13, 2021
5a4cab5
Add documentation for new style scripts
chrisburr Jan 13, 2021
65a1d99
Fix docs
chrisburr Jan 13, 2021
5a248b7
Fix docs some more
chrisburr Jan 13, 2021
35fa239
Fix docs text formatting
chrisburr Jan 13, 2021
6505f58
Rename all scripts to use _ instead of -
chrisburr Jan 13, 2021
d5ec9ff
PY3: Convery most scripts to use DiracScript decorator
chrisburr Jan 13, 2021
704dfa0
Fix filename in py3CheckDirs.txt
chrisburr Jan 13, 2021
6567cc9
PY3: Update ComponentInstaller to account for _ in script names
chrisburr Jan 13, 2021
850a3d5
Use global variables in some required places
chrisburr Jan 13, 2021
780368e
Fix typo
chrisburr Jan 13, 2021
6ba6fb7
PY3: Convert dirac-platform and add shell scripts to setup.cfg
chrisburr Jan 14, 2021
88c6150
PY3: Convert tornado scripts to be setup.cfg compatible
chrisburr Jan 14, 2021
fa95a5c
Fix formatting
chrisburr Jan 14, 2021
f0392ea
Restore dirac-agent.py dirac-executor.py and dirac-service.py from in…
chrisburr Jan 14, 2021
35931a0
Add deprecation notice to dirac-agent.py dirac-executor.py and dirac-…
chrisburr Jan 14, 2021
29f6fa8
Improve console scripts documentation
chrisburr Jan 14, 2021
3b627c7
Add setuptools_scm comment in pyproject.toml
chrisburr Jan 14, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 8 additions & 3 deletions docs/diracdoctools/cmd/commandReference.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ def getScripts(self):
continue

for mT in self.sectionDicts:
if any(pattern in scriptPath for pattern in mT[PATTERN]) and \
not any(pattern in scriptPath for pattern in mT[EXCLUDE]):
if any(pattern in scriptPath.replace("_", "-") for pattern in mT[PATTERN]) and \
not any(pattern in scriptPath.replace("_", "-") for pattern in mT[EXCLUDE]):
mT[SCRIPTS].append(scriptPath)

return
Expand Down Expand Up @@ -93,6 +93,7 @@ def createFilesAndIndex(self, sectionDict):
scriptName = os.path.basename(script)
if scriptName.endswith('.py'):
scriptName = scriptName[:-3]
scriptName = scriptName.replace("_", "-")
Comment thread
chrisburr marked this conversation as resolved.
prefix = sectionDict[PREFIX].lower()
prefix = prefix + '_' if prefix else ''
if self.createScriptDocFiles(script, sectionPath, scriptName, referencePrefix=prefix):
Expand Down Expand Up @@ -120,6 +121,7 @@ def createFiles(self, sectionDict):
scriptName = os.path.basename(script)
if scriptName.endswith('.py'):
scriptName = scriptName[:-3]
scriptName = scriptName.replace("_", "-")
prefix = sectionDict[PREFIX].lower()
prefix = prefix + '_' if prefix else ''
if self.createScriptDocFiles(script, sectionPath, scriptName, referencePrefix=prefix) and \
Expand All @@ -138,7 +140,10 @@ def cleanExistingIndex(self, sectionDict):
If an rst file exists for a command, we move it.
An existing entry for a non existing rst file will create a warning when running sphinx.
"""
existingCommands = {os.path.basename(com).replace('.py', '') for com in sectionDict[SCRIPTS] + sectionDict[MANUAL]}
existingCommands = {
os.path.basename(com).replace('.py', '').replace("_", "-")
for com in sectionDict[SCRIPTS] + sectionDict[MANUAL]
}
sectionPath = os.path.join(self.config.docsPath, sectionDict[SECTION_PATH])
LOG.info('Checking %r for non-existent commands', sectionPath)
# read the script index
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@
__RCSID__ = '$Id$'

from DIRAC import S_OK, S_ERROR, gLogger, exit as DIRACExit
from DIRAC.Core.Utilities.DIRACScript import DIRACScript
Comment thread
chrisburr marked this conversation as resolved.
from DIRAC.Core.Base import Script

cliParams = None
switchDict = None


class Params(object):
'''
Expand Down Expand Up @@ -93,29 +91,27 @@ def parseSwitches():
return switches


# IMPORTANT: Make sure to add the console-scripts entry to setup.cfg as well!
@DIRACScript()
def main():
'''
This is the script main method, which will hold all the logic.
'''
# Script initialization
registerSwitches()
switchDict = parseSwitches()

# Import the required DIRAC modules
from DIRAC.Interfaces.API.Dirac import Dirac

# let's do something
if not len(switchDict['servicesList']):
gLogger.error('No services defined')
DIRACExit(1)
gLogger.notice('We are done')

DIRACExit(0)

if __name__ == "__main__":

# Script initialization
registerSwitches()
switchDict = parseSwitches()

# Import the required DIRAC modules
from DIRAC.Interfaces.API.Dirac import Dirac

# Run the script
if __name__ == "__main__":
main()

# Bye
DIRACExit(0)
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
from DIRAC import exit as DIRACExit
from DIRAC import S_OK, S_ERROR
from DIRAC.Core.Base import Script

# Define a simple class to hold the script parameters
from DIRAC.Core.Utilities.DIRACScript import DIRACScript


# Define a simple class to hold the script parameters
class Params(object):

def __init__(self):
Expand All @@ -34,25 +34,33 @@ def setNumOfPingsToDo(self, value):
return S_OK()


# Instantiate the params class
cliParams = Params()
@DIRACScript()
def main():
# Instantiate the params class
cliParams = Params()

# Register accepted switches and their callbacks
Script.registerSwitch("r", "showRaw", "show raw result from the query", cliParams.setRawResult)
Script.registerSwitch("p:", "numPings=", "Number of pings to do (by default 1)", cliParams.setNumOfPingsToDo)

# Define a help message
Script.setUsageMessage('\n'.join([__doc__,
'Usage:',
' %s [option|cfgfile] <system name to ping>+' % Script.scriptName,
' Specifying a system is mandatory']))

# Parse the command line and initialize DIRAC
Script.parseCommandLine(ignoreErrors=False)

# Register accepted switches and their callbacks
Script.registerSwitch("r", "showRaw", "show raw result from the query", cliParams.setRawResult)
Script.registerSwitch("p:", "numPings=", "Number of pings to do (by default 1)", cliParams.setNumOfPingsToDo)
# Get the list of services
servicesList = Script.getPositionalArgs()

# Define a help message
Script.setUsageMessage('\n'.join([__doc__,
'Usage:',
' %s [option|cfgfile] <system name to ping>+' % Script.scriptName,
' Specifying a system is mandatory']))
# Check and process the command line switches and options
if not servicesList:
Script.showHelp(exitCode=1)

# Parse the command line and initialize DIRAC
Script.parseCommandLine(ignoreErrors=False)
# Do something!

# Get the list of services
servicesList = Script.getPositionalArgs()

# Check and process the command line switches and options
if not servicesList:
Script.showHelp(exitCode=1)
if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
Developing Commands
======================================

.. warning::
This instructions here demonstrate how to support both the legacy (Python 2) and future (Python3) installations of DIRAC.
If only having Python 3 support is acceptable, the requirement for scripts to be in the the *scripts* directory of their parent system will be removed and the only requirement will be for the function to be decorated with the ``@DIRACScript()`` decorator.
Comment thread
chrisburr marked this conversation as resolved.

Commands are one of the main interface tools for the users. Commands are also called *scripts* in DIRAC lingo.

Where to place scripts
Expand Down Expand Up @@ -31,9 +35,33 @@ The instructions below must be applied as close as possible although some variat

which will set the interpreter directive to the python on the environment.

**2.** The next is the documentation line which is describing the command. This same documentation line will be used also the command help information available with the *-h* command switch.
**2.** The next is the documentation line which is describing the command. This same documentation line will be used also the command help information available with the *-h* command switch.

**3.** The majority of the code should be contained with a function, often called ``main`` though this is not required. This function should be wrapped with the ``@DiracScript()`` decorator to allow the DIRAC plugin mechanism to override the script with the function from the highest priority extension.

.. code-block:: python

#Import the required DIRAC modules
from DIRAC.Core.Utilities.DIRACScript import DIRACScript
from DIRAC.Interfaces.API.DIRAC import DIRAC
from DIRAC import gLogger

@DiracScript()
def main()
# Do stuff

if __name__ == "__main__":
main()

**4.** Next the function must be registered as a ``console_scripts`` ``entrypoint`` in the ``setuptools`` metadata (`more details <https://setuptools.readthedocs.io/en/latest/userguide/entry_point.html>`_). This is done by adding a line to the ``console_scripts`` list in ``setup.cfg`` like below, where the first string is the name for the script you want to create, the left hand side of ``:`` is the module that contains your function and the right hand side is the object you want to invoke (e.g. a function).

**3.** Users need to specify parameters to scripts to define what they want to do. To do so, they pass arguments when calling the script. The first thing any script has to do is define what options and arguments the script accepts. Once the valid arguments are defined, the script can parse the command line. An example follows which is a typical command description part
.. code-block:: cfg

console_scripts =
dirac-info = DIRAC.Core.scripts.dirac_info:main
dirac-proxy-info = DIRAC.FrameworkSystem.scripts.dirac_proxy_info:main

**5.** Users need to specify parameters to scripts to define what they want to do. To do so, they pass arguments when calling the script. The first thing any script has to do is define what options and arguments the script accepts. Once the valid arguments are defined, the script can parse the command line. An example follows which is a typical command description part

.. literalinclude:: dirac-ping-info.py

Expand Down Expand Up @@ -61,31 +89,14 @@ All the command line arguments that are not corresponding to the explicitly defi

After defining the switches, the *parseCommandLine()* function has to be called. This method not only parses the command line options but also initializes DIRAC collecting all the configuration data. **It is absolutely important to call this function before importing any other DIRAC module**. The callbacks defined for the switches will be called when parsing the command line if necessary. *Even if the switch is not supposed to receive a parameter, the callback has to receive a value*. Switches without callbacks defined can be obtained with *getUnprocessedSwitches()* function.

**4.** Once the command line has been parsed and DIRAC is properly initialized, the rest of the required DIRAC modules can be imported and the script logic can take place:

.. code-block:: python

#Import the required DIRAC modules
from DIRAC.Interfaces.API.DIRAC import DIRAC
from DIRAC import gLogger
#Do stuff... depending on cliParams.raw, cliParams.pingsToDo and servicesList

def executeCommandLogic()
# Do stuff
gLogger.notice('This is the result of the command')

if __name__ == "__main__":
executeCommandLogic()

**5.** Once the command line has been parsed and DIRAC is properly initialized, the rest of the required DIRAC modules can be imported and the script logic can take place.

Having understood the logic of the script, there are few good practices that must be followed:

* Use *DIRAC.exit( exitCode )* instead of *sys.exit( exitCode )*
* Encapsulate the command code into functions / classes so that it can be easily tested
* Usage of *gLogger* instead of *print* is mandatory. The information in the normal command execution
must be printed out in the NOTICE logging level.
* Use the *if __name__ == "__main__"* close for the actual command execution to avoid running the script
when it is imported.

Example command
-----------------
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[build-system]
Comment thread
chrisburr marked this conversation as resolved.
requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4"]
build-backend = "setuptools.build_meta"

# Enable setuptools_scm to compute the version number from the most recent tag
# https://github.com/pypa/setuptools_scm/#pyprojecttoml-usage
[tool.setuptools_scm]
Comment thread
fstagni marked this conversation as resolved.
Loading