Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@ Coding Style
- Use `PEP8 <http://legacy.python.org/dev/peps/pep-0008/>`__ style. Not
only is this style good for readability in an absolute sense, but
consistent styling helps us all read each other's code.
- This includes module names: all modules, including instrument driver
modules, should be named using lower case ``snake_case``, e.g.
``weinschel_8320.py`` and not ``Weinschel_8320.py``. Vendor and model
capitalization belongs in the class name (``Weinschel8320``), not in the
module name. This is enforced by the ruff rule ``N999``
(``invalid-module-name``). A number of existing driver modules predate this
rule and are exempted in ``pyproject.toml`` because renaming them would
break user code; new modules should not be added to that exemption list.
- There is a command-line tool (``pip install pycodestyle``) you can run after
writing code to validate its style.
- A lot of editors have plugins that will check this for you
Expand Down
4 changes: 4 additions & 0 deletions docs/changes/newsfragments/8356.improved
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The documentation on naming instrument drivers (in the Contributor guide and in the
"Creating Instrument Drivers" example notebook) has been updated to state that instrument driver
modules should be named using lower case ``snake_case``, e.g. ``weinschel_8320.py``. Vendor and
model capitalization belongs in the class name (``Weinschel8320``) and not in the module name.
3 changes: 3 additions & 0 deletions docs/changes/newsfragments/8356.underthehood
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Enable the ruff rule ``N999`` (``invalid-module-name``). Instrument driver modules that are part of the
public ``qcodes`` namespace are exempted via ``lint.pep8-naming.extend-ignore-names`` in ``pyproject.toml``
so that no public module names change. Test modules with invalid names have been renamed to lower case.
21 changes: 13 additions & 8 deletions docs/examples/writing_drivers/Creating-Instrument-Drivers.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,13 @@
"The same rules should apply for QCoDeS-contrib-drivers with the exception that all drivers are stored in subfolders of the drivers folder. \n",
"\n",
"### Naming the Instrument class\n",
"A driver for an instrument with model `Model` and from the vendor `Vendor` should be stored in the file:\n",
"A driver for an instrument with model `Model` and from the vendor `Vendor` should be stored in the module:\n",
"\n",
"```\n",
"qcodes\\instrument_drivers\\{Vendor}\\{Vendor}_{Model}.py \n",
"qcodes\\instrument_drivers\\{Vendor}\\{vendor}_{model}.py \n",
"```\n",
"using snake case with an underscore between the vendor and model name but starting the\n",
"vendor name with upper case.\n",
"i.e. the module (file) name should be all lower case snake case with an underscore between the\n",
"vendor name and the model name.\n",
"\n",
"The primary instrument class should be named as follows:\n",
"```\n",
Expand All @@ -139,12 +139,17 @@
"```\n",
"E.g Vendor followed by Model number in CamelCase.\n",
"\n",
"Note that we use vendor names starting with upper case for both folders and file names.\n",
"Note that we use vendor names starting with upper case for folders but all lower case for module\n",
"(file) names. Module names must be valid lower case snake case identifiers; this is enforced by the\n",
"`N999` (`invalid-module-name`) ruff rule. A number of existing driver modules predate this rule and\n",
"are still named using `Vendor_Model` capitalization. Those are exempted via\n",
"`lint.pep8-naming.extend-ignore-names` in `pyproject.toml`, since renaming them would break user\n",
"code, but no new exemptions should be added.\n",
"\n",
"It is also fine to use an acronym for instrument vendors when there are well established. E.g. drivers for `American Magnetics Inc.` instruments\n",
"may use the acronym `AMI` to refer to the vendor.\n",
"\n",
"As an example the driver for the Weinschel 8320 should be stored in the file `qcodes\\instrument_drivers\\Weinschel\\Weinschel_8320.py` and the \n",
"As an example the driver for the Weinschel 8320 should be stored in the module `qcodes\\instrument_drivers\\Weinschel\\weinschel_8320.py` and the \n",
"class named `Weinschel8320` \n",
"\n",
"### Naming InstrumentModule classes\n",
Expand All @@ -161,11 +166,11 @@
"\n",
"As an example have a look at the Keysight 344xxA series of digital multi meters. To implement drivers for such instruments it is preferable\n",
"to implement a private base class such as `_Keysight344xxA`. This class should be stored either in a `private` subfolder of the Vendor folder or\n",
"in a file starting with an underscore i.e. `_Keysight344xxA.py`. If possible, we prefer a format where `x` is used to signal the parts of the model numbers that \n",
"in a module starting with an underscore i.e. `_keysight_344xxa.py`. If possible, we prefer a format where `x` is used to signal the parts of the model numbers that \n",
"may change. Along with this class subclasses for each of the supported models should be implemented. These may either make small modifications to the baseclass as needed \n",
"or be empty subclasses if no modifications are needed. \n",
"\n",
"E.g. subclasses of the Keysight 344xxA driver for the specific model `34410A` should be named as `Keysight34410A` and stored in `Keysight34410A.py`.\n",
"E.g. subclasses of the Keysight 344xxA driver for the specific model `34410A` should be named as `Keysight34410A` and stored in `keysight_34410a.py`.\n",
"\n"
]
},
Expand Down
154 changes: 153 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ extend-select = [
# it may be worth fixing some or these in the future
# PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed
ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917",
"N999", "BLE001", "TRY004", "TRY002", "S110"] # new defaults of 0.16.0 that we don't want to enable yet
"BLE001", "TRY004", "TRY002", "S110"] # new defaults of 0.16.0 that we don't want to enable yet

