Friday, March 23, 2018

Pushing your code to pypi



Here is a good document that describes how to push your code to the Pypi repository.

A URL has changed slightly. In your ~/.pypirc set the URL as follows:


[pypitest]
repository=https://test.pypi.org/legacy/

The register step is no longer required. All you need to do is upload the files.

python setup.py sdist upload -r pypitest

Each time you initiate an upload, you'd need to change the version number and the URL.

While this uploaded the package to test.pypi.org, the upload steps had changed for pypi.org:


thushara@ figleaf (master)$ python setup.py sdist upload -r pypi
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: 'install_requires'
  warnings.warn(msg)
running sdist
running check
warning: sdist: manifest template 'MANIFEST.in' does not exist (using default file list)

warning: sdist: standard file not found: should have one of README, README.txt

writing manifest file 'MANIFEST'
creating figleaf-0.2
creating figleaf-0.2/figleaf
making hard links in figleaf-0.2...
hard linking setup.cfg -> figleaf-0.2
hard linking setup.py -> figleaf-0.2
hard linking figleaf/__init__.py -> figleaf-0.2/figleaf
hard linking figleaf/graph.py -> figleaf-0.2/figleaf
Creating tar archive
removing 'figleaf-0.2' (and everything under it)
running upload
Submitting dist/figleaf-0.2.tar.gz to https://pypi.python.org/pypi
Upload failed (410): Gone (This API has been deprecated and removed from legacy PyPI in favor of using the APIs available in the new PyPI.org implementation of PyPI (located at https://pypi.org/). For more information about migrating your use of this API to PyPI.org, please see https://packaging.python.org/guides/migrating-to-pypi-org/#uploading. For more information about the sunsetting of this API, please see https://mail.python.org/pipermail/distutils-sig/2017-June/030766.html)
error: Upload failed (410): Gone (This API has been deprecated and removed from legacy PyPI in favor of using the APIs available in the new PyPI.org implementation of PyPI (located at https://pypi.org/). For more information about migrating your use of this API to PyPI.org, please see https://packaging.python.org/guides/migrating-to-pypi-org/#uploading. For more information about the sunsetting of this API, please see https://mail.python.org/pipermail/distutils-sig/2017-June/030766.html)

To upload to pypi I used twine. Installing that on MacOS High Sierra required the removal of SIP.

In ~/.pypirc, I removed the repository line under [pypi]


python setup.py sdist

Remove old tars under dist, and

twine upload dist/*

Now I could see the project under pypi

Installing Twine on MacOS High Sierra


thushara@ wildhops (master)*$ sudo -H pip install twine
Password:
Collecting twine
  Downloading twine-1.11.0-py2.py3-none-any.whl
Collecting pkginfo>=1.4.2 (from twine)
  Downloading pkginfo-1.4.2-py2.py3-none-any.whl
Requirement already satisfied: setuptools>=0.7.0 in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python (from twine)
Collecting tqdm>=4.14 (from twine)
  Downloading tqdm-4.19.8-py2.py3-none-any.whl (52kB)
    100% |████████████████████████████████| 61kB 2.1MB/s 
Collecting requests-toolbelt>=0.8.0 (from twine)
  Downloading requests_toolbelt-0.8.0-py2.py3-none-any.whl (54kB)
    100% |████████████████████████████████| 61kB 1.6MB/s 
Requirement already satisfied: requests!=2.15,!=2.16,>=2.5.0 in /Library/Python/2.7/site-packages (from twine)
Installing collected packages: pkginfo, tqdm, requests-toolbelt, twine
Exception:
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/Library/Python/2.7/site-packages/pip/commands/install.py", line 342, in run
    prefix=options.prefix_path,
  File "/Library/Python/2.7/site-packages/pip/req/req_set.py", line 784, in install
    **kwargs
  File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 851, in install
    self.move_wheel_files(self.source_dir, root=root, prefix=prefix)
  File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 1064, in move_wheel_files
    isolated=self.isolated,
  File "/Library/Python/2.7/site-packages/pip/wheel.py", line 377, in move_wheel_files
    clobber(source, dest, False, fixer=fixer, filter=filter)
  File "/Library/Python/2.7/site-packages/pip/wheel.py", line 316, in clobber
    ensure_dir(destdir)
  File "/Library/Python/2.7/site-packages/pip/utils/__init__.py", line 83, in ensure_dir
    os.makedirs(path)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 150, in makedirs
    makedirs(head, mode)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 1] Operation not permitted: '/System/Library/Frameworks/Python.framework/Versions/2.7/man'

The only way to get write access under /System is to boot into Recovery Mode and run this command on the Terminal:

csrutil disable


Reboot, install again

Thursday, March 22, 2018

A Graph in Python - and pythonic surprises

I started implementing a Graph in python for a project and I encountered an unexpected behavior. See if you can spot the problem.

Code for the graph is here:



However this is buggy. Each time an edge is added to one node, it gets added to all the nodes. Adding an edge from 'bellevue' to 'lynwood' added the edge to both vertices 'bellevue' and 'lynwood'.

Code/Output:

g.add_node(GraphNode('seattle', [Edge('seattle', 'bellevue', 'dist', 10), Edge('seattle', 'lynwood', 'dist', 20)]))

g.add_edge(('bellevue', 'lynwood', 'dist', 5))

print (g)

bellevue -> bellevue:lynwood:dist:5
lynwood -> bellevue:lynwood:dist:5
seattle -> seattle:bellevue:dist:10 seattle:lynwood:dist:20

After a lengthy debugging stint, the issue was identified to be the way Python evaluates default argument values to functions.