diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 0000000..4a1e620 --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,63 @@ +name: Publish PyPI + +on: + release: + types: [published] + + +jobs: + build: + + runs-on: ${{ matrix.os-version }} + name: ${{ matrix.os-version }} (${{ matrix.python-version }}) + + strategy: + fail-fast: false + matrix: + os-version: ["ubuntu-latest"] + python-version: ["3.9"] # ["3.8", "3.9", "3.10"] + + steps: + - uses: actions/checkout@v3 + - name: "Set up Python ${{ matrix.python-version }}" + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + - name: "Install flake8" + run: | + pip install flake8 + - name: "Lint with flake8" + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: "Install miniconda" + uses: conda-incubator/setup-miniconda@v2 + with: + miniconda-version: "latest" + auto-update-conda: true + mamba-version: "*" + python-version: ${{ matrix.python-version }} + channels: conda-forge,bioconda + environment-file: environment.yml + - name: "Install pytest" + shell: bash -l {0} + run: | + python -m pip install --upgrade pip + pip install setuptools wheel build pytest + pip install twine + - name: "Test with pytest" + shell: bash -l {0} + run: | + pytest -s + - name: Build package + shell: bash -l {0} + run: | + python setup.py bdist_wheel --universal + - name: Publish package + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.PYPI_TOKEN }} \ No newline at end of file diff --git a/CanDI/__version__.py b/CanDI/__version__.py new file mode 100644 index 0000000..cab7576 --- /dev/null +++ b/CanDI/__version__.py @@ -0,0 +1 @@ +version = "0.1.1" \ No newline at end of file diff --git a/CanDI/candi/__init__.py b/CanDI/candi/__init__.py index 5624efb..7fc3fbd 100644 --- a/CanDI/candi/__init__.py +++ b/CanDI/candi/__init__.py @@ -1,4 +1,4 @@ -from CanDI.candi import data +from . import data data = data.Data() #Global object data instantiated on import required for access by GeneQuery Objects -from CanDI.candi.candi import (Gene, CellLine, Organelle, Cancer, CellLineCluster, GeneCluster) +from . import (Gene, CellLine, Organelle, Cancer, CellLineCluster, GeneCluster) diff --git a/CanDI/candi/candi.py b/CanDI/candi/candi.py index 75615f5..c422fd8 100644 --- a/CanDI/candi/candi.py +++ b/CanDI/candi/candi.py @@ -4,8 +4,8 @@ import itertools as it import pandas as pd import numpy as np -from CanDI.candi import data, grabber -from CanDI.structures import entity +from . import data, grabber +from . import entity class SubsetHandler(object): diff --git a/CanDI/candi/grabber.py b/CanDI/candi/grabber.py index 3ff2eb6..045eaec 100644 --- a/CanDI/candi/grabber.py +++ b/CanDI/candi/grabber.py @@ -1,6 +1,6 @@ import numpy as np from pathlib import Path -from CanDI.candi import data +from . import data class Grabber: """"Grabber class handles all bulk data retrival from the CanDI Classes. diff --git a/CanDI/setup/install.py b/CanDI/setup/install.py index 43518f3..0042e94 100644 --- a/CanDI/setup/install.py +++ b/CanDI/setup/install.py @@ -1,20 +1,21 @@ import argparse -from manager import Manager +from .manager import Manager -if __name__ == "__main__": +def main(): parser = argparse.ArgumentParser() parser.add_argument("--source", help="Specify the download source", default="dataverse") + parser.add_argument("--data_dir", help="Specify the data directory", default=None) args = parser.parse_args() if args.source == 'dataverse': print("Downloading data from Dataverse") - m = Manager(download_source=args.source) + m = Manager(download_source=args.source, data_dir=args.data_dir) m.download_reformatted_data() m.write_config(m.cfig_path, m.parser) elif args.source == 'depmap': print("Downloading data from DepMap") - m = Manager(download_source=args.source) + m = Manager(download_source=args.source, data_dir=args.data_dir) m.get_depmap_info() m.write_config(m.cfig_path, m.parser) m.download_defaults() @@ -23,4 +24,7 @@ m.write_config(m.cfig_path, m.parser) else: - raise ValueError("Invalid source. Please specify either 'dataverse' or 'depmap'") \ No newline at end of file + raise ValueError("Invalid source. Please specify either 'dataverse' or 'depmap'") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/CanDI/setup/manager.py b/CanDI/setup/manager.py index 3b50364..5d2c3c4 100644 --- a/CanDI/setup/manager.py +++ b/CanDI/setup/manager.py @@ -8,16 +8,20 @@ from time import sleep from pathlib import Path from concurrent.futures import ThreadPoolExecutor -from dataverse import depmap_dataverse_download +from .dataverse import depmap_dataverse_download class Manager(object): """The Manager class handles interations with the datasources and the config file. It is used to setup of the config file upon installation. All data downloading is done by Manager """ - def __init__(self, download_source=None): + def __init__(self, download_source=None, data_dir=None): - manager_path = os.path.dirname(os.path.realpath(__file__)) + if data_dir: + manager_path = data_dir + else: + manager_path = os.path.dirname(os.path.realpath(__file__)) + cfig_path = manager_path + "/data/config.ini" parser = configparser.ConfigParser() parser.read(cfig_path.replace(".ini", ".draft.ini")) @@ -218,6 +222,12 @@ def format_depmap_data(self, df, path): def download_reformatted_data(self, depmap_release=''): + if not os.path.exists(self.manager_path + '/data/'): + os.makedirs(self.manager_path + '/data/') + + if not os.path.exists(self.manager_path + '/data/depmap/'): + os.makedirs(self.manager_path + '/data/depmap/') + if self.download_source == "dataverse": urls, file_names = depmap_dataverse_download( self.manager_path + '/data/depmap/', diff --git a/CanDI/setup/reset_config.py b/CanDI/setup/reset_config.py index 7453023..39a3a9d 100644 --- a/CanDI/setup/reset_config.py +++ b/CanDI/setup/reset_config.py @@ -1,7 +1,7 @@ import os import configparser import json -from manager import Manager +from .manager import Manager def main(): diff --git a/CanDI/structures/entity.py b/CanDI/structures/entity.py index 84fac42..2507068 100644 --- a/CanDI/structures/entity.py +++ b/CanDI/structures/entity.py @@ -1,5 +1,5 @@ import pandas as pd -from CanDI.structures import handlers +from . import handlers class Entity(object): diff --git a/README.rst b/README.rst index e0e34a9..86f1a20 100644 --- a/README.rst +++ b/README.rst @@ -8,20 +8,19 @@ CanDI - A global cancer data integrator Package Installation -------------------- -First, you need to clone this repository to use CanDI. +CanDI is now available on `PyPI `_ and can be installed with pip: .. code:: bash - git clone https://github.com/GilbertLabUCSF/CanDI.git + pip install CanDI -We suggest to use `Conda `__ as a -package manager and environment management system. You can create a -fresh conda environment with all ``CanDI``\ ’s requirements using bellow -command: +___ +For the latest version (development version) install from GitHub: .. code:: bash + + pip install git+https://github.com/GilbertLabUCSF/CanDI.git - conda env create -f CanDI/environment.yml -n candi Prepare Datasets ~~~~~~~~~~~~~~~~ @@ -59,22 +58,10 @@ Package Usage Import CanDI into python ~~~~~~~~~~~~~~~~~~~~~~~~ -To import ``CanDI``, your active directory in python must be same as the -cloned folder. - .. code:: python from CanDI import candi -**OR**, you can add path to the `CanDI` directory if you want to use it from other directories. - -.. code:: python - - import sys - sys.path.append("path-to-candi-directory") - - from CanDI import candi - CanDI Objects ~~~~~~~~~~~~~ diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..7358a89 --- /dev/null +++ b/setup.py @@ -0,0 +1,31 @@ +from setuptools import setup, find_packages +from CanDI.__version__ import version + +from pathlib import Path + +this_directory = Path(__file__).parent + +setup( + name='CanDI', + description='A cancer data integration package', + version=version, + packages=find_packages(), + python_requires='>=3.9', + install_requires=[ + "pandas", + "configparser", + "requests", + "tqdm", + ], + url = 'https://github.com/GilbertLabUCSF/CanDI', + entry_points={ + 'console_scripts': [ + 'candi-install = CanDI.setup.install:main', + ], + }, + classifiers=[ + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 3', + ], +) \ No newline at end of file