# we want to explicitly use the micro symbol
# not the greek letter
Expand All @@ -283,6 +283,158 @@ banned-module-level-imports = [
"xarray", "cf_xarray","pandas", "opencensus", "tqdm.dask", "dask",
"matplotlib", "IPython", "ruamel", "tabulate", "h5netcdf", "PIL", "qcodes_loop"]


[tool.ruff.lint.pep8-naming]
# N999 (invalid-module-name): these instrument driver modules are part of
# the public qcodes namespace so they cannot be renamed to lower case
# without breaking user code. New modules should use lower case names.
extend-ignore-names = [
"_Agilent_344xxA",
"_AimTTi_PL_P",
"_Keithley_2600",
"_Keysight_N5232B",
"_M5065",
"_M5180",
"_M5xxx",
"_TM620",
"Agilent_34401A",
"Agilent_34410A",
"Agilent_34411A",
"Agilent_E8257D",
"Agilent_E8267C",
"Aim_TTi_PL068_P",
"Aim_TTi_PL155_P",
"Aim_TTi_PL303_P",
"Aim_TTi_PL303QMD_P",
"Aim_TTi_PL303QMT_P",
"Aim_TTi_PL601_P",
"Aim_TTi_QL355_TP",
"AMI430_visa",
"ATS",
"ATS_acquisition_controllers",
"ATS9360",
"ATS9373",
"ATS9440",
"ATS9870",
"AWG5014",
"AWG5208",
"AWG70000A",
"AWG70002A",
"AWGFileParser",
"Base_SPDT",
"BaselSP983",
"BaselSP983a",
"BaselSP983c",
"Decadac",
"DP8xx",
"DPO7200xx",
"DynaCool",
"HP_8133A",
"HP_83650A",
"HP_8753D",
"Infiniium",
"Ithaco_1211",
"Keithley_2000",
"Keithley_2400",
"Keithley_2450",
"Keithley_2601B",
"Keithley_2602A",
"Keithley_2602B",
"Keithley_2604B",
"Keithley_2611B",
"Keithley_2612B",
"Keithley_2614B",
"Keithley_2634B",
"Keithley_2635B",
"Keithley_2636B",
"Keithley_3706A",
"Keithley_6500",
"Keithley_7510",
"Keithley_s46",
"Keysight_33210a",
"Keysight_33250a",
"Keysight_33510b",
"Keysight_33511b",
"Keysight_33512b",
"Keysight_33521b",
"Keysight_33522b",
"Keysight_33611a",
"Keysight_33612a",
"Keysight_33621a",
"Keysight_33622a",
"Keysight_34410A_submodules",
"Keysight_34411A_submodules",
"Keysight_34460A_submodules",
"Keysight_34461A_submodules",
"Keysight_34465A_submodules",
"Keysight_34470A_submodules",
"Keysight_344xxA_submodules",
"Keysight_B2962A",
"Keysight_N5173B",
"Keysight_N5183B",
"Keysight_N5222B",
"Keysight_N5230C",
"Keysight_N5245A",
"Keysight_N6705B",
"Keysight_N9030B",
"Keysight_P5002B",
"Keysight_P5004B",
"Keysight_P9374A",
"KeysightAgilent_33XXX",
"KeysightB1500_base",
"KeysightB1500_module",
"KeysightB1500_sampling_measurement",
"KeysightB1511B",
"KeysightB1517A",
"KeysightB1520A",
"KeysightB1530A",
"KtM960x",
"KtM960xDefs",
"KtMAwg",
"KtMAwgDefs",
"Lakeshore_model_325",
"Lakeshore_model_336",
"Lakeshore_model_372",
"MercuryiPS_VISA",
"N51x1",
"N52xx",
"QDac_channels",
"Rigol_DG1062",
"Rigol_DG4000",
"Rigol_DP821",
"Rigol_DP831",
"Rigol_DP832",
"Rigol_DS1074Z",
"Rigol_DS4000",
"Rohde_Schwarz_ZNB20",
"Rohde_Schwarz_ZNB8",
"RTO1000",
"SG384",
"SGS100A",
"SignalHound_USB_SA124B",
"SR560",
"SR830",
"SR860",
"SR865",
"SR865A",
"SR86x",
"Tektronix_70001A",
"Tektronix_70001B",
"Tektronix_70002B",
"Tektronix_DPO5000",
"Tektronix_DPO7000",
"Tektronix_DPO70000",
"Tektronix_DSA70000",
"Tektronix_MSO5000",
"Tektronix_MSO70000",
"TPS2012",
"USBHIDMixin",
"Weinschel_8320",
"Yokogawa_GS200",
"ZNB",
"ZNB20",
]

[tool.ruff.lint.pydocstyle]
convention = "google"

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading