root
+-- setup.py
+-- README
+-- LICENSE
+-- package_name/
| +-- __init__.py
| +-- foo.py
| +-- bar.py
setup.py
?¶python setup.py install
from setuptools import setup
setup(name='fitting_utilities',
version='0.1.0',
description='Various useful classes for fitting stuff.',
author='Kevin Gullikson',
author_email='kevin.gullikson@gmail.com',
license='BSD',
classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python',
'Topic :: Scientific/Engineering :: Astronomy',
],
packages=['fitters'],
requires=['numpy', 'astropy'])
setup.py
arguments¶import fitters
import fitting_utilities
python setup.py develop
¶__init__.py
?¶import package_name
package_name.foo.foofunction()
__init__.py
from foo import foofunction
import package_name
package_name.foofunction()
Always have a LICENSE
"Because I did not explicitly indicate a license, I declared an implicit copyright without explaining how others could use my code. Since the code is unlicensed, I could theoretically assert copyright at any time and demand that people stop using my code. Experienced developers won't touch unlicensed code because they have no legal right to use it. That's ironic, considering the whole reason I posted the code in the first place was so other developers could benefit from that code. I could have easily avoided this unfortunate situation if I had done the right thing and included a software license with my code." -- Jeff Atwood, (codinghorror)
The main choices are:
python setup.py install
)def blackbody_nu(in_x, temperature):
"""Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`.
.. note::
Use `numpy.errstate` to suppress Numpy warnings, if desired.
.. warning::
Output values might contain ``nan`` and ``inf``.
Parameters
----------
in_x : number, array-like, or `~astropy.units.Quantity`
Frequency, wavelength, or wave number.
If not a Quantity, it is assumed to be in Hz.
temperature : number, array-like, or `~astropy.units.Quantity`
Blackbody temperature.
If not a Quantity, it is assumed to be in Kelvin.
Returns
-------
flux : `~astropy.units.Quantity`
Blackbody monochromatic flux in
:math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`.
"""
"""Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`.
"""
"""
Parameters
----------
in_x : number, array-like, or `~astropy.units.Quantity`
Frequency, wavelength, or wave number.
If not a Quantity, it is assumed to be in Hz.
temperature : number, array-like, or `~astropy.units.Quantity`
Blackbody temperature.
If not a Quantity, it is assumed to be in Kelvin.
...
"""
"""
Returns
-------
flux : `~astropy.units.Quantity`
Blackbody monochromatic flux in
:math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`.
"""
Run sphinx-quickstart
in your root directory.
root
+-- setup.py
+-- README
+-- LICENSE
+-- package_name/
| +-- __init__.py
| +-- foo.py
| +-- bar.py
+-- docs/
| +-- conf.py
| +-- Makefile
| +-- index.rst
| +-- foo.rst
| +-- baz.rst
sphinx-quickstart
# -- General configuration ------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.coverage',
'sphinx.ext.mathjax',
]
You can use this format:
"""
Parameters
==========
- wave wavelength (in nanometers)
"""
But this format will render nicely with sphinx
"""
:param wave: wavelength (in nanometers)`
"""
Sam Harrold informs me that you can use the former, if you add this to your conf.py (for details see here):
extensions = [..., 'sphinxcontrib.napoleon']
# Mock a few modules
from mock import Mock as MagicMock
class Mock(MagicMock):
@classmethod
def __getattr__(cls, name):
return Mock()
MOCK_MODULES = ['FittingUtilities', 'numpy', 'scipy', 'matplotlib', 'scipy.interpolate', 'numpy.polynomial',
'lockfile', 'scipy.optimize', 'astropy', 'pysynphot', 'fortranformat', 'cython', 'requests',
'scipy.linalg', 'matplotlib.pyplot']
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
pip install astropy
[distutils] # this tells distutils what package indexes you can push to
index-servers =
pypi
pypitest
[pypi]
repository: https://pypi.python.org/pypi
username: your_username
password: your_password
[pypitest]
repository: https://testpypi.python.org/pypi
username: your_username
password: your_password
For each package
Register to pypitest:
python setup.py register -r pypitest
Upload to pypitest
python setup.py sdist upload -r pypitest
Test:
# Make a new environment to isolate this from the installation you probably already have working
conda create -n package_test python=3 numpy astropy ...
# Switch to the new environment
source activate package_test
# Install your new package
pip install -i https://testpypi.python.org/pypi <package name>
# Test that it works. At the very least, make sure you can import the package
python -c 'import package_name'
Upload to pypi (de-increment the version number if you had to update it while testing)
python setup.py register -r pypi
python setup.py sdist upload -r pypi
One-time stuff:
login:
anaconda login
# Enter username and password when prompted
For every package
conda skeleton pypi <package_name>
If you have the "install_requires" keyword in your setup.py, you may need to edit the build.sh to have:
$PYTHON setup.py install --single-version-externally-managed --record=/tmp/record.txt
(that fix came from this issue)
build the package. The full path name to the package will be printed to the screen
conda build <package_name>
Uploading to anaconda.org
Convert to work for other platforms (I am not sure this is guaranteed to work)
conda convert -f --platform all full/path/to/package -o output_directory
Upload all of the packages to anaconda.org (must be logged in)
for f in output_directory/*/*
do
anaconda upload $f
done
How to publicize sort of depends on how big the package you are developing. Options are: