diff --git a/.github/workflows/pypipublish_linux.yml b/.github/workflows/pypipublish_linux.yml new file mode 100644 index 00000000..498cffac --- /dev/null +++ b/.github/workflows/pypipublish_linux.yml @@ -0,0 +1,67 @@ +name: Linux Package PyPI deploy + +on: + release: + types: [created] + +jobs: + deploy: + strategy: + matrix: + os: + - ubuntu-latest + python-version: [3.5, 3.6, 3.7,3.8] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + - name: Set up submodules + run: | + bash ./ext_source_setup.sh + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Install pre-requisites + run: | + sudo apt-get update + # checking for g++ + dpkg -s g++ &> /dev/null + if [ $? -eq 0 ]; then + echo "g++ is installed, skipping..." + else + echo "Installing g++" + sudo apt-get install g++ + fi + echo "Installing Bazel dependencies" + sudo apt-get install pkg-config zip zlib1g-dev unzip + echo "Donwloading Bazel 2.1.0" + wget https://github.com/bazelbuild/bazel/releases/download/2.1.0/bazel-2.1.0-installer-linux-x86_64.sh + + chmod +x bazel-2.1.0-installer-linux-x86_64.sh + ./bazel-2.1.0-installer-linux-x86_64.sh --user + export PATH="$PATH:$HOME/bin" + - name: Build pydp lib + run: | + bash ./build_PyDP.sh + + - name: Install python dependencies + run: | + python -m pip install --upgrade pip + pip install -r ./requirements_dev.txt + + - name: Build wheel + run: | + python setup.py bdist_wheel + + - name: Renaming wheel + run: | + find . -name '*linux*.whl' -type f -exec bash -c 'mv "$1" "${1/linux/manylinux1}"' -- {} \; + + - name: Publishing the wheel + env: + TWINE_USERNAME: "__token__" + TWINE_PASSWORD: ${{ secrets.TOKEN }} + run: | + twine upload --skip-existing dist/*.whl diff --git a/README.md b/README.md index dc3d901f..901271ba 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ If you'd like to contribute to this project please read these [guidelines](https ## Usage -As part of the 0.1.0 dev release, we have managed to port the Private Mean function (Bounded Mean). Other functions will be released in further release. +As part of the 0.1.1 dev release, we have managed to port the Private Mean function (Bounded Mean). Other functions will be released in further release. To install the package: `pip install python-dp` diff --git a/contributing.md b/contributing.md index 22a40263..c6508233 100644 --- a/contributing.md +++ b/contributing.md @@ -55,7 +55,7 @@ $ python3 setup.py sdist bdist_wheel Install wheel: ``` -$ pip install dist/pydp-0.1.0-py2.py3-none-any.whl +$ pip install dist/*.whl ``` ## Docker Support diff --git a/docs/readme.rst b/docs/readme.rst new file mode 100644 index 00000000..8d1f5317 --- /dev/null +++ b/docs/readme.rst @@ -0,0 +1,54 @@ +Introduction +============ + +PyDP is a Python wrapper for Google’s `Differential Privacy`_ project. +The library provides a set of ε-differentially private algorithms, which +can be used to produce aggregate statistics over numeric data sets +containing private or sensitive information. + +PyDP is part of the OpenMined community, come join the movement on +`Slack`_. + +Instructions +============ + +If you’d like to contribute to this project please read these +`guidelines`_. + +Usage +----- + +As part of the 0.1.1 dev release, we have managed to port the Private +Mean function (Bounded Mean). Other functions will be released in +further release. + +To install the package: ``pip install python-dp`` + +:: + + import pydp as dp # imports the DP library + + # To calculate the Bounded Mean + # epsilon is a number between 0 and 1 denoting privacy threshold + # It measures the acceptable loss of privacy (with 0 meaning no loss is acceptable) + # If both the lower and upper bounds are specified, + # x = dp.BoundedMean(epsilon: double, lower: int, upper: int) + x = dp.BoundedMean(0.6, 1, 10) + + # If lower and upper bounds are not specified, + # DP library automatically calculates these bounds + # x = dp.BoundedMean(epsilon: double) + x = dp.BoundedMean(0.6) + + # To get the result + # Currently supported data types are integer and float. Future versions will support additional data types + # Refer to examples/carrots.py for an introduction + x.result(input_data: list) + +Known issue: If the privacy budget (epsilon is too less), we get a +StatusOR error in the command line. While this needs to be raised as an +error, right now, it’s just displayed as an error in logs. + +.. _Differential Privacy: https://github.com/google/differential-privacy +.. _Slack: http://slack.openmined.org/ +.. _guidelines: https://github.com/OpenMined/PyDP/blob/master/contributing.md \ No newline at end of file diff --git a/requirements_dev.txt b/requirements_dev.txt index 0cd4333e..3d81f682 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -6,3 +6,4 @@ tox==3.5.2 coverage==4.5.1 pytest pycodestyle +twine diff --git a/setup.cfg b/setup.cfg index 5670fc62..5e02149a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.0dev +current_version = 0.1.1dev commit = True tag = True @@ -7,8 +7,6 @@ tag = True search = version='{current_version}' replace = version='{new_version}' -[bdist_wheel] -universal = 1 [pycodestyle] max-line-length = 88 diff --git a/setup.py b/setup.py index b8d176fe..a4272672 100644 --- a/setup.py +++ b/setup.py @@ -5,14 +5,23 @@ from setuptools import setup, find_packages from setuptools.dist import Distribution +from setuptools.command.install import install + import os +class InstallPlatlib(install): + def finalize_options(self): + install.finalize_options(self) + if self.distribution.has_ext_modules(): + self.install_lib = self.install_platlib + + class BinaryDistribution(Distribution): - """This class is needed in order to create OS specific wheels.""" + """This class is needed in order to create OS specific wheels.""" - def has_ext_modules(self): - return True + def has_ext_modules(self): + return True def read(fname): @@ -36,22 +45,23 @@ def read(fname): "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", ], description="Python API for Google's Differential Privacy library", distclass=BinaryDistribution, install_requires=requirements, license="Apache-2.0", - long_description=read("README.md"), - long_description_content_type="text/markdown", + long_description=read("docs/readme.rst"), include_package_data=True, keywords="pydp", name="python-dp", package_data={"pydp": ["pydp.so"],}, - packages=find_packages(), # need to check this + packages=find_packages(exclude=["tests/"]), # need to check this + cmdclass={"install": InstallPlatlib}, setup_requires=setup_requirements, test_suite="tests", tests_require=test_requirements, url="https://github.com/OpenMined/PyDP", - version="0.1.0", + version="0.1.1", zip_safe=False, )