Source code for cellpy.cli

import base64
import getpass
import logging
import os
import pathlib
import platform
from pprint import pprint
import re
import subprocess
import sys
import time
from typing import Union
import urllib
from pathlib import Path

import click
import rich

import cellpy._version
from cellpy.exceptions import ConfigFileNotWritten
from cellpy.parameters import prmreader
from cellpy.parameters.internal_settings import OTHERPATHS
from cellpy.internals.core import OtherPath

[docs] DIFFICULT_MISSING_MODULES = {}
try: import cookiecutter.exceptions import cookiecutter.main import cookiecutter.prompt except ModuleNotFoundError: _txt = ( "Could not import cookiecutter (used by cellpy new). Try installing it, for example by writing:" "\n\n python -m pip install cookiecutter\n" ) DIFFICULT_MISSING_MODULES["cookiecutter"] = _txt try: import github from github import Github except ModuleNotFoundError: _txt = ( "Could not import the github library (used by cellpy pull). Try installing it, for example by writing:" "\n\n python -m pip install github\n" ) DIFFICULT_MISSING_MODULES["github"] = _txt try: import sqlalchemy_access except ModuleNotFoundError: _txt = ( "Could not import the sqlalchemy_access library (usually used by when reading arbin .res files " "on windows). If you need it, try installing it by writing:" "\n\n python -m pip install sqlalchemy-access\n" ) DIFFICULT_MISSING_MODULES["sqlalchemy-access"] = _txt try: import lmfit except ModuleNotFoundError: _txt = ( "Could not import the lmfit library (used when fitting ocv rlx data)." " If you think you will need it, try installing it for example by writing:" "\n\n python -m pip install lmfit\n" ) DIFFICULT_MISSING_MODULES["lmfit"] = _txt try: import jinja2_time except ModuleNotFoundError: _txt = ( "Could not import the jinja2_time library (used by cellpy new)." " Try installing it, for example by writing:" "\n\n python -m pip install jinja2_time\n" ) DIFFICULT_MISSING_MODULES["jinja2_time"] = _txt
[docs] VERSION = cellpy._version.__version__
[docs] REPO = "jepegit/cellpy"
[docs] USER = "jepegit"
[docs] GITHUB_PWD_VAR_NAME = "GD_PWD"
[docs] DEFAULT_EDITOR = "vim"
[docs] EDITORS = {"Windows": "notepad"}
[docs] def save_prm_file(prm_filename): """saves (writes) the prms to file""" prmreader._write_prm_file(prm_filename)
[docs] def dump_env_file(env_filename): """saves (writes) the env to file""" click.echo(f" dumping env file to {env_filename}") prmreader._write_env_file(env_filename)
[docs] def get_package_prm_dir(): """gets the folder where the cellpy package lives""" return pathlib.Path(cellpy.parameters.__file__).parent
[docs] def get_default_config_file_path(init_filename=None): """gets the path to the default config-file""" prm_dir = get_package_prm_dir() if not init_filename: init_filename = prmreader.DEFAULT_FILENAME src = prm_dir / init_filename return src
[docs] def get_dst_file(user_dir, init_filename): """gets the destination path for the config-file""" user_dir = pathlib.Path(user_dir) dst_file = user_dir / init_filename return dst_file
[docs] def echo_missing_modules(): """prints out the missing modules""" for m in DIFFICULT_MISSING_MODULES: print(f"missing module: {m}") print(f"message: {DIFFICULT_MISSING_MODULES[m]}")
def _modify_config_file(): pass def _create_cellpy_folders(): pass @click.group("cellpy")
[docs] def cli(): """cellpy - command line interface.""" pass
# ----------------------- setup -------------------------------------- @click.command() @click.option( "--interactive", "-i", is_flag=True, default=False, help="Allows you to specify div. folders and setting.", ) @click.option( "--not-relative", "-nr", is_flag=True, default=False, help="If root-dir is given, put it directly in the root (/) folder" " i.e. don't put it in your home directory. Defaults to False. Remark" " that if you specifically write a path name instead of selecting the" " suggested default, the path you write will be used as is.", ) @click.option( "--dry-run", "-dr", is_flag=True, default=False, help="Run setup in dry mode (only print - do not execute). This is" " typically used when developing and testing cellpy. Defaults to" " False.", ) @click.option( "--reset", "-r", is_flag=True, default=False, help="Do not suggest path defaults based on your current configuration-file", ) @click.option( "--root-dir", "-d", default=None, type=click.Path(), help="Use custom root dir. If not given, your home directory" " will be used as the top level where cellpy-folders" " will be put. The folder path must follow" " directly after this option (if used). Example:\n" " $ cellpy setup -d 'MyDir'", ) @click.option( "--folder-name", "-n", default=None, type=click.Path(), help="", ) @click.option( "--test_user", "-t", default=None, help="Fake name for fake user (for testing)" ) @click.option("--silent", "-s", is_flag=True, help="Silent mode (no questions asked)") @click.option( "--no-deps", "-n", is_flag=True, help="Don't install missing dependencies" )
[docs] def setup( interactive, not_relative, dry_run, reset, root_dir, folder_name, test_user, silent, no_deps, ): """This will help you to set up cellpy.""" click.echo("[cellpy] (setup)") click.echo(f"[cellpy] root-dir: {root_dir}") # notify of missing 'difficult' or optional modules if not no_deps: click.echo("[cellpy] checking dependencies") for m in DIFFICULT_MISSING_MODULES: click.echo(" [cellpy] WARNING! ".center(80, "-")) click.echo("[cellpy] missing dependencies:") click.echo(f"[cellpy] - {m}") click.echo(f"[cellpy] {DIFFICULT_MISSING_MODULES[m]}") click.echo( "[cellpy] (you can skip this check by using the --no-deps option)" ) click.echo(80 * "-") # generate variables init_filename = prmreader.create_custom_init_filename() user_dir, dst_file = prmreader.get_user_dir_and_dst(init_filename) env_file = prmreader.get_env_file_name() if dry_run: click.echo("Create custom init filename and get user_dir and destination") click.echo(f"Got the following parameters:") click.echo(f" - init_filename: {init_filename}") click.echo(f" - user_dir: {user_dir}") click.echo(f" - dst_file: {dst_file}") click.echo(f" - not_relative: {not_relative}") if root_dir and not interactive: click.echo("[cellpy] custom root-dir can only be used in interactive mode") click.echo("[cellpy] -> setting interactive mode") interactive = True if not root_dir: root_dir = user_dir # root_dir = pathlib.Path(os.getcwd()) root_dir = pathlib.Path(root_dir) if dry_run: click.echo(f" - root_dir: {root_dir}") if test_user: click.echo(f"[cellpy] (setup) DEV-MODE test_user: {test_user}") init_filename = prmreader.create_custom_init_filename(test_user) user_dir = root_dir dst_file = get_dst_file(user_dir, init_filename) click.echo(f"[cellpy] (setup) DEV-MODE user_dir: {user_dir}") click.echo(f"[cellpy] (setup) DEV-MODE dst_file: {dst_file}") if not pathlib.Path(dst_file).is_file(): click.echo(f"[cellpy] {dst_file} not found -> I will make one for you") reset = True if not pathlib.Path(env_file).is_file(): click.echo( f"[cellpy] {env_file} not found -> I will make one (but you must edit it yourself)" ) if interactive: click.echo(" interactive mode ".center(80, "-")) _update_paths( custom_dir=root_dir, relative_home=not not_relative, default_dir=folder_name, dry_run=dry_run, reset=reset, interactive=True, ) _write_config_file(user_dir, dst_file, init_filename, dry_run) _write_env_file(user_dir, env_file, dry_run) _check(dry_run=dry_run) else: if reset: _update_paths( user_dir, False, default_dir=folder_name, dry_run=dry_run, reset=True, interactive=False, silent=silent, ) _write_config_file(user_dir, dst_file, init_filename, dry_run) _write_env_file(user_dir, env_file, dry_run) _check(dry_run=dry_run, full_check=False)
def _update_paths( custom_dir=None, relative_home=True, reset=False, dry_run=False, default_dir=None, silent=False, interactive=False, ): # please, refactor me :-( h = prmreader.get_user_dir() if default_dir is None: default_dir = "cellpy_data" if dry_run: click.echo(f" - default_dir: {default_dir}") click.echo(f" - custom_dir: {custom_dir}") click.echo(f" - relative_home: {relative_home}") if custom_dir: reset = True if relative_home: h = h / custom_dir if not custom_dir.parts[-1] == default_dir: h = h / default_dir if not reset: outdatadir = pathlib.Path(prmreader.prms.Paths.outdatadir) rawdatadir = OtherPath(prmreader.prms.Paths.rawdatadir) cellpydatadir = OtherPath(prmreader.prms.Paths.cellpydatadir) filelogdir = pathlib.Path(prmreader.prms.Paths.filelogdir) examplesdir = pathlib.Path(prmreader.prms.Paths.examplesdir) db_path = pathlib.Path(prmreader.prms.Paths.db_path) db_filename = prmreader.prms.Paths.db_filename notebookdir = pathlib.Path(prmreader.prms.Paths.notebookdir) batchfiledir = pathlib.Path(prmreader.prms.Paths.batchfiledir) templatedir = pathlib.Path(prmreader.prms.Paths.templatedir) instrumentdir = pathlib.Path(prmreader.prms.Paths.instrumentsdir) else: outdatadir = "out" rawdatadir = "raw" cellpydatadir = "cellpyfiles" filelogdir = "logs" examplesdir = "examples" db_path = "db" db_filename = "cellpy_db.xlsx" notebookdir = "notebooks" batchfiledir = "batchfiles" templatedir = "templates" instrumentdir = "instruments" outdatadir = h / outdatadir rawdatadir = h / rawdatadir cellpydatadir = h / cellpydatadir filelogdir = h / filelogdir examplesdir = h / examplesdir db_path = h / db_path notebookdir = h / notebookdir batchfiledir = h / batchfiledir templatedir = h / templatedir instrumentdir = h / instrumentdir if dry_run: click.echo(f" - base (h): {h}") if interactive: outdatadir = _ask_about_path( "where to output processed data and results", outdatadir ) rawdatadir = _ask_about_otherpath("where your raw data are located", rawdatadir) cellpydatadir = _ask_about_otherpath("where to put cellpy-files", cellpydatadir) filelogdir = _ask_about_path("where to dump the log-files", filelogdir) examplesdir = _ask_about_path( "where to download cellpy examples and tests", examplesdir ) db_path = _ask_about_path("what folder your db file lives in", db_path) db_filename = _ask_about_name("the name of your db-file", db_filename) notebookdir = _ask_about_path( "where to put your jupyter notebooks", notebookdir ) batchfiledir = _ask_about_path("where to put your batch files", batchfiledir) templatedir = _ask_about_path("where to put your batch files", templatedir) instrumentdir = _ask_about_path("where to put your batch files", instrumentdir) # update folders based on suggestions for d in [ outdatadir, rawdatadir, cellpydatadir, filelogdir, examplesdir, notebookdir, db_path, batchfiledir, templatedir, instrumentdir, ]: if not dry_run: _create_dir(d, confirm=not silent) else: click.echo(f"dry run (so I did not create {d})") # update config-file based on suggestions prmreader.prms.Paths.outdatadir = str(outdatadir) prmreader.prms.Paths.rawdatadir = str(rawdatadir) prmreader.prms.Paths.cellpydatadir = str(cellpydatadir) prmreader.prms.Paths.filelogdir = str(filelogdir) prmreader.prms.Paths.examplesdir = str(examplesdir) prmreader.prms.Paths.db_path = str(db_path) prmreader.prms.Paths.db_filename = str(db_filename) prmreader.prms.Paths.notebookdir = str(notebookdir) prmreader.prms.Paths.batchfiledir = str(batchfiledir) prmreader.prms.Paths.templatedir = str(templatedir) prmreader.prms.Paths.instrumentdir = str(instrumentdir) def _ask_about_path(q, p): click.echo(f"\n[cellpy] (setup) input {q}") click.echo(f"[cellpy] (setup) current: {p}") new_path = input("[cellpy] (setup) new value (press enter to keep) >>> ").strip() if not new_path: new_path = p return pathlib.Path(new_path) def _ask_about_otherpath(q, p): click.echo(f"\n[cellpy] (setup) input {q}") click.echo(f"[cellpy] (setup) current: {p}") new_path = input("[cellpy] (setup) new value (press enter to keep) >>> ").strip() if not new_path: new_path = p return OtherPath(new_path) def _ask_about_name(q, n): click.echo(f"\n[cellpy] (setup) input {q}") click.echo(f"[cellpy] (setup) current: {n}") new_name = input("[cellpy] (setup) new value (press enter to keep) >>> ").strip() if not new_name: new_name = n return new_name def _create_dir(path, confirm=True, parents=True, exist_ok=True): if isinstance(path, OtherPath): if path.is_external: return path o = path.resolve() if not o.is_dir(): o_parent = o.parent create_dir = True if confirm: if not o_parent.is_dir(): create_dir = input( f"\n[cellpy] (setup) {o_parent} does not exist. Create it [y]/n ?" ) if not create_dir: create_dir = True elif create_dir in ["y", "Y"]: create_dir = True else: create_dir = False if create_dir: try: o.mkdir(parents=parents, exist_ok=exist_ok) click.echo(f"[cellpy] (setup) Created {o}") except FileExistsError: click.echo(f"[cellpy] (setup) {o} already exists.") except FileNotFoundError: click.echo(f"[cellpy] (setup) {o} not available.") except Exception as e: click.echo(f"[cellpy] (setup) WARNING! Could not create {o}.") logging.debug(e) click.echo(f"[cellpy] (setup) ...continuing anyway.") else: click.echo(f"[cellpy] (setup) Could not create {o}") return o def _check_import_cellpy(): try: import cellpy from cellpy import log from cellpy.readers import cellreader return True except: click.echo(" Failed to import cellpy") click.echo(" Severity: critical") return False def _check_import_pyodbc(): import platform from cellpy.parameters import prms ODBC = prms._odbc SEARCH_FOR_ODBC_DRIVERS = prms._search_for_odbc_driver use_subprocess = prms.Instruments.Arbin.use_subprocess detect_subprocess_need = prms.Instruments.Arbin.detect_subprocess_need click.echo(f" This is needed for loading Arbin .res files") click.echo(f" parsing prms") click.echo( f" (from your configuration file if it exists, otherwise using defaults)" ) click.echo(f" - ODBC: {ODBC}") click.echo(f" - SEARCH_FOR_ODBC_DRIVERS: {SEARCH_FOR_ODBC_DRIVERS}") click.echo(f" - use_subprocess: {use_subprocess}") click.echo(f" - detect_subprocess_need: {detect_subprocess_need}") click.echo(f" - stated office version: {prms.Instruments.Arbin.office_version}") click.echo(" checking system") is_posix = False is_macos = False if os.name == "posix": is_posix = True click.echo(f" - running on posix") current_platform = platform.system() if current_platform == "Darwin": is_macos = True click.echo(f" - running on a mac") python_version, os_version = platform.architecture() click.echo(f" - python version: {python_version}") click.echo(f" - os version: {os_version}") if not is_posix: if not prms.Instruments.Arbin.sub_process_path: sub_process_path = str(prms._sub_process_path) else: sub_process_path = str(prms.Instruments.Arbin.sub_process_path) click.echo(f" stated path to sub-process: {sub_process_path}") if not os.path.isfile(sub_process_path): click.echo(f" - OBS! missing") if is_posix: click.echo(" checking existence of mdb-export") sub_process_path = "mdb-export" from subprocess import PIPE, run command = ["command", "-v", sub_process_path] try: click.echo(f" - trying to run {command}") result = run( command, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True ) if result.returncode == 0: click.echo(f" - found it!") return True click.echo(f" - could not find {sub_process_path}") if is_macos: driver = "/usr/local/lib/libmdbodbc.dylib" click.echo( f" looks like you are on a mac. Searching for suitable driver: {driver})" ) if not os.path.isfile(driver): click.echo(f" - could not find {driver}") click.echo( " ! If you want to load Arbin .res files you will have to install it manually." ) click.echo(" - Try installing it with brew:\n") click.echo(" brew install mdbtools") return False click.echo(f" - found it: {driver}") return True else: click.echo( " ! If you want to load Arbin .res files you will have to install it manually." ) click.echo(" For example (for ubuntu):\n") click.echo(" sudp apt-get update") click.echo(" sudp apt-get install -y mdbtools") return False except AssertionError: click.echo(" - could not find any suitable driver") return False # not posix - checking for odbc drivers # 1) checking if you have defined one try: driver = prms.Instruments.Arbin.odbc_driver if not driver: raise AttributeError click.echo(" You have defined an odbc driver in your config file") click.echo(f" - driver: {driver}") except AttributeError: click.echo(" FYI: you have not defined any odbc_driver(s)") click.echo( " (The name of the driver from the configuration file is " "used as a backup when cellpy cannot locate a driver by itself)" ) use_ado = False if ODBC == "ado": use_ado = True click.echo(" you stated that you prefer the ado loader") click.echo(" checking if adodbapi is installed") try: import adodbapi as dbloader except ImportError: use_ado = False click.echo(" Failed! Try setting pyodbc as your loader or install") click.echo(" adodbapi (http://adodbapi.sourceforge.net/)") if not use_ado: if ODBC == "pyodbc": click.echo(" you stated that you prefer the pyodbc loader") try: import pyodbc as dbloader except ImportError: click.echo(" Failed! Could not import it.") click.echo(" Try 'pip install pyodbc'") dbloader = None elif ODBC == "pypyodbc": click.echo(" you stated that you prefer the pypyodbc loader") try: import pypyodbc as dbloader except ImportError: click.echo(" Failed! Could not import it.") click.echo(" try 'pip install pypyodbc'") click.echo(" or set pyodbc as your loader in your prm file") click.echo(" (and install it)") dbloader = None click.echo(" searching for odbc drivers") try: drivers = [ driver for driver in dbloader.drivers() if "Microsoft Access Driver" in driver ] click.echo(f" Found these: {drivers}") driver = drivers[0] click.echo(f" - odbc driver: {driver}") return True except IndexError as e: logging.debug(" Unfortunately, it seems the list of drivers is emtpy.") click.echo( "\n Could not find any odbc-drivers suitable for .res-type files. " "Check out the homepage of pydobc for info on installing drivers" ) click.echo( " One solution that might work is downloading " "the Microsoft Access database engine " "(in correct bytes (32 or 64)) " "from:\n" "https://www.microsoft.com/en-us/download/details.aspx?id=13255" ) click.echo( " Or install mdbtools and set it up (check the cellpy docs for help)" ) click.echo("\n") return False def _check_config_file(): prm_file_name = _configloc() env_file_name = _envloc() if env_file_name is None: click.echo(" FYI! Could not locate the environment file") if prm_file_name is None: click.echo(" Could not find the config file") click.echo(" You can create one by running 'cellpy setup'") return False prm_dict = prmreader._read_prm_file_without_updating(prm_file_name) try: prm_paths = prm_dict["Paths"] required_dirs = [ "cellpydatadir", "examplesdir", "filelogdir", "notebookdir", "outdatadir", "rawdatadir", "batchfiledir", "templatedir", "db_path", ] missing = 0 for k in required_dirs: value = prm_paths.get(k, None) click.echo(f" - {k}: {value}") # splitting this into two if-statements to make it easier to debug if OtherPath changes if k in OTHERPATHS: print(f" skipping check for external {k} (for now)") # if not OtherPath( # value # ).is_dir(): # Assuming OtherPath returns True if it is external. # missing += 1 # click.echo("COULD NOT CONNECT!") # click.echo(f"({value} is not a directory)") elif value and not pathlib.Path(value).is_dir(): missing += 1 click.echo(" COULD NOT CONNECT!") click.echo(f" ({value} is not a directory)") if not value: missing += 1 click.echo(" MISSING") value = prm_paths.get("db_filename", None) click.echo(f" - db_filename: {value}") if not value: missing += 1 click.echo(" MISSING") if missing: return False else: return True except Exception as e: click.echo(" Following error occurred:") click.echo(e) return False def _check(dry_run=False, full_check=True): click.echo(" checking ".center(80, "=")) if dry_run: click.echo("*** dry-run: skipping the test") return failed_checks = 0 number_of_checks = 0 def sub_check(check_type, check_func): failed = 0 click.echo(f"[cellpy] * - Checking {check_type}") if check_func(): click.echo(f"[cellpy] -> succeeded!") else: click.echo("f[cellpy] -> failed!!!!") failed = 1 click.echo(80 * "-") return failed check_types = [ "cellpy imports", "importing pyodbc", ] check_funcs = [ _check_import_cellpy, _check_import_pyodbc, ] # additional checks that require loading the config file (not a part of setup) additional_types = ["configuration files"] additional_funcs = [_check_config_file] if full_check: check_types.extend(additional_types) check_funcs.extend(additional_funcs) for ct, cf in zip(check_types, check_funcs): try: failed_checks += sub_check(ct, cf) except Exception as e: click.echo(f"[cellpy] check raised an exception ({e})") number_of_checks += 1 click.echo(" results ".center(80, "=")) succeeded_checks = number_of_checks - failed_checks if failed_checks > 0: click.echo( f"[cellpy] Some of the checks failed! This could potentially be a problem." ) click.echo(f"[cellpy] Failed {failed_checks} out of {number_of_checks} checks.") else: click.echo( f"[cellpy] Succeeded {succeeded_checks} out of {number_of_checks} checks." ) click.echo(80 * "=") def _write_config_file(user_dir, dst_file, init_filename, dry_run): click.echo(" update configuration ".center(80, "-")) click.echo("[cellpy] (setup) Writing configurations to user directory:") click.echo(f"\n {user_dir}\n") if os.path.isfile(dst_file): click.echo("[cellpy] (setup) File already exists!") click.echo("[cellpy] (setup) Keeping most of the old configuration parameters") try: if dry_run: click.echo( f"*** dry-run: skipping actual saving of {dst_file} ***", color="red" ) else: click.echo(f"[cellpy] (setup) Saving file ({dst_file})") save_prm_file(dst_file) except ConfigFileNotWritten: click.echo("[cellpy] (setup) Something went wrong! Could not write the file") click.echo( "[cellpy] (setup) Trying to write a file" + f"called {prmreader.DEFAULT_FILENAME} instead" ) try: user_dir, dst_file = prmreader.get_user_dir_and_dst(init_filename) if dry_run: click.echo( f"*** dry-run: skipping actual saving of {dst_file} ***", color="red", ) else: save_prm_file(dst_file) except ConfigFileNotWritten: _txt = "[cellpy] (setup) No, that did not work either.\n" _txt += "[cellpy] (setup) Well, guess you have to talk to the developers." click.echo(_txt) else: click.echo(f"[cellpy] (setup) Configuration file written!") click.echo( f"[cellpy] (setup) OK! Now you can edit it. For example by " f"issuing \n\n [your-favourite-editor] {init_filename}\n" ) def _write_env_file(user_dir, dst_file, dry_run): click.echo(" update configuration ".center(80, "-")) click.echo("[cellpy] (setup) Writing environment file:") click.echo(f"\n {dst_file}\n") if os.path.isfile(dst_file): click.echo(f"[cellpy] (setup) Environment file {dst_file} already exists!") if not dry_run: return try: if dry_run: click.echo( f"*** dry-run: skipping actual saving of {dst_file} ***", color="red" ) else: click.echo(f"[cellpy] (setup) Saving file ({dst_file})") dump_env_file(dst_file) except ConfigFileNotWritten: _txt = "[cellpy] (setup) No, that did not work either.\n" _txt += "[cellpy] (setup) Well, guess you have to talk to the developers." click.echo(_txt) else: click.echo(f"[cellpy] (setup) Environment file written!") click.echo( f"[cellpy] (setup) OK! Now you can edit it. For example by " f"issuing \n\n [your-favourite-editor] {dst_file}\n" ) def _get_default_editor(): """ Return the default text editor. This code is based on the `editor` library by @rec. """ return os.environ.get("VISUAL") or ( os.environ.get("EDITOR") or EDITORS.get(platform.system(), DEFAULT_EDITOR) ) # ----------------------- edit --------------------------------------- @click.command() @click.option( "--default-editor", "-e", default=None, type=str, help="try to use this editor instead", ) @click.option("--debug", "-d", is_flag=True, help="Run in debug mode.") @click.option("--silent", "-s", is_flag=True, help="Run in silent mode.") @click.argument( "name", type=str, default=None, required=False, )
[docs] def edit(name, default_editor, debug, silent): """Edit your cellpy config or database files. You can use this to edit the configuration file, the database file, or the environment file. If you do not specify which file to edit, the configuration file will be opened. Examples: edit your cellpy configuration file cellpy edit config or just cellpy edit edit your cellpy database file cellpy edit db edit your cellpy environment file using notepad.exe (on Windows) cellpy edit env -e notepad.exe """ if name.lower() == "db": _run_db(debug, silent) return elif name.lower() not in ["env", "config"] and name is not None: click.echo("unknown file") return if name is None or name.lower() == "config": config_file = _configloc() filename = str(config_file.resolve()) if config_file is None: print("could not find the config file") return elif name.lower() == "env": filename = _envloc() if filename is None: print("could not find the env file") return else: filename = name if default_editor is None: default_editor = _get_default_editor() args = [default_editor, filename] click.echo(f"[cellpy] (edit) Calling '{default_editor}'") try: subprocess.call(args) except: click.echo(f"[cellpy] (edit) Failed!") click.echo( "[cellpy] (edit) Try 'cellpy edit -e notepad.exe' if you are on Windows" )
# ----------------------- info --------------------------------------- @click.command() @click.option("--version", "-v", is_flag=True, help="Print version information.") @click.option( "--configloc", "-l", is_flag=True, help="Print full path to the config file." ) @click.option("--params", "-p", is_flag=True, help="Dump all parameters to screen.") @click.option( "--check", "-c", is_flag=True, help="Do a sanity check to see if things works as they should.", )
[docs] def info(version, configloc, params, check): """This will give you some valuable information about your cellpy.""" complete_info = True if check: complete_info = False _check() if version: complete_info = False _version() if configloc: complete_info = False _configloc() if params: complete_info = False _dump_params() if complete_info: _version() _configloc()
# ----------------------- run ---------------------------------------- @click.command() @click.option( "--journal", "-j", is_flag=True, help="Run a batch job defined in the given journal-file", ) @click.option("--key", "-k", is_flag=True, help="Run a batch job defined by batch-name") @click.option( "--folder", "-f", is_flag=True, help="Run all batch jobs iteratively in a given folder", ) @click.option( "--cellpy-project", "-p", is_flag=True, help="Use PaperMill to run the notebook(s) within the given project folder " "(will only work properly if the notebooks can be sorted in correct run-order by 'sorted'). " "Warning! since we are using `click` - the NAME will be 'converted' when it is loaded " "(same as print(name) does) - " "so you can't use backslash ('\\') as normal in windows (use either '/' or '\\\\' instead).", ) @click.option("--debug", "-d", is_flag=True, help="Run in debug mode.") @click.option("--silent", "-s", is_flag=True, help="Run in silent mode.") @click.option("--raw", is_flag=True, help="Force loading raw-file(s).") @click.option("--cellpyfile", is_flag=True, help="Force cellpy-file(s).") @click.option("--minimal", is_flag=True, help="Minimal processing.") @click.option( "--nom-cap", default=None, type=float, help="nominal capacity (used in calculating rates etc)", ) @click.option( "--batch_col", default=None, type=str, help="batch column (if selecting running from db)", ) @click.option( "--project", default=None, type=str, help="name of the project (if selecting running from db)", ) @click.option("--list", "-l", "list_", is_flag=True, help="List batch-files.") @click.argument("name", default="NONE")
[docs] def run( journal, key, folder, cellpy_project, debug, silent, raw, cellpyfile, minimal, nom_cap, batch_col, project, list_, name, ): """Run a cellpy process (for example a batch-job). You can use this to launch specific applications. Examples: run a batch job described in a journal file cellpy run -j my_experiment.json """ if list_: _run_list(name) return if name == "NONE": click.echo( "Usage: cellpy run [OPTIONS] NAME\n" "Try 'cellpy run --help' for help.\n\n" "Error: Missing argument 'NAME'." ) sys.exit(-1) if debug: click.echo("[cellpy] (run) debug mode on") if silent: click.echo("[cellpy] (run) silent mode on") click.echo("[cellpy]\n") if cellpy_project: _run_project(name) elif journal: _run_journal(name, debug, silent, raw, cellpyfile, minimal, nom_cap) elif folder: _run_journals(name, debug, silent, raw, cellpyfile, minimal) elif key: _run_from_db( name, debug, silent, raw, cellpyfile, minimal, nom_cap, batch_col, project, ) else: _run(name, debug, silent)
def _run_from_db( name, debug, silent, raw, cellpyfile, minimal, nom_cap, batch_col, project, ): click.echo( f"running from db \nkey={name}, batch_col={batch_col}, project={project}" ) kwargs = dict() kwargs["name"] = name if debug: kwargs["default_log_level"] = "DEBUG" if not minimal: kwargs["export_raw"] = False kwargs["export_cycles"] = False kwargs["export_ica"] = False if batch_col is not None: kwargs["batch_col"] = batch_col if project is None: kwargs["project"] = "various" else: kwargs["project"] = project click.echo("Warming up ...") from cellpy.utils import batch click.echo(" - starting batch processing") b = batch.process_batch( force_raw_file=raw, force_cellpy=cellpyfile, nom_cap=nom_cap, backend="matplotlib", **kwargs, ) if b is not None and not silent: print(b) click.echo("---") def _run_journal(file_name, debug, silent, raw, cellpyfile, minimal, nom_cap): click.echo(f"running journal {file_name}") # click.echo(f" --debug [{debug}]") # click.echo(f" --silent [{silent}]") # click.echo(f" --raw [{raw}]") # click.echo(f" --cellpyfile [{cellpyfile}]") # click.echo(f" --minimal [{minimal}]") # click.echo(f" --nom_cap [{nom_cap}] {type(nom_cap)}") kwargs = dict() if debug: kwargs["default_log_level"] = "DEBUG" if not minimal: kwargs["export_raw"] = False kwargs["export_cycles"] = False kwargs["export_ica"] = False from cellpy import prms from cellpy.utils import batch batchfiledir = pathlib.Path(prms.Paths.batchfiledir) file = pathlib.Path(file_name) if not file.is_file(): click.echo(f"file_name={file_name} not found - looking into batchfiledir") if not batchfiledir.is_dir(): click.echo("batchfiledir not found - aborting") return file = batchfiledir / file.name if not file.is_file(): click.echo(f"{file} not found - aborting") return b = batch.process_batch( file, force_raw_file=raw, force_cellpy=cellpyfile, nom_cap=nom_cap, backend="matplotlib", **kwargs, ) if b is not None and not silent: print(b) click.echo("---") def _run_list(batchfiledir): from cellpy import prms if batchfiledir == "NONE" or batchfiledir is None: batchfiledir = pathlib.Path(prms.Paths.batchfiledir) else: batchfiledir = pathlib.Path(batchfiledir).resolve() if batchfiledir.is_dir(): click.echo(f"Content of '{batchfiledir}':\n") i = 0 for i, f in enumerate(batchfiledir.glob("cellpy*.json")): click.echo(f"{f.name}") if i: print(f"\nnumber of batch-files located: {i}") else: print("No batch-files found in this directory.") else: click.echo(f"{batchfiledir} not found.") def _run_journals(folder_name, debug, silent, raw, cellpyfile, minimal): click.echo(f"running journals in {folder_name}") # click.echo(f" --debug [{debug}]") # click.echo(f" --silent [{silent}]") # click.echo(f" --raw [{raw}]") # click.echo(f" --cellpyfile [{cellpyfile}]") # click.echo(f" --minimal [{minimal}]") kwargs = dict() if debug: kwargs["default_log_level"] = "DEBUG" if not minimal: kwargs["export_raw"] = False kwargs["export_cycles"] = False kwargs["export_ica"] = False from cellpy.utils import batch folder_name = pathlib.Path(folder_name).resolve() if not folder_name.is_dir(): click.echo(f"{folder_name} not found - aborting") return batch.iterate_batches( folder_name, force_raw_file=raw, force_cellpy=cellpyfile, silent=True, **kwargs ) click.echo("---") def _run_project(our_new_project, **kwargs): try: import papermill as pm except ImportError: click.echo( "[cellpy]: You need to install papermill for automatically execute the notebooks." ) click.echo("[cellpy]: You can install it using pip like this:") click.echo(" >> pip install papermill") return our_new_project = pathlib.Path(our_new_project) click.echo(f"[cellpy]: trying to run notebooks in {our_new_project}") notebooks = sorted(list(our_new_project.glob("*.ipynb"))) for notebook in notebooks: click.echo(f"[cellpy - papermill] running {notebook.name}") pm.execute_notebook(notebook, notebook, parameters=kwargs) def _run(name, debug, silent): click.echo(f"running {name}") click.echo(f" --debug [{debug}]") click.echo(f" --silent [{silent}]") click.echo("[cellpy]: sorry, I am not allowed to run this on my own") def _run_db(debug, silent): import platform from cellpy import prms if not silent: click.echo(f"running database editor") if debug: click.echo("running in debug-mode, but nothing to tell") db_path = Path(prms.Paths.db_path) / prms.Paths.db_filename if platform.system() == "Windows": try: os.system(f'start excel "{str(db_path)}"') except Exception as e: click.echo("Something went wrong trying to open") click.echo(db_path) print() print(e) elif platform.system() == "Linux": click.echo("RUNNING LINUX") # not tested subprocess.check_call(["open", "-a", "Microsoft Excel", db_path]) elif platform.system() == "Darwin": click.echo(f" - running on a mac") subprocess.check_call(["open", "-a", "Microsoft Excel", db_path]) else: print("RUNNING SOMETHING ELSE") print(platform.system()) # not tested subprocess.check_call(["open", "-a", "Microsoft Excel", db_path]) # ----------------------- pull --------------------------------------- @click.command() @click.option("--tests", "-t", is_flag=True, help="Download test-files from repo.") @click.option( "--examples", "-e", is_flag=True, help="Download example-files from repo." ) @click.option("--clone", "-c", is_flag=True, help="Clone the full repo.") @click.option("--directory", "-d", default=None, help="Save into custom directory DIR") @click.option("--password", "-p", default=None, help="Password option for the repo")
[docs] def pull(tests, examples, clone, directory, password): """Download examples or tests from the big internet (needs git).""" if directory is not None: click.echo(f"[cellpy] (pull) custom directory: {directory}") else: directory = pathlib.Path(prmreader.prms.Paths.examplesdir) if password is not None: click.echo("DEV MODE: password provided") if clone: _clone_repo(directory, password) else: if tests: _pull_tests(directory, password) if examples: _pull_examples(directory, password) else: click.echo( f"[cellpy] (pull) Nothing selected for pulling. " f"Please select an option (--tests,--examples, -clone, ...) " )
def _clone_repo(directory, password): directory = pathlib.Path(directory) txt = "[cellpy] The plan is that this " txt += "[cellpy] cmd will pull (clone) the cellpy repo.\n" txt += "[cellpy] For now it only prints the link to the git-hub\n" txt += "[cellpy] repository:\n" txt += "[cellpy]\n" txt += "[cellpy] https://github.com/jepegit/cellpy.git\n" txt += "[cellpy]\n" click.echo(txt) def _pull_tests(directory, pw=None): txt = ( "[cellpy] (pull) Pulling tests from", " https://github.com/jepegit/cellpy.git", ) click.echo(txt) _pull(gdirpath="tests", rootpath=directory, pw=pw) _pull(gdirpath="testdata", rootpath=directory, pw=pw) def _pull_examples(directory, pw): txt = ( "[cellpy] (pull) Pulling examples from", " https://github.com/jepegit/cellpy.git", ) click.echo(txt) _pull(gdirpath="examples", rootpath=directory, pw=pw) def _version(): version_text = "[cellpy] version: " + str(VERSION) click.echo(version_text) def _configloc(): _, config_file_name = prmreader.get_user_dir_and_dst() click.echo(f"[cellpy] -> {config_file_name}") if not os.path.isfile(config_file_name): click.echo("[cellpy] File does not exist!") else: return config_file_name def _envloc(): env_file_name = prmreader.get_env_file_name() click.echo(f"[cellpy] (from config) -> {env_file_name}") if not os.path.isfile(env_file_name): return return env_file_name def _dump_params(): click.echo("[cellpy] Running prmreader.info:\n") prmreader.info() def _download_g_blob(name, local_path): import urllib.request dirs = local_path.parent if not dirs.is_dir(): click.echo(f"[cellpy] (pull) creating dir: {dirs}") dirs.mkdir(parents=True) print(f"[cellpy] (pull) downloading blob: {name.download_url}") filename, headers = urllib.request.urlretrieve( name.download_url, filename=local_path ) click.echo(f"[cellpy] (pull) downloaded blob: {filename}") def _parse_g_subdir(stuff, repo, gdirpath): """recursive function for parsing repo subdirectories""" for f in repo.get_contents(gdirpath): if f.type != "dir": stuff.append(f) else: _parse_g_subdir(stuff, repo, f.path) def _parse_g_dir(repo, gdirpath): """yields content of repo directory""" stuff = [] _parse_g_subdir(stuff, repo, gdirpath) for f in stuff: yield f def _get_user_name(): return "jepegit" def _get_pw(method): if method == "ask": return getpass.getpass() elif method == "env": return os.environ.get(GITHUB_PWD_VAR_NAME, None) else: return None def _pull(gdirpath="examples", rootpath=None, u=None, pw=None): if rootpath is None: rootpath = prmreader.prms.Paths.examplesdir rootpath = pathlib.Path(rootpath) ndirpath = rootpath / gdirpath if pw is not None: click.echo(" DEV MODE ".center(80, "-")) u = _get_user_name() if pw == "ask": click.echo(" - ask for password") pw = _get_pw(pw) elif pw == "env": click.echo(" - check environ for password ") pw = _get_pw(pw) click.echo(" - got something") if pw is None: click.echo(" - only None") u = None g = Github(u, pw) try: repo = g.get_repo(REPO) except github.RateLimitExceededException: click.echo(" - rate limit exceeded") click.echo(" - waiting 60 seconds, and trying only once more") click.echo( " - hint! you can check status directly using the github api, e.g. " ) click.echo(" $ curl -i https://api.github.com/users/USERNAME") click.echo(" - press ctrl-c to abort") time.sleep(60) repo = g.get_repo(REPO) click.echo(f"[cellpy] (pull) pulling {gdirpath}") click.echo(f"[cellpy] (pull) -> {ndirpath}") if not ndirpath.is_dir(): click.echo(f"[cellpy] (pull) creating dir: {ndirpath}") ndirpath.mkdir(parents=True) for gfile in _parse_g_dir(repo, gdirpath): gfilename = pathlib.Path(gfile.path) nfilename = rootpath / gfilename try: _download_g_blob(gfile, nfilename) except github.RateLimitExceededException: click.echo(" - rate limit exceeded") click.echo(" - waiting 60 seconds, and trying only once more") click.echo(" - press ctrl-c to abort") time.sleep(60) _download_g_blob(gfile, nfilename) def _get_default_template(): template = "standard" try: template = prmreader.prms.Batch.template except: logging.debug("You dont have any default template defined in you .conf file") return template def _read_local_templates(local_templates_path=None): if local_templates_path is None: local_templates_path = pathlib.Path(prmreader.prms.Paths.templatedir) templates = {} for p in list(local_templates_path.rglob("cellpy_cookie*.zip")): label = p.stem.strip()[len("cellpy_cookie_") :] templates[label] = (str(p), None) logging.debug(f"Found the following templates: {templates}") return templates # ----------------------- new ---------------------------------------- @click.command() @click.option("--template", "-t", help="Provide template name.") @click.option("--directory", "-d", default=None, help="Create in custom directory.") @click.option( "--project", "-p", default=None, help="Provide project name (i.e. sub-directory name).", ) @click.option( "--experiment", "-e", default=None, help="Provide experiment name (i.e. lookup-value).", ) @click.option( "--local-user-template", "-u", is_flag=True, default=False, help="Use local template from the templates directory.", ) @click.option("--serve", "-s", "serve_", is_flag=True, help="Run Jupyter.") @click.option( "--run", "-r", "run_", is_flag=True, help="Use PaperMill to run the notebook(s) from the template (will only work properly if " "the notebooks can be sorted in correct run-order by 'sorted' and " "cellpy can find the jupyter executable).", ) @click.option( "--lab", "-j", is_flag=True, help="Use Jupyter Lab instead of Notebook when serving.", ) @click.option( "--jupyter-executable", default=None, help="Jupyter executable.", ) @click.option( "--list", "-l", "list_", is_flag=True, help="List available templates and exit." )
[docs] def new( template, directory, project, experiment, local_user_template, serve_, run_, lab, jupyter_executable, list_, ): """Set up a batch experiment (might need git installed).""" _new( template, directory=directory, project_dir=project, session_id=experiment, local_user_template=local_user_template, serve_=serve_, run_=run_, lab=lab, executable=jupyter_executable, list_=list_, )
def _new( template: str, directory: Union[Path, str, None] = None, project_dir: Union[str, None] = None, local_user_template: bool = False, serve_: bool = False, run_: bool = False, lab: bool = False, list_: bool = False, executable: Union[str, None] = None, session_id: str = "experiment_001", no_input: bool = False, cookie_directory: str = "", ): """Set up a batch experiment (might need git installed). Args: template: short-name of template. directory: the directory for your cellpy projects. local_user_template: use local template if True. serve_: serve the notebook after creation if True. run_: run the notebooks using papermill if True. lab: use jupyter-lab instead of jupyter notebook if True. executable: path to jupyter executable. list_: list all available templates and return if True. project_dir: your project directory. session_id: the lookup value. no_input: accept defaults if True (only valid when providing project_dir and session_id) cookie_directory: name of the directory for your cookie (inside the repository or zip file). Returns: None """ from cellpy.parameters import prms try: import cookiecutter.exceptions import cookiecutter.main import cookiecutter.prompt except ModuleNotFoundError: click.echo("Could not import cookiecutter.") click.echo("Try installing it, for example by writing:") click.echo("\npython -m pip install cookiecutter\n") if list_: click.echo(f"\n[cellpy] batch templates") default_template = _get_default_template() local_templates = _read_local_templates() local_templates_path = prmreader.prms.Paths.templatedir registered_templates = prms._registered_templates click.echo(f"[cellpy] - default: {default_template}") click.echo("[cellpy] - registered templates (on github):") for label, link in registered_templates.items(): click.echo(f"\t\t{label:18s} {link}") if local_templates: click.echo(f"[cellpy] - local templates ({local_templates_path}):") for label, link in local_templates.items(): click.echo(f"\t\t{label:18s} {link}") else: click.echo(f"[cellpy] - local templates ({local_templates_path}): none") return if project_dir is None or session_id is None: no_input = False if not template: template = _get_default_template() if lab: server = "lab" else: server = "notebook" click.echo(f"Template: {template}") if local_user_template: # forcing using local template templates = _read_local_templates() if not templates: click.echo( "You asked me to use a local template, but you have none. Aborting." ) return else: templates = prms._registered_templates if local_templates := _read_local_templates(): templates.update(local_templates) if not template.lower() in templates.keys(): click.echo("This template does not exist. Aborting.") return if directory is None: logging.debug("no dir given") directory = prms.Paths.notebookdir if not os.path.isdir(directory): click.echo("Sorry. This did not work as expected!") click.echo(f" - {directory} does not exist") return directory = Path(directory) selected_project_dir = None if project_dir: selected_project_dir = directory / project_dir if not selected_project_dir.is_dir(): if cookiecutter.prompt.read_user_yes_no( f"{project_dir} does not exist. Create?", "yes" ): os.mkdir(selected_project_dir) click.echo(f"Created {selected_project_dir}") else: selected_project_dir = None click.echo(f"Select another directory instead") if not selected_project_dir: project_dirs = [ d.name for d in directory.iterdir() if d.is_dir() and not d.name.startswith(".") ] project_dirs.insert(0, "[create new dir]") project_dir = cookiecutter.prompt.read_user_choice( "project folder", project_dirs ) if project_dir == "[create new dir]": default_name = "cellpy_project" temp_default_name = default_name for j in range(999): if temp_default_name in project_dirs: temp_default_name = default_name + str(j + 1).zfill(3) else: default_name = temp_default_name break project_dir = cookiecutter.prompt.read_user_variable( "New name", default_name ) try: os.mkdir(directory / project_dir) click.echo(f"created {project_dir}") except FileExistsError: click.echo("OK - but this directory already exists!") selected_project_dir = directory / project_dir # get a list of all folders existing_projects = os.listdir(selected_project_dir) os.chdir(selected_project_dir) cellpy_version = cellpy.__version__ try: selected_template, cookie_dir = templates[template.lower()] if cookie_directory: cookie_dir = cookie_directory if not cookie_dir: cookie_dir = template.lower() author_name = _get_author_name() cookiecutter.main.cookiecutter( selected_template, extra_context={ "author_name": author_name, "project_name": project_dir, "cellpy_version": cellpy_version, "session_id": session_id, }, no_input=no_input, directory=cookie_dir, ) except cookiecutter.exceptions.OutputDirExistsException as e: click.echo("Sorry. This did not work as expected!") click.echo(" - cookiecutter refused to create the project") click.echo(e) if serve_: os.chdir(directory) _serve(server, executable) elif run_: click.echo("WARNING - experimental feature - use at your own risk") input("Press Enter to continue...") try: import papermill as pm except ImportError: click.echo( "[cellpy]: You need to install papermill for automatically execute the notebooks." ) click.echo("[cellpy]: You can install it using pip like this:") click.echo(" >> pip install papermill") return new_existing_projects = os.listdir(selected_project_dir) our_new_projects = list(set(new_existing_projects) - set(existing_projects)) if not len(our_new_projects): click.echo( "[cellpy]: Sorry, could not deiced what is the new project " "- so I don't dare to try to execute automatically." ) return our_new_project = selected_project_dir / our_new_projects[0] _run_project(our_new_project) def _get_author_name(): """Get the name of the author.""" try: import getpass author_name = getpass.getuser() except Exception as e: click.echo("Could not get the author name") click.echo(e) author_name = "unknown" return author_name def _serve(server, executable=None): click.echo(f"serving with jupyter {server}") # TODO: search for jupyter and find the right one if executable is None: executable = "jupyter" subprocess.run([executable, server], check=True) click.echo("Finished serving.") # ----------------------- serve --------------------------------------- @click.command() @click.option("--lab", "-l", is_flag=True, help="Use Jupyter Lab instead of Notebook") @click.option("--directory", "-d", default=None, help="Start in custom directory DIR") @click.option( "--executable", "-e", default=None, help="Custom Jupyter executable (needed if Jupyter is not in the same env as cellpy)", )
[docs] def serve(lab, directory, executable): """Start a Jupyter server.""" from cellpy.parameters import prms if directory is None: directory = prms.Paths.notebookdir elif directory == "home": directory = Path().home() elif directory == "here": directory = Path(os.getcwd()) if not os.path.isdir(directory): click.echo("Sorry. This did not work as expected!") click.echo(f" - {directory} does not exist") return if lab: server = "lab" else: server = "notebook" os.chdir(directory) _serve(server, executable=executable)
cli.add_command(setup) cli.add_command(info) cli.add_command(edit) cli.add_command(pull) cli.add_command(run) cli.add_command(new) cli.add_command(serve) # tests etc def _main_pull(): if sys.platform == "win32": rootpath = pathlib.Path(r"C:\Temp\cellpy_user") else: rootpath = pathlib.Path("/Users/jepe/scripting/tmp/cellpy_test_user") _pull_examples(rootpath, pw="env") _pull_tests(rootpath, pw="env") # _pull(gdirpath="examples", rootpath=rootpath, u="ask", pw="ask") # _pull(gdirpath="tests", rootpath=rootpath, u="ask", pw="ask") # _pull(gdirpath="testdata", rootpath=rootpath, u="ask", pw="ask") def _main(): file_name = prmreader.create_custom_init_filename() click.echo(file_name) user_directory, destination_file_name = prmreader.get_user_dir_and_dst(file_name) click.echo(user_directory) click.echo(destination_file_name) click.echo("trying to save it") save_prm_file(destination_file_name + "_dummy") click.echo(" Testing setup ".center(80, "=")) setup(["--interactive", "--reset"]) def _cli_setup_interactive(): from click.testing import CliRunner if sys.platform == "win32": root_dir = r"C:\Temp\cellpy_user" else: root_dir = "/Users/jepe/scripting/tmp/cellpy_test_user" testuser = "tester" init_filename = prmreader.create_custom_init_filename(testuser) dst_file = get_dst_file(root_dir, init_filename) init_file = pathlib.Path(dst_file) opts = list() opts.append("setup") opts.append("-i") # opts.append("-nr") opts.append("-r") opts.extend(["-d", root_dir]) opts.extend(["-t", testuser]) input_str = "\n" # out input_str += "\n" # rawdatadir input_str += "\n" # cellpyfiles input_str += "\n" # log input_str += "\n" # examples input_str += "\n" # dbfolder input_str += "\n" # dbfile runner = CliRunner() result = runner.invoke(cli, opts, input=input_str) click.echo(" out ".center(80, ".")) click.echo(result.output) from pprint import pprint pprint(prmreader.prms.Paths) click.echo(" conf-file ".center(80, ".")) click.echo(init_file) click.echo() with init_file.open() as f: for line in f.readlines(): click.echo(line.strip()) def _check_it(var=None): import pathlib import sys p_env = pathlib.Path(sys.prefix) print(p_env.name) new(list_=True) u1 = os.getlogin() u2 = os.path.expanduser("~") u3 = os.environ.get("USERNAME") u4 = _get_author_name() u5 = _get_user_name() print(u1) print(u2) print(u3) print(u4) print(u5) print(cellpy.parameters.__file__) print(pathlib.Path(cellpy.parameters.__file__).parent) # check_it() # click.echo("\n\n", " RUNNING MAIN PULL ".center(80, "*"), "\n") _main_pull() # click.echo("ok") def _check_info_check(): """Check your cellpy installation.""" _check() if __name__ == "__main__": _check_info_check()