From cd4258643ee00bcb7da49efbc830efe0d0e748b6 Mon Sep 17 00:00:00 2001 From: Maksim Rakitin Date: Thu, 21 Dec 2023 11:45:00 -0500 Subject: [PATCH 1/8] CLN: remove travis-ci config --- .travis.yml | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6c3fb50..0000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: python -python: - - 3.6 -cache: - directories: - - $HOME/.cache/pip - - $HOME/.ccache # https://github.com/travis-ci/travis-ci/issues/5853 - -install: - # Install this package and the packages listed in requirements.txt. - - pip install . - # Install extra requirements for running tests and building docs. - - pip install -r requirements-dev.txt - -script: - - coverage run -m pytest # Run the tests and check for test coverage. - - coverage report -m # Generate test coverage report. - - codecov # Upload the report to codecov. - - flake8 # Enforce code style ('relaxed' line length limit is set in .flake8 config file). - - make -C docs html # Build the documentation. From a280e7d4f0fbc8c17e2118ea3747a903eff7a287 Mon Sep 17 00:00:00 2001 From: Maksim Rakitin Date: Thu, 21 Dec 2023 11:48:22 -0500 Subject: [PATCH 2/8] MNT: add GeRM handlers --- nsls2_detector_handlers/germ.py | 26 ++++++++++++++++++++++++++ requirements.txt | 1 + 2 files changed, 27 insertions(+) create mode 100644 nsls2_detector_handlers/germ.py diff --git a/nsls2_detector_handlers/germ.py b/nsls2_detector_handlers/germ.py new file mode 100644 index 0000000..f77c8b3 --- /dev/null +++ b/nsls2_detector_handlers/germ.py @@ -0,0 +1,26 @@ +from . import HandlerBase +import h5py +import tifffile + +class AreaDetectorTiffHandlerGERM(HandlerBase): + specs = {"AD_TIFF_GERM"} + + def __init__(self, fpath): + self._path = os.path.join(fpath, "") + + def __call__(self): + ret = [] + with tifffile.TiffFile(self._path) as tif: + ret.append(tif.asarray()) + return np.array(ret) + + +class AreaDetectorHDF5HandlerGERM(HandlerBase): + specs = {"AD_HDF5_GERM"} + def __init__(self, filename): + self._name = filename + + def __call__(self, frame): + with h5py.File(self._name, "r") as f: + entry = f["/entry/data/data"] + return entry[frame, :] diff --git a/requirements.txt b/requirements.txt index 36168ff..0de308d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ h5py numpy pandas +tifffile From 5adc02274c437f8982ae18f58498a1bf2860bbdb Mon Sep 17 00:00:00 2001 From: Maksim Rakitin Date: Thu, 21 Dec 2023 11:52:53 -0500 Subject: [PATCH 3/8] STY: reformat with `pre-commit` --- .codecov.yml | 2 +- .pre-commit-config.yaml | 30 +++ CONTRIBUTING.rst | 1 - docs/source/conf.py | 95 +++++---- nsls2_detector_handlers/__init__.py | 2 +- nsls2_detector_handlers/_version.py | 154 ++++++++------ nsls2_detector_handlers/electrometer.py | 31 ++- nsls2_detector_handlers/germ.py | 8 +- nsls2_detector_handlers/pizzabox.py | 43 ++-- nsls2_detector_handlers/srx_flyscans.py | 4 +- nsls2_detector_handlers/webcam.py | 5 +- setup.py | 60 +++--- versioneer.py | 267 +++++++++++++++--------- 13 files changed, 434 insertions(+), 268 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.codecov.yml b/.codecov.yml index 4ac1b0a..20ad66b 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,4 +1,4 @@ -# show coverage in CI status, not as a comment. +# show coverage in CI status, not as a comment. comment: off coverage: status: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..c506033 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,30 @@ +default_language_version: + python: python3 +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/ambv/black + rev: 23.3.0 + hooks: + - id: black + language_version: python3.10 + - id: black-jupyter + language_version: python3.10 + exclude: ^(.*\.py) + args: [--line-length=88] + - repo: https://github.com/pycqa/flake8 + rev: 6.0.0 + hooks: + - id: flake8 + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort + - repo: https://github.com/kynan/nbstripout + rev: 0.6.1 + hooks: + - id: nbstripout diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 481026e..c6fcfcc 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -101,4 +101,3 @@ Before you submit a pull request, check that it meets these guidelines: 3. The pull request should work for Python 2.7, 3.3, 3.4, 3.5 and for PyPy. Check https://travis-ci.org/bluesky/nsls2-detector-handlers/pull_requests and make sure that the tests pass for all supported Python versions. - diff --git a/docs/source/conf.py b/docs/source/conf.py index 13a1c85..4d3c21d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -32,17 +32,17 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.githubpages', - 'sphinx.ext.intersphinx', - 'sphinx.ext.mathjax', - 'sphinx.ext.viewcode', - 'IPython.sphinxext.ipython_directive', - 'IPython.sphinxext.ipython_console_highlighting', - 'matplotlib.sphinxext.plot_directive', - 'numpydoc', - 'sphinx_copybutton', + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.githubpages", + "sphinx.ext.intersphinx", + "sphinx.ext.mathjax", + "sphinx.ext.viewcode", + "IPython.sphinxext.ipython_directive", + "IPython.sphinxext.ipython_console_highlighting", + "matplotlib.sphinxext.plot_directive", + "numpydoc", + "sphinx_copybutton", ] # Configuration options for plot_directive. See: @@ -55,27 +55,28 @@ numpydoc_show_class_members = False # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'nsls2-detector-handlers' -copyright = '2020, Brookhaven National Laboratory' -author = 'Brookhaven National Laboratory' +project = "nsls2-detector-handlers" +copyright = "2020, Brookhaven National Laboratory" +author = "Brookhaven National Laboratory" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # import nsls2_detector_handlers + # The short X.Y version. version = nsls2_detector_handlers.__version__ # The full version, including alpha/beta/rc tags. @@ -94,7 +95,7 @@ exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -105,8 +106,9 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" import sphinx_rtd_theme + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # Theme options are theme-specific and customize the look and feel of a theme @@ -118,7 +120,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -126,9 +128,9 @@ # This is required for the alabaster theme # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars html_sidebars = { - '**': [ - 'relations.html', # needs 'show_related': True theme option to display - 'searchbox.html', + "**": [ + "relations.html", # needs 'show_related': True theme option to display + "searchbox.html", ] } @@ -136,7 +138,7 @@ # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'nsls2-detector-handlers' +htmlhelp_basename = "nsls2-detector-handlers" # -- Options for LaTeX output --------------------------------------------- @@ -145,15 +147,12 @@ # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # # 'preamble': '', - # Latex figure (float) alignment # # 'figure_align': 'htbp', @@ -163,8 +162,13 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'nsls2-detector-handlers.tex', 'nsls2-detector-handlers Documentation', - 'Contributors', 'manual'), + ( + master_doc, + "nsls2-detector-handlers.tex", + "nsls2-detector-handlers Documentation", + "Contributors", + "manual", + ), ] @@ -173,8 +177,13 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'nsls2-detector-handlers', 'nsls2-detector-handlers Documentation', - [author], 1) + ( + master_doc, + "nsls2-detector-handlers", + "nsls2-detector-handlers Documentation", + [author], + 1, + ) ] @@ -184,19 +193,23 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'nsls2-detector-handlers', 'nsls2-detector-handlers Documentation', - author, 'nsls2-detector-handlers', 'Staging repo for handlers specific to NSLS-II', - 'Miscellaneous'), + ( + master_doc, + "nsls2-detector-handlers", + "nsls2-detector-handlers Documentation", + author, + "nsls2-detector-handlers", + "Staging repo for handlers specific to NSLS-II", + "Miscellaneous", + ), ] - - # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { - 'python': ('https://docs.python.org/3/', None), - 'numpy': ('https://docs.scipy.org/doc/numpy/', None), - 'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None), - 'pandas': ('https://pandas.pydata.org/pandas-docs/stable', None), - 'matplotlib': ('https://matplotlib.org', None), + "python": ("https://docs.python.org/3/", None), + "numpy": ("https://docs.scipy.org/doc/numpy/", None), + "scipy": ("https://docs.scipy.org/doc/scipy/reference/", None), + "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None), + "matplotlib": ("https://matplotlib.org", None), } diff --git a/nsls2_detector_handlers/__init__.py b/nsls2_detector_handlers/__init__.py index 4ff432b..d9b3e90 100644 --- a/nsls2_detector_handlers/__init__.py +++ b/nsls2_detector_handlers/__init__.py @@ -1,6 +1,6 @@ from ._version import get_versions -__version__ = get_versions()['version'] +__version__ = get_versions()["version"] del get_versions diff --git a/nsls2_detector_handlers/_version.py b/nsls2_detector_handlers/_version.py index ee9f943..eadbc4e 100644 --- a/nsls2_detector_handlers/_version.py +++ b/nsls2_detector_handlers/_version.py @@ -1,4 +1,3 @@ - # This file helps to compute a version number in source trees obtained from # git-archive tarball (such as those provided by githubs download-from-tag # feature). Distribution tarballs (built by setup.py sdist) and build @@ -58,17 +57,18 @@ class NotThisMethod(Exception): def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f + return decorate -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) p = None @@ -76,10 +76,13 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, try: dispcmd = str([c] + args) # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) + p = subprocess.Popen( + [c] + args, + cwd=cwd, + env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr else None), + ) break except EnvironmentError: e = sys.exc_info()[1] @@ -116,16 +119,22 @@ def versions_from_parentdir(parentdir_prefix, root, verbose): for i in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} + return { + "version": dirname[len(parentdir_prefix) :], + "full-revisionid": None, + "dirty": False, + "error": None, + "date": None, + } else: rootdirs.append(root) root = os.path.dirname(root) # up a level if verbose: - print("Tried directories %s but none started with prefix %s" % - (str(rootdirs), parentdir_prefix)) + print( + "Tried directories %s but none started with prefix %s" + % (str(rootdirs), parentdir_prefix) + ) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") @@ -181,7 +190,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + tags = set([r[len(TAG) :] for r in refs if r.startswith(TAG)]) if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %d @@ -190,7 +199,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) + tags = set([r for r in refs if re.search(r"\d", r)]) if verbose: print("discarding '%s', no digits" % ",".join(refs - tags)) if verbose: @@ -198,19 +207,26 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] + r = ref[len(tag_prefix) :] if verbose: print("picking %s" % r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} + return { + "version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, + "error": None, + "date": date, + } # no suitable tags, so version is "0+unknown", but full hex is still there if verbose: print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} + return { + "version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, + "error": "no suitable tags", + "date": None, + } @register_vcs_handler("git", "pieces_from_vcs") @@ -225,8 +241,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) if rc != 0: if verbose: print("Directory %s not under git control" % root) @@ -234,10 +249,19 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%s*" % tag_prefix], - cwd=root) + describe_out, rc = run_command( + GITS, + [ + "describe", + "--tags", + "--dirty", + "--always", + "--long", + "--match", + "%s*" % tag_prefix, + ], + cwd=root, + ) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") @@ -260,17 +284,16 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): dirty = git_describe.endswith("-dirty") pieces["dirty"] = dirty if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] + git_describe = git_describe[: git_describe.rindex("-dirty")] # now we have TAG-NUM-gHEX or HEX if "-" in git_describe: # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + mo = re.search(r"^(.+)-(\d+)-g([0-9a-f]+)$", git_describe) if not mo: # unparseable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%s'" - % describe_out) + pieces["error"] = "unable to parse git-describe output: '%s'" % describe_out return pieces # tag @@ -279,10 +302,12 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): if verbose: fmt = "tag '%s' doesn't start with prefix '%s'" print(fmt % (full_tag, tag_prefix)) - pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" - % (full_tag, tag_prefix)) + pieces["error"] = "tag '%s' doesn't start with prefix '%s'" % ( + full_tag, + tag_prefix, + ) return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] + pieces["closest-tag"] = full_tag[len(tag_prefix) :] # distance: number of commits since tag pieces["distance"] = int(mo.group(2)) @@ -293,13 +318,13 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): else: # HEX: no tags pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], - cwd=root)[0].strip() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[ + 0 + ].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces @@ -330,8 +355,7 @@ def render_pep440(pieces): rendered += ".dirty" else: # exception #1 - rendered = "0+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) + rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" return rendered @@ -445,11 +469,13 @@ def render_git_describe_long(pieces): def render(pieces, style): """Render the given version pieces into the requested style.""" if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} + return { + "version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None, + } if not style or style == "default": style = "pep440" # the default @@ -469,9 +495,13 @@ def render(pieces, style): else: raise ValueError("unknown style '%s'" % style) - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} + return { + "version": rendered, + "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], + "error": None, + "date": pieces.get("date"), + } def get_versions(): @@ -485,8 +515,7 @@ def get_versions(): verbose = cfg.verbose try: - return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, - verbose) + return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, verbose) except NotThisMethod: pass @@ -495,13 +524,16 @@ def get_versions(): # versionfile_source is the relative path from the top of the source # tree (where the .git directory might live) to this file. Invert # this to find the root from __file__. - for i in cfg.versionfile_source.split('/'): + for i in cfg.versionfile_source.split("/"): root = os.path.dirname(root) except NameError: - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to find root of source tree", - "date": None} + return { + "version": "0+unknown", + "full-revisionid": None, + "dirty": None, + "error": "unable to find root of source tree", + "date": None, + } try: pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) @@ -515,6 +547,10 @@ def get_versions(): except NotThisMethod: pass - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to compute version", "date": None} + return { + "version": "0+unknown", + "full-revisionid": None, + "dirty": None, + "error": "unable to compute version", + "date": None, + } diff --git a/nsls2_detector_handlers/electrometer.py b/nsls2_detector_handlers/electrometer.py index 0023ecc..4a37193 100644 --- a/nsls2_detector_handlers/electrometer.py +++ b/nsls2_detector_handlers/electrometer.py @@ -11,29 +11,24 @@ class ElectrometerBinFileHandler(HandlerBase): def __init__(self, fpath): # It's a text config file, which we don't store in the resources yet, parsing for now - fpath_txt = f'{os.path.splitext(fpath)[0]}.txt' + fpath_txt = f"{os.path.splitext(fpath)[0]}.txt" self.files = [fpath, fpath_txt] - with open(fpath_txt, 'r') as fp: - N = int(fp.readline().split(':')[1]) - Gains = [int(x) for x in fp.readline().split(':')[1].split(',')] - Offsets = [int(x) for x in fp.readline().split(':')[1].split(',')] - FAdiv = float(fp.readline().split(':')[1]) + with open(fpath_txt, "r") as fp: + Gains = [int(x) for x in fp.readline().split(":")[1].split(",")] + Offsets = [int(x) for x in fp.readline().split(":")[1].split(",")] + FAdiv = float(fp.readline().split(":")[1]) fp.readline() - Ranges = [int(x) for x in fp.readline().split(':')[1].split(',')] - FArate = float(fp.readline().split(':')[1]) + Ranges = [int(x) for x in fp.readline().split(":")[1].split(",")] def Range(val): - ranges = {1: 1, - 2: 10, - 4: 100, - 8: 1000, - 16: 100087} + ranges = {1: 1, 2: 10, 4: 100, 8: 1000, 16: 100087} try: ret = ranges[val] - except: + except Exception: raise ValueError(f'The value "val" can be one of {ranges.keys()}') return ret + # 1566332720 366808768 -4197857 11013120 00 raw_data = np.fromfile(fpath, dtype=np.int32) @@ -46,13 +41,17 @@ def Range(val): raw_data = raw_data.reshape((raw_data.size // num_columns, num_columns)) derived_data = np.zeros((raw_data.shape[0], raw_data.shape[1] - 1)) - derived_data[:, 0] = raw_data[:, -2] + raw_data[:, -1] * 8.0051232 * 1e-9 # Unix timestamp with nanoseconds + derived_data[:, 0] = ( + raw_data[:, -2] + raw_data[:, -1] * 8.0051232 * 1e-9 + ) # Unix timestamp with nanoseconds derived_data[:, 1] = Ra * ((raw_data[:, 0] / FAdiv) - Offsets[0]) / Gains[0] derived_data[:, 2] = Rb * ((raw_data[:, 1] / FAdiv) - Offsets[1]) / Gains[1] derived_data[:, 3] = Rc * ((raw_data[:, 2] / FAdiv) - Offsets[2]) / Gains[2] derived_data[:, 4] = Rd * ((raw_data[:, 3] / FAdiv) - Offsets[3]) / Gains[3] - self.df = pd.DataFrame(data=derived_data, columns=['timestamp', 'i0', 'it', 'ir', 'iff']) + self.df = pd.DataFrame( + data=derived_data, columns=["timestamp", "i0", "it", "ir", "iff"] + ) self.raw_data = raw_data def __call__(self): diff --git a/nsls2_detector_handlers/germ.py b/nsls2_detector_handlers/germ.py index f77c8b3..3af07d1 100644 --- a/nsls2_detector_handlers/germ.py +++ b/nsls2_detector_handlers/germ.py @@ -1,7 +1,12 @@ -from . import HandlerBase +import os + import h5py +import numpy as np import tifffile +from . import HandlerBase + + class AreaDetectorTiffHandlerGERM(HandlerBase): specs = {"AD_TIFF_GERM"} @@ -17,6 +22,7 @@ def __call__(self): class AreaDetectorHDF5HandlerGERM(HandlerBase): specs = {"AD_HDF5_GERM"} + def __init__(self, filename): self._name = filename diff --git a/nsls2_detector_handlers/pizzabox.py b/nsls2_detector_handlers/pizzabox.py index b68e658..52e8e30 100644 --- a/nsls2_detector_handlers/pizzabox.py +++ b/nsls2_detector_handlers/pizzabox.py @@ -8,19 +8,21 @@ class PizzaBoxAnHandlerTxt(HandlerBase): """Read PizzaBox text files using info from filestore.""" - encoder_row = namedtuple('encoder_row', ['ts_s', 'ts_ns', 'index', 'adc']) + encoder_row = namedtuple("encoder_row", ["ts_s", "ts_ns", "index", "adc"]) bases = (10, 10, 10, 16) def __init__(self, fpath, chunk_size): self.chunk_size = chunk_size self.filename = fpath - with open(fpath, 'r') as f: + with open(fpath, "r") as f: self.lines = list(f) def __call__(self, chunk_num): cs = self.chunk_size - return [self.encoder_row(*(int(v, base=b) for v, b in zip(ln.split(), self.bases))) - for ln in self.lines[chunk_num*cs:(chunk_num+1)*cs]] + return [ + self.encoder_row(*(int(v, base=b) for v, b in zip(ln.split(), self.bases))) + for ln in self.lines[chunk_num * cs : (chunk_num + 1) * cs] # noqa E203 + ] def get_file_list(self, datum_kwargs_gen): return [self.filename] @@ -29,18 +31,20 @@ def get_file_list(self, datum_kwargs_gen): class PizzaBoxDIHandlerTxt(HandlerBase): """Read PizzaBox text files using info from filestore.""" - di_row = namedtuple('di_row', ['ts_s', 'ts_ns', 'encoder', 'index', 'di']) + di_row = namedtuple("di_row", ["ts_s", "ts_ns", "encoder", "index", "di"]) def __init__(self, fpath, chunk_size): self.chunk_size = chunk_size self.filename = fpath - with open(fpath, 'r') as f: + with open(fpath, "r") as f: self.lines = list(f) def __call__(self, chunk_num): cs = self.chunk_size - return [self.di_row(*(int(v) for v in ln.split())) - for ln in self.lines[chunk_num*cs:(chunk_num+1)*cs]] + return [ + self.di_row(*(int(v) for v in ln.split())) + for ln in self.lines[chunk_num * cs : (chunk_num + 1) * cs] # noqa E203 + ] def get_file_list(self, datum_kwargs_gen): return [self.filename] @@ -49,19 +53,22 @@ def get_file_list(self, datum_kwargs_gen): class PizzaBoxEncHandlerTxt(HandlerBase): """Read PizzaBox text files using info from filestore.""" - encoder_row = namedtuple('encoder_row', - ['ts_s', 'ts_ns', 'encoder', 'index', 'state']) + encoder_row = namedtuple( + "encoder_row", ["ts_s", "ts_ns", "encoder", "index", "state"] + ) def __init__(self, fpath, chunk_size): self.chunk_size = chunk_size self.filename = fpath - with open(fpath, 'r') as f: + with open(fpath, "r") as f: self.lines = list(f) def __call__(self, chunk_num): cs = self.chunk_size - return [self.encoder_row(*(int(v) for v in ln.split())) - for ln in self.lines[chunk_num*cs:(chunk_num+1)*cs]] + return [ + self.encoder_row(*(int(v) for v in ln.split())) + for ln in self.lines[chunk_num * cs : (chunk_num + 1) * cs] # noqa E203 + ] def get_file_list(self, datum_kwargs_gen): return [self.filename] @@ -72,7 +79,7 @@ class PizzaBoxAnHandlerTxtPD(HandlerBase): """Read PizzaBox text files using info from filestore.""" def __init__(self, fpath): - self.df = pd.read_table(fpath, names=['ts_s', 'ts_ns', 'index', 'adc'], sep=' ') + self.df = pd.read_table(fpath, names=["ts_s", "ts_ns", "index", "adc"], sep=" ") self.filename = fpath def __call__(self): @@ -86,7 +93,9 @@ class PizzaBoxDIHandlerTxtPD(HandlerBase): """Read PizzaBox text files using info from filestore.""" def __init__(self, fpath): - self.df = pd.read_table(fpath, names=['ts_s', 'ts_ns', 'encoder', 'index', 'di'], sep=' ') + self.df = pd.read_table( + fpath, names=["ts_s", "ts_ns", "encoder", "index", "di"], sep=" " + ) self.filename = fpath def __call__(self): @@ -100,7 +109,9 @@ class PizzaBoxEncHandlerTxtPD(HandlerBase): """Read PizzaBox text files using info from filestore.""" def __init__(self, fpath): - self.df = pd.read_table(fpath, names=['ts_s', 'ts_ns', 'encoder', 'index', 'state'], sep=' ') + self.df = pd.read_table( + fpath, names=["ts_s", "ts_ns", "encoder", "index", "state"], sep=" " + ) self.filename = fpath def __call__(self): diff --git a/nsls2_detector_handlers/srx_flyscans.py b/nsls2_detector_handlers/srx_flyscans.py index 2fd1634..281045e 100644 --- a/nsls2_detector_handlers/srx_flyscans.py +++ b/nsls2_detector_handlers/srx_flyscans.py @@ -4,11 +4,11 @@ class ZebraHDF5Handler(HandlerBase): - specs = {'ZEBRA_HDF51', 'SIS_HDF51'} + specs = {"ZEBRA_HDF51", "SIS_HDF51"} def __init__(self, resource_fn): self._resource_fn = resource_fn - self._handle = h5py.File(resource_fn, 'r') + self._handle = h5py.File(resource_fn, "r") def __call__(self, *, column): return self._handle[column][:] diff --git a/nsls2_detector_handlers/webcam.py b/nsls2_detector_handlers/webcam.py index 169b89c..bc5c3b5 100644 --- a/nsls2_detector_handlers/webcam.py +++ b/nsls2_detector_handlers/webcam.py @@ -1,8 +1,11 @@ -from . import HandlerBase import h5py +from . import HandlerBase + + class VideoStreamHDF5Handler(HandlerBase): specs = {"VIDEO_STREAM_HDF5"} + def __init__(self, filename): self._name = filename diff --git a/setup.py b/setup.py index 11a7453..e076069 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,9 @@ -from os import path -from setuptools import setup, find_packages import sys -import versioneer +from os import path +from setuptools import find_packages, setup + +import versioneer # NOTE: This file must remain Python 2 compatible for the foreseeable future, # to ensure that we error out properly for people with outdated setuptools @@ -19,47 +20,52 @@ Upgrade pip like so: pip install --upgrade pip -""".format(*(sys.version_info[:2] + min_version)) +""".format( + *(sys.version_info[:2] + min_version) + ) sys.exit(error) here = path.abspath(path.dirname(__file__)) -with open(path.join(here, 'README.rst'), encoding='utf-8') as readme_file: +with open(path.join(here, "README.rst"), encoding="utf-8") as readme_file: readme = readme_file.read() -with open(path.join(here, 'requirements.txt')) as requirements_file: +with open(path.join(here, "requirements.txt")) as requirements_file: # Parse requirements.txt, ignoring any commented-out lines. - requirements = [line for line in requirements_file.read().splitlines() - if not line.startswith('#')] + requirements = [ + line + for line in requirements_file.read().splitlines() + if not line.startswith("#") + ] setup( - name='nsls2-detector-handlers', + name="nsls2-detector-handlers", version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), description="Staging repo for handlers specific to NSLS-II", long_description=readme, author="Brookhaven National Laboratory", - author_email='dama@bnl.gov', - url='https://github.com/bluesky/nsls2-detector-handlers', - python_requires='>={}'.format('.'.join(str(n) for n in min_version)), - packages=find_packages(exclude=['docs', 'tests']), + author_email="dama@bnl.gov", + url="https://github.com/bluesky/nsls2-detector-handlers", + python_requires=">={}".format(".".join(str(n) for n in min_version)), + packages=find_packages(exclude=["docs", "tests"]), entry_points={ - 'databroker.handlers': [ - 'ZEBRA_HDF51 = nsls2_detector_handlers.srx_flyscans:ZebraHDF5Handler', - 'SIS_HDF51 = nsls2_detector_handlers.srx_flyscans:ZebraHDF5Handler', - 'PIZZABOX_AN_FILE_TXT = nsls2_detector_handlers.pizzabox:PizzaBoxAnHandlerTxt', - 'PIZZABOX_DI_FILE_TXT = nsls2_detector_handlers.pizzabox:PizzaBoxDIHandlerTxt', - 'PIZZABOX_ENC_FILE_TXT = nsls2_detector_handlers.pizzabox:PizzaBoxEncHandlerTxt', - 'PIZZABOX_AN_FILE_TXT_PD = nsls2_detector_handlers.pizzabox:PizzaBoxAnHandlerTxtPD', - 'PIZZABOX_DI_FILE_TXT_PD = nsls2_detector_handlers.pizzabox:PizzaBoxDIHandlerTxtPD', - 'PIZZABOX_ENC_FILE_TXT_PD = nsls2_detector_handlers.pizzabox:PizzaBoxEncHandlerTxtPD', - 'ELECTROMETER = nsls2_detector_handlers.electrometer:ElectrometerBinFileHandler', + "databroker.handlers": [ + "ZEBRA_HDF51 = nsls2_detector_handlers.srx_flyscans:ZebraHDF5Handler", + "SIS_HDF51 = nsls2_detector_handlers.srx_flyscans:ZebraHDF5Handler", + "PIZZABOX_AN_FILE_TXT = nsls2_detector_handlers.pizzabox:PizzaBoxAnHandlerTxt", + "PIZZABOX_DI_FILE_TXT = nsls2_detector_handlers.pizzabox:PizzaBoxDIHandlerTxt", + "PIZZABOX_ENC_FILE_TXT = nsls2_detector_handlers.pizzabox:PizzaBoxEncHandlerTxt", + "PIZZABOX_AN_FILE_TXT_PD = nsls2_detector_handlers.pizzabox:PizzaBoxAnHandlerTxtPD", + "PIZZABOX_DI_FILE_TXT_PD = nsls2_detector_handlers.pizzabox:PizzaBoxDIHandlerTxtPD", + "PIZZABOX_ENC_FILE_TXT_PD = nsls2_detector_handlers.pizzabox:PizzaBoxEncHandlerTxtPD", + "ELECTROMETER = nsls2_detector_handlers.electrometer:ElectrometerBinFileHandler", ], }, include_package_data=True, package_data={ - 'nsls2_detector_handlers': [ + "nsls2_detector_handlers": [ # When adding files here, remember to update MANIFEST.in as well, # or else they will not be included in the distribution on PyPI! # 'path/to/data_file', @@ -68,8 +74,8 @@ install_requires=requirements, license="BSD (3-clause)", classifiers=[ - 'Development Status :: 2 - Pre-Alpha', - 'Natural Language :: English', - 'Programming Language :: Python :: 3', + "Development Status :: 2 - Pre-Alpha", + "Natural Language :: English", + "Programming Language :: Python :: 3", ], ) diff --git a/versioneer.py b/versioneer.py index f84667e..8a2e783 100644 --- a/versioneer.py +++ b/versioneer.py @@ -1,4 +1,3 @@ - # Version: 0.18 """The Versioneer - like a rocketeer, but for versions. @@ -277,6 +276,7 @@ """ from __future__ import print_function + try: import configparser except ImportError: @@ -308,11 +308,13 @@ def get_root(): setup_py = os.path.join(root, "setup.py") versioneer_py = os.path.join(root, "versioneer.py") if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): - err = ("Versioneer was unable to run the project root directory. " - "Versioneer requires setup.py to be executed from " - "its immediate directory (like 'python setup.py COMMAND'), " - "or in a way that lets it use sys.argv[0] to find the root " - "(like 'python path/to/setup.py COMMAND').") + err = ( + "Versioneer was unable to run the project root directory. " + "Versioneer requires setup.py to be executed from " + "its immediate directory (like 'python setup.py COMMAND'), " + "or in a way that lets it use sys.argv[0] to find the root " + "(like 'python path/to/setup.py COMMAND')." + ) raise VersioneerBadRootError(err) try: # Certain runtime workflows (setup.py install/develop in a setuptools @@ -325,8 +327,10 @@ def get_root(): me_dir = os.path.normcase(os.path.splitext(me)[0]) vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) if me_dir != vsr_dir: - print("Warning: build in %s is using versioneer.py from %s" - % (os.path.dirname(me), versioneer_py)) + print( + "Warning: build in %s is using versioneer.py from %s" + % (os.path.dirname(me), versioneer_py) + ) except NameError: pass return root @@ -347,6 +351,7 @@ def get(parser, name): if parser.has_option("versioneer", name): return parser.get("versioneer", name) return None + cfg = VersioneerConfig() cfg.VCS = VCS cfg.style = get(parser, "style") or "" @@ -371,17 +376,18 @@ class NotThisMethod(Exception): def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f + return decorate -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) p = None @@ -389,10 +395,13 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, try: dispcmd = str([c] + args) # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) + p = subprocess.Popen( + [c] + args, + cwd=cwd, + env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr else None), + ) break except EnvironmentError: e = sys.exc_info()[1] @@ -417,7 +426,9 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, return stdout, p.returncode -LONG_VERSION_PY['git'] = ''' +LONG_VERSION_PY[ + "git" +] = ''' # This file helps to compute a version number in source trees obtained from # git-archive tarball (such as those provided by githubs download-from-tag # feature). Distribution tarballs (built by setup.py sdist) and build @@ -992,7 +1003,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + tags = set([r[len(TAG) :] for r in refs if r.startswith(TAG)]) if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %d @@ -1001,7 +1012,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) + tags = set([r for r in refs if re.search(r"\d", r)]) if verbose: print("discarding '%s', no digits" % ",".join(refs - tags)) if verbose: @@ -1009,19 +1020,26 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] + r = ref[len(tag_prefix) :] if verbose: print("picking %s" % r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} + return { + "version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, + "error": None, + "date": date, + } # no suitable tags, so version is "0+unknown", but full hex is still there if verbose: print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} + return { + "version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, + "error": "no suitable tags", + "date": None, + } @register_vcs_handler("git", "pieces_from_vcs") @@ -1036,8 +1054,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) if rc != 0: if verbose: print("Directory %s not under git control" % root) @@ -1045,10 +1062,19 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%s*" % tag_prefix], - cwd=root) + describe_out, rc = run_command( + GITS, + [ + "describe", + "--tags", + "--dirty", + "--always", + "--long", + "--match", + "%s*" % tag_prefix, + ], + cwd=root, + ) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") @@ -1071,17 +1097,16 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): dirty = git_describe.endswith("-dirty") pieces["dirty"] = dirty if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] + git_describe = git_describe[: git_describe.rindex("-dirty")] # now we have TAG-NUM-gHEX or HEX if "-" in git_describe: # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + mo = re.search(r"^(.+)-(\d+)-g([0-9a-f]+)$", git_describe) if not mo: # unparseable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%s'" - % describe_out) + pieces["error"] = "unable to parse git-describe output: '%s'" % describe_out return pieces # tag @@ -1090,10 +1115,12 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): if verbose: fmt = "tag '%s' doesn't start with prefix '%s'" print(fmt % (full_tag, tag_prefix)) - pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" - % (full_tag, tag_prefix)) + pieces["error"] = "tag '%s' doesn't start with prefix '%s'" % ( + full_tag, + tag_prefix, + ) return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] + pieces["closest-tag"] = full_tag[len(tag_prefix) :] # distance: number of commits since tag pieces["distance"] = int(mo.group(2)) @@ -1104,13 +1131,13 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): else: # HEX: no tags pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], - cwd=root)[0].strip() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[ + 0 + ].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces @@ -1166,16 +1193,22 @@ def versions_from_parentdir(parentdir_prefix, root, verbose): for i in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} + return { + "version": dirname[len(parentdir_prefix) :], + "full-revisionid": None, + "dirty": False, + "error": None, + "date": None, + } else: rootdirs.append(root) root = os.path.dirname(root) # up a level if verbose: - print("Tried directories %s but none started with prefix %s" % - (str(rootdirs), parentdir_prefix)) + print( + "Tried directories %s but none started with prefix %s" + % (str(rootdirs), parentdir_prefix) + ) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") @@ -1204,11 +1237,13 @@ def versions_from_file(filename): contents = f.read() except EnvironmentError: raise NotThisMethod("unable to read _version.py") - mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", - contents, re.M | re.S) + mo = re.search( + r"version_json = '''\n(.*)''' # END VERSION_JSON", contents, re.M | re.S + ) if not mo: - mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", - contents, re.M | re.S) + mo = re.search( + r"version_json = '''\r\n(.*)''' # END VERSION_JSON", contents, re.M | re.S + ) if not mo: raise NotThisMethod("no version_json in _version.py") return json.loads(mo.group(1)) @@ -1217,8 +1252,7 @@ def versions_from_file(filename): def write_to_version_file(filename, versions): """Write the given version number to the given _version.py file.""" os.unlink(filename) - contents = json.dumps(versions, sort_keys=True, - indent=1, separators=(",", ": ")) + contents = json.dumps(versions, sort_keys=True, indent=1, separators=(",", ": ")) with open(filename, "w") as f: f.write(SHORT_VERSION_PY % contents) @@ -1250,8 +1284,7 @@ def render_pep440(pieces): rendered += ".dirty" else: # exception #1 - rendered = "0+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) + rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" return rendered @@ -1365,11 +1398,13 @@ def render_git_describe_long(pieces): def render(pieces, style): """Render the given version pieces into the requested style.""" if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} + return { + "version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None, + } if not style or style == "default": style = "pep440" # the default @@ -1389,9 +1424,13 @@ def render(pieces, style): else: raise ValueError("unknown style '%s'" % style) - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} + return { + "version": rendered, + "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], + "error": None, + "date": pieces.get("date"), + } class VersioneerBadRootError(Exception): @@ -1414,8 +1453,9 @@ def get_versions(verbose=False): handlers = HANDLERS.get(cfg.VCS) assert handlers, "unrecognized VCS '%s'" % cfg.VCS verbose = verbose or cfg.verbose - assert cfg.versionfile_source is not None, \ - "please set versioneer.versionfile_source" + assert ( + cfg.versionfile_source is not None + ), "please set versioneer.versionfile_source" assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" versionfile_abs = os.path.join(root, cfg.versionfile_source) @@ -1469,9 +1509,13 @@ def get_versions(verbose=False): if verbose: print("unable to compute version") - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, "error": "unable to compute version", - "date": None} + return { + "version": "0+unknown", + "full-revisionid": None, + "dirty": None, + "error": "unable to compute version", + "date": None, + } def get_version(): @@ -1520,6 +1564,7 @@ def run(self): print(" date: %s" % vers.get("date")) if vers["error"]: print(" error: %s" % vers["error"]) + cmds["version"] = cmd_version # we override "build_py" in both distutils and setuptools @@ -1552,14 +1597,15 @@ def run(self): # now locate _version.py in the new build/ directory and replace # it with an updated value if cfg.versionfile_build: - target_versionfile = os.path.join(self.build_lib, - cfg.versionfile_build) + target_versionfile = os.path.join(self.build_lib, cfg.versionfile_build) print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) + cmds["build_py"] = cmd_build_py if "cx_Freeze" in sys.modules: # cx_freeze enabled? from cx_Freeze.dist import build_exe as _build_exe + # nczeczulin reports that py2exe won't like the pep440-style string # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. # setup(console=[{ @@ -1580,17 +1626,21 @@ def run(self): os.unlink(target_versionfile) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % - {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) + f.write( + LONG + % { + "DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + } + ) + cmds["build_exe"] = cmd_build_exe del cmds["build_py"] - if 'py2exe' in sys.modules: # py2exe enabled? + if "py2exe" in sys.modules: # py2exe enabled? try: from py2exe.distutils_buildexe import py2exe as _py2exe # py3 except ImportError: @@ -1609,13 +1659,17 @@ def run(self): os.unlink(target_versionfile) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % - {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) + f.write( + LONG + % { + "DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + } + ) + cmds["py2exe"] = cmd_py2exe # we override different "sdist" commands for both environments @@ -1642,8 +1696,10 @@ def make_release_tree(self, base_dir, files): # updated value target_versionfile = os.path.join(base_dir, cfg.versionfile_source) print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, - self._versioneer_generated_versions) + write_to_version_file( + target_versionfile, self._versioneer_generated_versions + ) + cmds["sdist"] = cmd_sdist return cmds @@ -1698,11 +1754,13 @@ def do_setup(): root = get_root() try: cfg = get_config_from_root(root) - except (EnvironmentError, configparser.NoSectionError, - configparser.NoOptionError) as e: + except ( + EnvironmentError, + configparser.NoSectionError, + configparser.NoOptionError, + ) as e: if isinstance(e, (EnvironmentError, configparser.NoSectionError)): - print("Adding sample versioneer config to setup.cfg", - file=sys.stderr) + print("Adding sample versioneer config to setup.cfg", file=sys.stderr) with open(os.path.join(root, "setup.cfg"), "a") as f: f.write(SAMPLE_CONFIG) print(CONFIG_ERROR, file=sys.stderr) @@ -1711,15 +1769,18 @@ def do_setup(): print(" creating %s" % cfg.versionfile_source) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - - ipy = os.path.join(os.path.dirname(cfg.versionfile_source), - "__init__.py") + f.write( + LONG + % { + "DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + } + ) + + ipy = os.path.join(os.path.dirname(cfg.versionfile_source), "__init__.py") if os.path.exists(ipy): try: with open(ipy, "r") as f: @@ -1761,8 +1822,10 @@ def do_setup(): else: print(" 'versioneer.py' already in MANIFEST.in") if cfg.versionfile_source not in simple_includes: - print(" appending versionfile_source ('%s') to MANIFEST.in" % - cfg.versionfile_source) + print( + " appending versionfile_source ('%s') to MANIFEST.in" + % cfg.versionfile_source + ) with open(manifest_in, "a") as f: f.write("include %s\n" % cfg.versionfile_source) else: From ea4723de7c443b54961c058058afeb84e2158513 Mon Sep 17 00:00:00 2001 From: Maksim Rakitin Date: Thu, 21 Dec 2023 11:53:34 -0500 Subject: [PATCH 4/8] STY: update pre-commit deps --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c506033..8b49149 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,13 +2,13 @@ default_language_version: python: python3 repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/ambv/black - rev: 23.3.0 + rev: 23.12.0 hooks: - id: black language_version: python3.10 @@ -17,11 +17,11 @@ repos: exclude: ^(.*\.py) args: [--line-length=88] - repo: https://github.com/pycqa/flake8 - rev: 6.0.0 + rev: 6.1.0 hooks: - id: flake8 - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort - repo: https://github.com/kynan/nbstripout From 8e8b9952a4b989e9c80c52287569dda01eda960b Mon Sep 17 00:00:00 2001 From: Maksim Rakitin Date: Thu, 21 Dec 2023 11:55:01 -0500 Subject: [PATCH 5/8] CI: add pre-commit workflow --- .github/workflows/pre-commit.yml | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/pre-commit.yml diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..dde2e82 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,33 @@ +name: pre-commit + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + lint: + # pull requests are a duplicate of a branch push if within the same repo. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository + + name: Check code style + runs-on: ubuntu-latest + strategy: + fail-fast: false + defaults: + run: + shell: bash -l {0} + + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-python@v4 + + - name: Install dev dependencies + run: | + set -vxeuo pipefail + python -m pip install -r requirements-dev.txt + python -m pip list + + - name: Run pre-commit + run: pre-commit run --all-files From 01a48a40d4cc90e76b168f97fbbecb01d23eff2e Mon Sep 17 00:00:00 2001 From: Maksim Rakitin Date: Thu, 21 Dec 2023 11:59:40 -0500 Subject: [PATCH 6/8] STY: allow longer lines --- .isort.cfg | 4 +++ nsls2_detector_handlers/_version.py | 9 ++----- nsls2_detector_handlers/electrometer.py | 4 +-- nsls2_detector_handlers/pizzabox.py | 12 +++------ pyproject.toml | 20 ++++++++++++++ setup.py | 6 +---- versioneer.py | 35 ++++++------------------- 7 files changed, 39 insertions(+), 51 deletions(-) create mode 100644 .isort.cfg create mode 100644 pyproject.toml diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..e0926f4 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,4 @@ +[settings] +line_length = 115 +multi_line_output = 3 +include_trailing_comma = True diff --git a/nsls2_detector_handlers/_version.py b/nsls2_detector_handlers/_version.py index eadbc4e..9266551 100644 --- a/nsls2_detector_handlers/_version.py +++ b/nsls2_detector_handlers/_version.py @@ -131,10 +131,7 @@ def versions_from_parentdir(parentdir_prefix, root, verbose): root = os.path.dirname(root) # up a level if verbose: - print( - "Tried directories %s but none started with prefix %s" - % (str(rootdirs), parentdir_prefix) - ) + print("Tried directories %s but none started with prefix %s" % (str(rootdirs), parentdir_prefix)) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") @@ -322,9 +319,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[ - 0 - ].strip() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces diff --git a/nsls2_detector_handlers/electrometer.py b/nsls2_detector_handlers/electrometer.py index 4a37193..4576c9d 100644 --- a/nsls2_detector_handlers/electrometer.py +++ b/nsls2_detector_handlers/electrometer.py @@ -49,9 +49,7 @@ def Range(val): derived_data[:, 3] = Rc * ((raw_data[:, 2] / FAdiv) - Offsets[2]) / Gains[2] derived_data[:, 4] = Rd * ((raw_data[:, 3] / FAdiv) - Offsets[3]) / Gains[3] - self.df = pd.DataFrame( - data=derived_data, columns=["timestamp", "i0", "it", "ir", "iff"] - ) + self.df = pd.DataFrame(data=derived_data, columns=["timestamp", "i0", "it", "ir", "iff"]) self.raw_data = raw_data def __call__(self): diff --git a/nsls2_detector_handlers/pizzabox.py b/nsls2_detector_handlers/pizzabox.py index 52e8e30..66971cd 100644 --- a/nsls2_detector_handlers/pizzabox.py +++ b/nsls2_detector_handlers/pizzabox.py @@ -53,9 +53,7 @@ def get_file_list(self, datum_kwargs_gen): class PizzaBoxEncHandlerTxt(HandlerBase): """Read PizzaBox text files using info from filestore.""" - encoder_row = namedtuple( - "encoder_row", ["ts_s", "ts_ns", "encoder", "index", "state"] - ) + encoder_row = namedtuple("encoder_row", ["ts_s", "ts_ns", "encoder", "index", "state"]) def __init__(self, fpath, chunk_size): self.chunk_size = chunk_size @@ -93,9 +91,7 @@ class PizzaBoxDIHandlerTxtPD(HandlerBase): """Read PizzaBox text files using info from filestore.""" def __init__(self, fpath): - self.df = pd.read_table( - fpath, names=["ts_s", "ts_ns", "encoder", "index", "di"], sep=" " - ) + self.df = pd.read_table(fpath, names=["ts_s", "ts_ns", "encoder", "index", "di"], sep=" ") self.filename = fpath def __call__(self): @@ -109,9 +105,7 @@ class PizzaBoxEncHandlerTxtPD(HandlerBase): """Read PizzaBox text files using info from filestore.""" def __init__(self, fpath): - self.df = pd.read_table( - fpath, names=["ts_s", "ts_ns", "encoder", "index", "state"], sep=" " - ) + self.df = pd.read_table(fpath, names=["ts_s", "ts_ns", "encoder", "index", "state"], sep=" ") self.filename = fpath def __call__(self): diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..3239179 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,20 @@ +[tool.black] +line-length = 115 +include = '\.pyi?$' +exclude = ''' +/( + \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + + # The following are specific to Black, you probably don't want those. + | blib2to3 + | tests/data +)/ +''' diff --git a/setup.py b/setup.py index e076069..e78c115 100644 --- a/setup.py +++ b/setup.py @@ -32,11 +32,7 @@ with open(path.join(here, "requirements.txt")) as requirements_file: # Parse requirements.txt, ignoring any commented-out lines. - requirements = [ - line - for line in requirements_file.read().splitlines() - if not line.startswith("#") - ] + requirements = [line for line in requirements_file.read().splitlines() if not line.startswith("#")] setup( diff --git a/versioneer.py b/versioneer.py index 8a2e783..d437e09 100644 --- a/versioneer.py +++ b/versioneer.py @@ -327,10 +327,7 @@ def get_root(): me_dir = os.path.normcase(os.path.splitext(me)[0]) vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) if me_dir != vsr_dir: - print( - "Warning: build in %s is using versioneer.py from %s" - % (os.path.dirname(me), versioneer_py) - ) + print("Warning: build in %s is using versioneer.py from %s" % (os.path.dirname(me), versioneer_py)) except NameError: pass return root @@ -1135,9 +1132,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[ - 0 - ].strip() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces @@ -1205,10 +1200,7 @@ def versions_from_parentdir(parentdir_prefix, root, verbose): root = os.path.dirname(root) # up a level if verbose: - print( - "Tried directories %s but none started with prefix %s" - % (str(rootdirs), parentdir_prefix) - ) + print("Tried directories %s but none started with prefix %s" % (str(rootdirs), parentdir_prefix)) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") @@ -1237,13 +1229,9 @@ def versions_from_file(filename): contents = f.read() except EnvironmentError: raise NotThisMethod("unable to read _version.py") - mo = re.search( - r"version_json = '''\n(.*)''' # END VERSION_JSON", contents, re.M | re.S - ) + mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", contents, re.M | re.S) if not mo: - mo = re.search( - r"version_json = '''\r\n(.*)''' # END VERSION_JSON", contents, re.M | re.S - ) + mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", contents, re.M | re.S) if not mo: raise NotThisMethod("no version_json in _version.py") return json.loads(mo.group(1)) @@ -1453,9 +1441,7 @@ def get_versions(verbose=False): handlers = HANDLERS.get(cfg.VCS) assert handlers, "unrecognized VCS '%s'" % cfg.VCS verbose = verbose or cfg.verbose - assert ( - cfg.versionfile_source is not None - ), "please set versioneer.versionfile_source" + assert cfg.versionfile_source is not None, "please set versioneer.versionfile_source" assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" versionfile_abs = os.path.join(root, cfg.versionfile_source) @@ -1696,9 +1682,7 @@ def make_release_tree(self, base_dir, files): # updated value target_versionfile = os.path.join(base_dir, cfg.versionfile_source) print("UPDATING %s" % target_versionfile) - write_to_version_file( - target_versionfile, self._versioneer_generated_versions - ) + write_to_version_file(target_versionfile, self._versioneer_generated_versions) cmds["sdist"] = cmd_sdist @@ -1822,10 +1806,7 @@ def do_setup(): else: print(" 'versioneer.py' already in MANIFEST.in") if cfg.versionfile_source not in simple_includes: - print( - " appending versionfile_source ('%s') to MANIFEST.in" - % cfg.versionfile_source - ) + print(" appending versionfile_source ('%s') to MANIFEST.in" % cfg.versionfile_source) with open(manifest_in, "a") as f: f.write("include %s\n" % cfg.versionfile_source) else: From 2d31fc802a3e557247986e4e771542386cf4571b Mon Sep 17 00:00:00 2001 From: Maksim Rakitin Date: Thu, 21 Dec 2023 12:04:23 -0500 Subject: [PATCH 7/8] MNT: add hadnlers to entrypoints --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index e78c115..518d388 100644 --- a/setup.py +++ b/setup.py @@ -57,6 +57,9 @@ "PIZZABOX_DI_FILE_TXT_PD = nsls2_detector_handlers.pizzabox:PizzaBoxDIHandlerTxtPD", "PIZZABOX_ENC_FILE_TXT_PD = nsls2_detector_handlers.pizzabox:PizzaBoxEncHandlerTxtPD", "ELECTROMETER = nsls2_detector_handlers.electrometer:ElectrometerBinFileHandler", + "AD_TIFF_GERM = nsls2_detector_handlers.germ:AreaDetectorTiffHandlerGERM", + "AD_HDF5_GERM = nsls2_detector_handlers.germ:AreaDetectorHDF5HandlerGERM", + "VIDEO_STREAM_HDF5 = nsls2_detector_handlers.webcam:VideoStreamHDF5Handler", ], }, include_package_data=True, From 813632fe39f0f0111760f07fe1e0401a671220b0 Mon Sep 17 00:00:00 2001 From: Maksim Rakitin Date: Thu, 21 Dec 2023 12:05:27 -0500 Subject: [PATCH 8/8] MNT: add pre-commit into dev deps --- requirements-dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index 8ba29aa..ec0b82b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -3,6 +3,7 @@ codecov coverage flake8 +pre-commit pytest sphinx # These are dependencies of various sphinx extensions for documentation.