<commit_before>#!/usr/bin/env python

import os
from setuptools import setup

README = open(os.path.join(os.path.dirname(__file__), 'README.md')).read()

# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))

setup(
    name='canvas-analytics',
    version='1.0',
    packages=['analytics'],
    include_package_data=True,
    install_requires = [
        'Django>=2.1',
        'UW-RestClients-SWS>=2.2.1,<3.0',
        'UW-RestClients-Canvas>=1.1.12,<2.0',
        'UW-Django-SAML2>=1.4,<2.0',
    ],
    license='Apache License, Version 2.0',
    description='Builds reports about UW Canvas usage',
    long_description=README,
    url='https://github.com/uw-it-aca/canvas-analytics',
    author = "UW-IT AXDD",
    author_email = "aca-it@uw.edu",
    classifiers=[
        'Environment :: Web Environment',
        'Framework :: Django',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: Apache Software License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 3.6',
    ],
)
<commit_msg>pin django version<commit_after>#!/usr/bin/env python

import os
from setuptools import setup

README = open(os.path.join(os.path.dirname(__file__), 'README.md')).read()

# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))

setup(
    name='canvas-analytics',
    version='1.0',
    packages=['analytics'],
    include_package_data=True,
    install_requires = [
        'Django>=2.0.13,<2.1',
        'UW-RestClients-SWS>=2.2.1,<3.0',
        'UW-RestClients-Canvas>=1.1.12,<2.0',
        'UW-Django-SAML2>=1.4,<2.0',
    ],
    license='Apache License, Version 2.0',
    description='Builds reports about UW Canvas usage',
    long_description=README,
    url='https://github.com/uw-it-aca/canvas-analytics',
    author = "UW-IT AXDD",
    author_email = "aca-it@uw.edu",
    classifiers=[
        'Environment :: Web Environment',
        'Framework :: Django',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: Apache Software License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 3.6',
    ],
)
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""The setup script."""

from setuptools import setup, find_packages

with open('README.rst') as readme_file:
    readme = readme_file.read()

with open('HISTORY.rst') as history_file:
    history = history_file.read()

with open('requirements.txt') as f:
    requirements = f.read().splitlines()
with open('requirements_dev.txt') as f:
    requirements_dev = f.read().splitlines()[1:] # ignore the general requirements
with open('requirements_doc.txt') as f:
    requirements_doc = f.read().splitlines()

setup(
    name='pydov',
    version='0.1.0',
    description="A Python package to download data from Databank Ondergrond Vlaanderen (DOV).",
    long_description=readme + '\n\n' + history,
    author="DOV-Vlaanderen",
    author_email='dov@vlaanderen.be',
    url='https://github.com/DOV-Vlaanderen/pydov',
    packages=find_packages(include=['pydov']),
    # entry_points={
    #     'console_scripts': [
    #         'pydov=pydov.cli:main'
    #     ]
    # },
    include_package_data=True,
    install_requires=requirements,
    license="MIT license",
    zip_safe=False,
    keywords='pydov',
    classifiers=[
        'Development Status :: 2 - Pre-Alpha',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Natural Language :: English',
        "Programming Language :: Python :: 2",
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
    ],
    test_suite='tests',
    tests_require=requirements_dev,
    extras_require={
        'docs': requirements_doc,
        'devs': requirements_dev
    }
)
<commit_msg>Fix reference to rst readme<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""The setup script."""

from setuptools import setup, find_packages

with open('README.md') as readme_file:
    readme = readme_file.read()

with open('HISTORY.rst') as history_file:
    history = history_file.read()

with open('requirements.txt') as f:
    requirements = f.read().splitlines()
with open('requirements_dev.txt') as f:
    requirements_dev = f.read().splitlines()[1:] # ignore the general requirements
with open('requirements_doc.txt') as f:
    requirements_doc = f.read().splitlines()

setup(
    name='pydov',
    version='0.1.0',
    description="A Python package to download data from Databank Ondergrond Vlaanderen (DOV).",
    long_description=readme + '\n\n' + history,
    author="DOV-Vlaanderen",
    author_email='dov@vlaanderen.be',
    url='https://github.com/DOV-Vlaanderen/pydov',
    packages=find_packages(include=['pydov']),
    # entry_points={
    #     'console_scripts': [
    #         'pydov=pydov.cli:main'
    #     ]
    # },
    include_package_data=True,
    install_requires=requirements,
    license="MIT license",
    zip_safe=False,
    keywords='pydov',
    classifiers=[
        'Development Status :: 2 - Pre-Alpha',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Natural Language :: English',
        "Programming Language :: Python :: 2",
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
    ],
    test_suite='tests',
    tests_require=requirements_dev,
    extras_require={
        'docs': requirements_doc,
        'devs': requirements_dev
    }
)
<|endoftext|>


<commit_before>from setuptools import setup, find_packages

version = '0.4.0'

setup(name='htext',
      version=version,
      description="htext.ja - helpers for handling japanese text",
      long_description="""\
htext.ja is helper library for handling japanese text.
""",
      classifiers=filter(None, map(str.strip, """\
Development Status :: 3 - Alpha
License :: OSI Approved :: MIT License
Programming Language :: Python
""".splitlines())),
      keywords='',
      author='Chihio SAKATOKU',
      author_email='csakatoku@gmail.com',
      url='https://github.com/hunza/htext',
      license='MIT License',
      platforms=['any'],
      packages=find_packages(exclude=['ez_setup', 'tests']),
      include_package_data=True,
      zip_safe=False,
      install_requires=[
          # -*- Extra requirements: -*-
      ],
      entry_points="""
      # -*- Entry points: -*-
      """,
      test_suite='nose.collector'
      )
<commit_msg>Bump version to 0.4.1<commit_after>from setuptools import setup, find_packages

version = '0.4.1'

setup(name='htext',
      version=version,
      description="htext.ja - helpers for handling japanese text",
      long_description="""\
htext.ja is helper library for handling japanese text.
""",
      classifiers=filter(None, map(str.strip, """\
Development Status :: 3 - Alpha
License :: OSI Approved :: MIT License
Programming Language :: Python
""".splitlines())),
      keywords='',
      author='Chihio SAKATOKU',
      author_email='csakatoku@gmail.com',
      url='https://github.com/hunza/htext',
      license='MIT License',
      platforms=['any'],
      packages=find_packages(exclude=['ez_setup', 'tests']),
      include_package_data=True,
      zip_safe=False,
      install_requires=[
          # -*- Extra requirements: -*-
      ],
      entry_points="""
      # -*- Entry points: -*-
      """,
      test_suite='nose.collector'
      )
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import setup

setup(
    name='django-viewflow',
    version='1.5.3',
    author='Mikhail Podgurskiy',
    author_email='kmmbvnr@gmail.com',
    description='Reusable workflow library for django',
    long_description=open('README.rst').read(),
    platforms=['Any'],
    keywords=['workflow', 'django', 'bpm', 'automaton'],
    url='http://github.com/viewflow/viewflow',
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Intended Audience :: Developers',
        'Natural Language :: English',
        'Operating System :: OS Independent',
        'Framework :: Django',
        'Framework :: Django :: 1.11',
        'Framework :: Django :: 2.0',
        'Framework :: Django :: 2.1',
        'Framework :: Django :: 2.2',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3.7',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
    ],
    install_requires=[
        'Django>=1.11',
        'django-filter>=1.0'
    ],
    packages=['viewflow',
              'viewflow.flow',
              'viewflow.flow.views',
              'viewflow.management',
              'viewflow.migrations',
              'viewflow.nodes',
              'viewflow.templatetags',
              'viewflow.frontend',
              'viewflow.frontend.templatetags'],
    include_package_data=True,
    zip_safe=False)
<commit_msg>Bump version<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import setup

setup(
    name='django-viewflow',
    version='1.5.6',
    author='Mikhail Podgurskiy',
    author_email='kmmbvnr@gmail.com',
    description='Reusable workflow library for django',
    long_description=open('README.rst').read(),
    platforms=['Any'],
    keywords=['workflow', 'django', 'bpm', 'automaton'],
    url='http://github.com/viewflow/viewflow',
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Intended Audience :: Developers',
        'Natural Language :: English',
        'Operating System :: OS Independent',
        'Framework :: Django',
        'Framework :: Django :: 1.11',
        'Framework :: Django :: 2.0',
        'Framework :: Django :: 2.1',
        'Framework :: Django :: 2.2',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3.7',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
    ],
    install_requires=[
        'Django>=1.11',
        'django-filter>=1.0'
    ],
    packages=['viewflow',
              'viewflow.flow',
              'viewflow.flow.views',
              'viewflow.management',
              'viewflow.migrations',
              'viewflow.nodes',
              'viewflow.templatetags',
              'viewflow.frontend',
              'viewflow.frontend.templatetags'],
    include_package_data=True,
    zip_safe=False)
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
Service to render pngs from vector tiles using Carto CSS.
"""

import base64
import json
from urllib import quote_plus

from tornado import web
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from tornado.ioloop import IOLoop
from tornado.options import define, parse_command_line, options
import mapnik                   # pylint: disable=import-error
import msgpack

from carto_renderer.errors import BadRequest, PayloadKeyError, ServiceError
from carto_renderer.util import get_logger, init_logging, LogWrapper
from carto_renderer.version import BUILD_TIME, SEMANTIC

__package__ = 'carto_renderer'  # pylint: disable=redefined-builtin

# Variables for Vector Tiles.
BASE_ZOOM = 29
TILE_ZOOM_FACTOR = 16
TILE_SIZE = 256

def render_png(tile, _zoom, xml, overscan):
    """
    Render the tile as a .png

    TODO: Actually handling zoom levels.
    """
    # mapnik is installed in a non-standard way.
    # It confuses pylint.
    # pylint: disable=no-member,too-many-locals

    map_tile_size = TILE_SIZE + (overscan * 2)
    logger = get_logger()
    ctx = mapnik.Context()

    map_tile = mapnik.Map(map_tile_size, map_tile_size)
    # scale_denom = 1 << (BASE_ZOOM - int(zoom or 1))
    # scale_factor = scale_denom / map_tile.scale_denominator()
    # map_tile.zoom(scale_factor)  # Is overriden by zoom_to_box.

    mapnik.load_map_from_string(map_tile, xml)

    box_min = -overscan
    box_max = TILE_SIZE + overscan - 1
    map_tile.zoom_to_box(mapnik.Box2d(box_min, box_min, box_max, box_max))

    for (name, features) in tile.items():
        name = name.encode('ascii', 'ignore')
        source = mapnik.MemoryDatasource()
        map_layer = mapnik.Layer(name)
        map_layer.datasource = source

        for feature in features:
            feat = mapnik.Feature(ctx, 0)

            try:
                feat.geometry = mapnik.Geometry.from_wkb(feature)
            except RuntimeError:
                try:
                    wkt = mapnik.Geometry.from_wkb(feature).to_wkt()
                    logger.error('Invalid feature: %s', wkt)
                except RuntimeError:
                    logger.error('Corrupt feature: %s', feature.encode('hex'))

            source.add_feature(feat)

        map_layer.styles.append(name)
        map_tile.layers.append(map_layer)

    image = mapnik.Image(TILE_SIZE, TILE_SIZE)
    # tile, image, scale, offset_x, offset_y
    mapnik.render(map_tile, image, 1, overscan, overscan)

    return image.tostring('png')

class BaseHandler(web.RequestHandler):
    # pylint: disable=abstract-method
    """
    Convert ServiceErrors to HTTP errors.
    """
    def extract_body(self):
        """
        Extract the body from self.request as a dictionary.
        """
        logger = get_logger(self)

        request_id = self.request.headers.get('x-socrata-requestid', '')
        LogWrapper.ENV['X-Socrata-RequestId'] = request_id

        content_type = self.request.headers.get('content-type', '').lower()
        if not content_type.startswith('application/octet-stream'):
            message = 'Invalid Content-Type: "{ct}"; ' + \
                      'expected"application/octet-stream"'
            logger.warn('Invalid Content-Type: "%s"', content_type)
            raise BadRequest(message.format(ct=content_type))

        body = self.request.body

        try:
            extracted = msgpack.loads(body)
        except Exception:
            logger.warn('Invalid message')
            raise BadRequest('Could not parse message.', body)
        return extracted

    def _handle_request_exception(self, err):
        """
        Convert ServiceErrors to HTTP errors.
        """
        logger = get_logger(self)

        payload = {}
        logger.exception(err)
        if isinstance(err, ServiceError):
            status_code = err.status_code
            if err.request_body:
                payload['request_body'] = err.request_body
        else:
            status_code = 500

        payload['resultCode'] = status_code
        payload['message'] = err.message

        self.clear()
        self.set_status(status_code)
        self.write(json.dumps(payload))
        self.finish()

class VersionHandler(BaseHandler):
    # pylint: disable=abstract-method
    """
    Return the version of the service, currently hardcoded.
    """
    import sys

    (major, minor, micro, _, _) = sys.version_info

    version = {'health': 'alive',
               'pythonVersion': '{}.{}.{}'.format(major, minor, micro),
               'version': SEMANTIC,
               'buildTime': BUILD_TIME}

    def get(self):
        """
        Return the version of the service, currently hardcoded.
        """
        request_id = self.request.headers.get('x-socrata-requestid', '')
        LogWrapper.ENV['X-Socrata-RequestId'] = request_id

        logger = get_logger(self)

        logger.info('Alive!')
        self.write(VersionHandler.version)
        self.finish()

class RenderHandler(BaseHandler):
    # pylint: disable=abstract-method, arguments-differ
    """
    Actually render the png.

    Expects a dictionary with 'style', 'zoom', and 'tile' values.
    """
    keys = ['tile', 'zoom', 'style']

    def initialize(self, http_client, style_host, style_port):
        """Magic Tornado __init__ replacement."""
        self.http_client = http_client  # pragma: no cover
        self.style_host = style_host    # pragma: no cover
        self.style_port = style_port    # pragma: no cover

    @web.asynchronous
    def post(self):
        """
        Actually render the png.

        Expects a JSON blob with 'style', 'zoom', and 'tile' values.
        """
        logger = get_logger(self)

        geobody = self.extract_body()

        if not all([k in geobody for k in self.keys]):
            logger.warn('Invalid JSON: %s', geobody)
            raise PayloadKeyError(self.keys, geobody)
        else:
            try:
                overscan = int(geobody['overscan'])
            except:
                logger.warn('Invalid JSON; overscan must be an integer: %s',
                            geobody)
                raise BadRequest('"overscan" must be an integer',
                                 request_body=geobody)

            try:
                zoom = int(geobody['zoom'])
            except:
                logger.warn('Invalid JSON; zoom must be an integer: %s',
                            geobody)
                raise BadRequest('"zoom" must be an integer.',
                                 request_body=geobody)

            path = 'http://{host}:{port}/style?style={css}'.format(
                host=self.style_host,
                port=self.style_port,
                css=quote_plus(geobody['style']))

            tile = geobody['tile']

            # Hack for compat with Base64 and MsgPack.  Should be
            # ripped out after TileServer goes out.
            try:
                first_byte = ord(geobody['tile'].items()[0][1][0][0])

                if first_byte not in [0, 1]:
                    tile = {layer: [base64.b64decode(wkb) for wkb in wkbs]
                            for layer, wkbs in geobody['tile'].items()}
            except IndexError:
                pass
            # End Base64 backwards compatibility hack.

            def handle_response(response):
                """
                Process the XML returned by the style renderer.
                """
                if response.body is None:
                    raise ServiceError(
                        "Failed to contact style-renderer at '{url}'".format(
                            url=path),
                        503)

                xml = response.body

                logger.info('zoom: %d, num features: %d, len(xml): %d',
                            zoom,
                            sum([len(layer) for layer in tile.values()]),
                            len(xml))
                logger.debug('xml: %s',
                             LogWrapper.Lazy(lambda: xml.replace('\n', ' ')))

                self.write(render_png(tile, zoom, xml, overscan))
                self.finish()

            headers = LogWrapper.ENV \
                if LogWrapper.ENV['X-Socrata-RequestId'] is not None \
                else {}

            req = HTTPRequest(path, headers=headers)
            self.http_client.fetch(req, callback=handle_response)

def main():  # pragma: no cover
    """
    Actually fire up the web server.

    Listens on 4096.
    """
    define('port', default=4096)
    define('style_host', default='localhost')
    define('style_port', default=4097)
    define('log_level', default='INFO')
    define('log_format', default='%(asctime)s %(levelname)s [%(thread)d] ' +
           '[%(X-Socrata-RequestId)s] %(name)s %(message)s')
    parse_command_line()
    init_logging()

    routes = [
        web.url(r'/', web.RedirectHandler, {'url': '/version'}),
        web.url(r'/version', VersionHandler),
        web.url(r'/render', RenderHandler, {
            'style_host': options.style_host,
            'style_port': options.style_port,
            'http_client': AsyncHTTPClient()
        }),
    ]

    app = web.Application(routes)
    app.listen(options.port)
    logger = get_logger()
    logger.info('Listening on localhost:4096...')
    IOLoop.instance().start()

if __name__ == '__main__':  # pragma: no cover
    main()
<commit_msg>Remove hack providing backwards compatibility for base64 encoded WKB<commit_after>#!/usr/bin/env python
"""
Service to render pngs from vector tiles using Carto CSS.
"""

import json
from urllib import quote_plus

from tornado import web
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from tornado.ioloop import IOLoop
from tornado.options import define, parse_command_line, options
import mapnik                   # pylint: disable=import-error
import msgpack

from carto_renderer.errors import BadRequest, PayloadKeyError, ServiceError
from carto_renderer.util import get_logger, init_logging, LogWrapper
from carto_renderer.version import BUILD_TIME, SEMANTIC

__package__ = 'carto_renderer'  # pylint: disable=redefined-builtin

# Variables for Vector Tiles.
BASE_ZOOM = 29
TILE_ZOOM_FACTOR = 16
TILE_SIZE = 256

def render_png(tile, _zoom, xml, overscan):
    """
    Render the tile as a .png

    TODO: Actually handling zoom levels.
    """
    # mapnik is installed in a non-standard way.
    # It confuses pylint.
    # pylint: disable=no-member,too-many-locals

    map_tile_size = TILE_SIZE + (overscan * 2)
    logger = get_logger()
    ctx = mapnik.Context()

    map_tile = mapnik.Map(map_tile_size, map_tile_size)
    # scale_denom = 1 << (BASE_ZOOM - int(zoom or 1))
    # scale_factor = scale_denom / map_tile.scale_denominator()
    # map_tile.zoom(scale_factor)  # Is overriden by zoom_to_box.

    mapnik.load_map_from_string(map_tile, xml)

    box_min = -overscan
    box_max = TILE_SIZE + overscan - 1
    map_tile.zoom_to_box(mapnik.Box2d(box_min, box_min, box_max, box_max))

    for (name, features) in tile.items():
        name = name.encode('ascii', 'ignore')
        source = mapnik.MemoryDatasource()
        map_layer = mapnik.Layer(name)
        map_layer.datasource = source

        for feature in features:
            feat = mapnik.Feature(ctx, 0)

            try:
                feat.geometry = mapnik.Geometry.from_wkb(feature)
            except RuntimeError:
                try:
                    wkt = mapnik.Geometry.from_wkb(feature).to_wkt()
                    logger.error('Invalid feature: %s', wkt)
                except RuntimeError:
                    logger.error('Corrupt feature: %s', feature.encode('hex'))

            source.add_feature(feat)

        map_layer.styles.append(name)
        map_tile.layers.append(map_layer)

    image = mapnik.Image(TILE_SIZE, TILE_SIZE)
    # tile, image, scale, offset_x, offset_y
    mapnik.render(map_tile, image, 1, overscan, overscan)

    return image.tostring('png')

class BaseHandler(web.RequestHandler):
    # pylint: disable=abstract-method
    """
    Convert ServiceErrors to HTTP errors.
    """
    def extract_body(self):
        """
        Extract the body from self.request as a dictionary.
        """
        logger = get_logger(self)

        request_id = self.request.headers.get('x-socrata-requestid', '')
        LogWrapper.ENV['X-Socrata-RequestId'] = request_id

        content_type = self.request.headers.get('content-type', '').lower()
        if not content_type.startswith('application/octet-stream'):
            message = 'Invalid Content-Type: "{ct}"; ' + \
                      'expected"application/octet-stream"'
            logger.warn('Invalid Content-Type: "%s"', content_type)
            raise BadRequest(message.format(ct=content_type))

        body = self.request.body

        try:
            extracted = msgpack.loads(body)
        except Exception:
            logger.warn('Invalid message')
            raise BadRequest('Could not parse message.', body)
        return extracted

    def _handle_request_exception(self, err):
        """
        Convert ServiceErrors to HTTP errors.
        """
        logger = get_logger(self)

        payload = {}
        logger.exception(err)
        if isinstance(err, ServiceError):
            status_code = err.status_code
            if err.request_body:
                payload['request_body'] = err.request_body
        else:
            status_code = 500

        payload['resultCode'] = status_code
        payload['message'] = err.message

        self.clear()
        self.set_status(status_code)
        self.write(json.dumps(payload))
        self.finish()

class VersionHandler(BaseHandler):
    # pylint: disable=abstract-method
    """
    Return the version of the service, currently hardcoded.
    """
    import sys

    (major, minor, micro, _, _) = sys.version_info

    version = {'health': 'alive',
               'pythonVersion': '{}.{}.{}'.format(major, minor, micro),
               'version': SEMANTIC,
               'buildTime': BUILD_TIME}

    def get(self):
        """
        Return the version of the service, currently hardcoded.
        """
        request_id = self.request.headers.get('x-socrata-requestid', '')
        LogWrapper.ENV['X-Socrata-RequestId'] = request_id

        logger = get_logger(self)

        logger.info('Alive!')
        self.write(VersionHandler.version)
        self.finish()

class RenderHandler(BaseHandler):
    # pylint: disable=abstract-method, arguments-differ
    """
    Actually render the png.

    Expects a dictionary with 'style', 'zoom', and 'tile' values.
    """
    keys = ['tile', 'zoom', 'style']

    def initialize(self, http_client, style_host, style_port):
        """Magic Tornado __init__ replacement."""
        self.http_client = http_client  # pragma: no cover
        self.style_host = style_host    # pragma: no cover
        self.style_port = style_port    # pragma: no cover

    @web.asynchronous
    def post(self):
        """
        Actually render the png.

        Expects a JSON blob with 'style', 'zoom', and 'tile' values.
        """
        logger = get_logger(self)

        geobody = self.extract_body()

        if not all([k in geobody for k in self.keys]):
            logger.warn('Invalid JSON: %s', geobody)
            raise PayloadKeyError(self.keys, geobody)
        else:
            try:
                overscan = int(geobody['overscan'])
            except:
                logger.warn('Invalid JSON; overscan must be an integer: %s',
                            geobody)
                raise BadRequest('"overscan" must be an integer',
                                 request_body=geobody)

            try:
                zoom = int(geobody['zoom'])
            except:
                logger.warn('Invalid JSON; zoom must be an integer: %s',
                            geobody)
                raise BadRequest('"zoom" must be an integer.',
                                 request_body=geobody)

            path = 'http://{host}:{port}/style?style={css}'.format(
                host=self.style_host,
                port=self.style_port,
                css=quote_plus(geobody['style']))

            tile = geobody['tile']

            def handle_response(response):
                """
                Process the XML returned by the style renderer.
                """
                if response.body is None:
                    raise ServiceError(
                        "Failed to contact style-renderer at '{url}'".format(
                            url=path),
                        503)

                xml = response.body

                logger.info('zoom: %d, num features: %d, len(xml): %d',
                            zoom,
                            sum([len(layer) for layer in tile.values()]),
                            len(xml))
                logger.debug('xml: %s',
                             LogWrapper.Lazy(lambda: xml.replace('\n', ' ')))

                self.write(render_png(tile, zoom, xml, overscan))
                self.finish()

            headers = LogWrapper.ENV \
                if LogWrapper.ENV['X-Socrata-RequestId'] is not None \
                else {}

            req = HTTPRequest(path, headers=headers)
            self.http_client.fetch(req, callback=handle_response)

def main():  # pragma: no cover
    """
    Actually fire up the web server.

    Listens on 4096.
    """
    define('port', default=4096)
    define('style_host', default='localhost')
    define('style_port', default=4097)
    define('log_level', default='INFO')
    define('log_format', default='%(asctime)s %(levelname)s [%(thread)d] ' +
           '[%(X-Socrata-RequestId)s] %(name)s %(message)s')
    parse_command_line()
    init_logging()

    routes = [
        web.url(r'/', web.RedirectHandler, {'url': '/version'}),
        web.url(r'/version', VersionHandler),
        web.url(r'/render', RenderHandler, {
            'style_host': options.style_host,
            'style_port': options.style_port,
            'http_client': AsyncHTTPClient()
        }),
    ]

    app = web.Application(routes)
    app.listen(options.port)
    logger = get_logger()
    logger.info('Listening on localhost:4096...')
    IOLoop.instance().start()

if __name__ == '__main__':  # pragma: no cover
    main()
<|endoftext|>


<commit_before>#!/usr/bin/env python

"""
distutilazy
-----------

Extra distutils commands.

:license: MIT, see LICENSE for more details.
"""

from __future__ import print_function

import os
import sys

try:
    import setuptools
    from setuptools import setup
except ImportError as exp:
    setuptools = None
    from distutils.core import setup

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

import distutilazy
import distutilazy.clean
import distutilazy.test

CLASSIFIERS = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    "Programming Language :: Python",
    "Programming Language :: Python :: 2.7",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.2",
    "Programming Language :: Python :: 3.3",
    "Programming Language :: Python :: 3.4",
    "Programming Language :: Python :: 3.5",
    "Programming Language :: Python :: Implementation :: CPython",
    "Programming Language :: Python :: Implementation :: PyPy",
    "Topic :: Software Development :: Libraries :: Python Modules",
    "Topic :: System :: Archiving :: Packaging",
    "Topic :: System :: Systems Administration",
]

long_description = __doc__
with open(os.path.join(os.path.dirname(__file__), "README.rst")) as fh:
    long_description = fh.read()

params = dict(
    name = "distutilazy",
    author = "Farzad Ghanei",
    author_email = "farzad.ghanei@gmail.com",
    url = "http://github.com/farzadghanei/distutilazy/",
    packages = ["distutilazy", "distutilazy.command"],
    version = distutilazy.__version__,
    description = "Extra distutils commands",
    long_description = long_description,
    license = "MIT",
    classifiers = CLASSIFIERS,
    cmdclass = {
        "clean_pyc": distutilazy.clean.CleanPyc,
        "clean_jython_class": distutilazy.clean.CleanJythonClass,
        "clean_all": distutilazy.clean.CleanAll,
        "test": distutilazy.test.RunTests
        }
)

if setuptools:
    params.update(zip_safe = True)

dist = setup(**params)
<commit_msg>Add scripts/distutilazy to setup.py<commit_after>#!/usr/bin/env python

"""
distutilazy
-----------

Extra distutils commands.

:license: MIT, see LICENSE for more details.
"""

from __future__ import print_function

import os
import sys

try:
    import setuptools
    from setuptools import setup
except ImportError as exp:
    setuptools = None
    from distutils.core import setup

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

import distutilazy
import distutilazy.clean
import distutilazy.test

CLASSIFIERS = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    "Programming Language :: Python",
    "Programming Language :: Python :: 2.7",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.2",
    "Programming Language :: Python :: 3.3",
    "Programming Language :: Python :: 3.4",
    "Programming Language :: Python :: 3.5",
    "Programming Language :: Python :: Implementation :: CPython",
    "Programming Language :: Python :: Implementation :: PyPy",
    "Topic :: Software Development :: Libraries :: Python Modules",
    "Topic :: System :: Archiving :: Packaging",
    "Topic :: System :: Systems Administration",
]

long_description = __doc__
with open(os.path.join(os.path.dirname(__file__), "README.rst")) as fh:
    long_description = fh.read()

params = dict(
    name="distutilazy",
    author="Farzad Ghanei",
    author_email="farzad.ghanei@gmail.com",
    url="http://github.com/farzadghanei/distutilazy/",
    packages=["distutilazy", "distutilazy.command"],
    version=distutilazy.__version__,
    description="Extra distutils commands",
    long_description=long_description,
    license="MIT",
    classifiers=CLASSIFIERS,
    cmdclass={
        "clean_pyc": distutilazy.clean.CleanPyc,
        "clean_jython_class": distutilazy.clean.CleanJythonClass,
        "clean_all": distutilazy.clean.CleanAll,
        "test": distutilazy.test.RunTests
        },
    scripts=['scripts/distutilazy']
)

if setuptools:
    params.update(zip_safe = True)

dist = setup(**params)
<|endoftext|>


<commit_before>import suds

from decimal import Decimal

from uuid import uuid4

from django.utils.translation import ugettext_lazy as _

from mezzanine.conf import settings

from cartridge.shop.models import CartItem, Order, Product, ProductVariation
from cartridge.shop.utils import set_shipping
from cartridge.shop.checkout import CheckoutError

from utils import set_salestax

def tax_billship_handler(request, order_form):
    """
    Tax/billing/shipping handler - called when the first step in
    the checkout process with billing/shipping address fields is
    submitted. Implement your own and specify the path to import it
    from via the setting ``SHOP_HANDLER_BILLING_SHIPPING``.
    This function will typically contain any shipping calculation
    where the shipping amount can then be set using the function
    ``cartridge.shop.utils.set_shipping``. The Cart object is also
    accessible via ``request.cart``
    """
    settings.use_editable()
    if not request.session.get('free_shipping'):
        set_shipping(request, _("Flat rate shipping"),
                settings.SHOP_DEFAULT_SHIPPING_VALUE)

    if settings.TAX_SHIPPING:
        tax_shipping = \
                Decimal(str(request.session.get('shipping_total')))
    else:
        tax_shipping = Decimal(0)

    if request.session.get('tax_total'):
        del request.session['tax_total']

    if not settings.TAX_USE_TAXCLOUD:
        if settings.TAX_OUT_OF_STATE or \
                request.session.get('order')['shipping_detail_state'] \
                    == settings.TAX_SHOP_STATE:
            # Use the flat rate
            tax_rate = Decimal(settings.TAX_FLAT_RATE) * Decimal(str(.01))
            tax_total = (request.cart.total_price() + tax_shipping) * \
                Decimal(tax_rate)
            set_salestax(request, _("Flat sales tax"), tax_total)
        else:
            # Sweet: no sales tax
            set_salestax(request, _("Out of state"), Decimal(0))
    else:
        # Use TaxCloud.net SOAP service.
        api_key = settings.TAX_TAXCLOUD_API_KEY
        api_id = settings.TAX_TAXCLOUD_API_ID
        url = "https://api.taxcloud.net/1.0/?wsdl"
        client = suds.client.Client(url)
        order = request.session.get('order')
        settings.use_editable()
        origin = client.factory.create('Address')
        origin.Address1 = settings.TAX_SHOP_ADDRESS
        origin.Address2 = settings.TAX_SHOP_ADDRESS2
        origin.City = settings.TAX_SHOP_CITY
        origin.State = settings.TAX_SHOP_STATE
        origin.Zip5 = settings.TAX_SHOP_POSTCODE
        origin.Zip4 = settings.TAX_SHOP_POSTCODE_PLUS4
        if len(str(order['shipping_detail_postcode']).replace('-','')) == 9:
            shipping_detail_postcode_plus4 = \
                    str(order['shipping_detail_postcode'])[:-4]
            shipping_detail_postcode = \
                    str(order['shipping_detail_postcode'])[0:5]
        else:
            shipping_detail_postcode = \
                    str(order['shipping_detail_postcode'])[0:5]
            shipping_detail_postcode_plus4 = '0000'
        destination = client.factory.create('Address')
        destination.Address1 = order['shipping_detail_street']
        destination.Address2 = ''
        destination.City = order['shipping_detail_city']
        destination.State = order['shipping_detail_state']
        destination.Zip5 = shipping_detail_postcode
        destination.Zip4 = shipping_detail_postcode_plus4
        ArrayOfCartItem = client.factory.create('ArrayOfCartItem')
        items = CartItem.objects.filter(cart_id=request.session.get('cart'))
        for idx, item in enumerate(items):
            cartItem = client.factory.create('CartItem')
            cartItem.Index = idx + 1
            cartItem.ItemID = str(item.sku)
            productVariation = ProductVariation.objects.get(sku=item.sku)
            product = Product.objects.get(id=productVariation.product_id)
            cartItem.TIC = int(product.tic)
            cartItem.Price = float(item.unit_price)
            cartItem.Qty = float(item.quantity)
            ArrayOfCartItem.CartItem.append(cartItem)
        shipping = client.factory.create('CartItem')
        shipping.Index = len(items) + 1
        shipping.ItemID = str('shipping')
        shipping.TIC = int(11010)
        shipping.Price = float(tax_shipping)
        shipping.Qty = float(1)
        ArrayOfCartItem.CartItem.append(shipping)
        cartID = uuid4()
        request.session['cartID'] = cartID
        request.session.modified = True
        try:
            result = client.service.Lookup(str(api_id), str(api_key),
                str(request.user.id),
                cartID,
                ArrayOfCartItem, origin, destination, False
                )
            tax_total = 0
        except:
            raise CheckoutError("Unable to contact the TaxCloud \
            server.")
        if str(result.ResponseType) == 'OK' and \
                result.CartID == cartID:
            for CartItemResponse in result.CartItemsResponse[0]:
                tax_total += CartItemResponse.TaxAmount
        else:
            raise CheckoutError(result.Messages)
        print tax_total
        set_salestax(request, _("Sales tax for shipping address"), tax_total)

def tax_order_handler(request, order_form, order):
    """
    Tax order handler - called when the order is complete and
    contains its final data. Implement your own and specify the path
    to import it from via the setting ``SHOP_HANDLER_ORDER``.
    """
    order.tax_total = Decimal(str(request.session.get('tax_total')))
    order.total += order.tax_total
    if settings.TAX_USE_TAXCLOUD_AUTHORIZATION:
        api_key = settings.TAX_TAXCLOUD_API_KEY
        api_id = settings.TAX_TAXCLOUD_API_ID
        url = "https://api.taxcloud.net/1.0/?wsdl"
        client = suds.client.Client(url)
        result = client.service.Authorized(
                    str(api_id),
                    str(api_key),
                    str(request.user.id),
                    request.session['cartID'],
                    str(order.id),
                    order.time,
                    )
        if str(result.ResponseType) == 'OK':
            captured = client.service.Captured(str(api_id), str(api_key),
                    str(order.id))
            if str(captured.ResponseType) == 'OK':
                pass
            else:
                raise CheckoutError(result.Messages)
        else:
            raise CheckoutError(result.Messages)
    order.save()aaaaa
    del request.session['tax_type']
    del request.session['tax_total']
    try:
        del request.session['cartID']
    except:
        pass
<commit_msg>Fix typo after order.save()<commit_after>import suds

from decimal import Decimal

from uuid import uuid4

from django.utils.translation import ugettext_lazy as _

from mezzanine.conf import settings

from cartridge.shop.models import CartItem, Order, Product, ProductVariation
from cartridge.shop.utils import set_shipping
from cartridge.shop.checkout import CheckoutError

from utils import set_salestax

def tax_billship_handler(request, order_form):
    """
    Tax/billing/shipping handler - called when the first step in
    the checkout process with billing/shipping address fields is
    submitted. Implement your own and specify the path to import it
    from via the setting ``SHOP_HANDLER_BILLING_SHIPPING``.
    This function will typically contain any shipping calculation
    where the shipping amount can then be set using the function
    ``cartridge.shop.utils.set_shipping``. The Cart object is also
    accessible via ``request.cart``
    """
    settings.use_editable()
    if not request.session.get('free_shipping'):
        set_shipping(request, _("Flat rate shipping"),
                settings.SHOP_DEFAULT_SHIPPING_VALUE)

    if settings.TAX_SHIPPING:
        tax_shipping = \
                Decimal(str(request.session.get('shipping_total')))
    else:
        tax_shipping = Decimal(0)

    if request.session.get('tax_total'):
        del request.session['tax_total']

    if not settings.TAX_USE_TAXCLOUD:
        if settings.TAX_OUT_OF_STATE or \
                request.session.get('order')['shipping_detail_state'] \
                    == settings.TAX_SHOP_STATE:
            # Use the flat rate
            tax_rate = Decimal(settings.TAX_FLAT_RATE) * Decimal(str(.01))
            tax_total = (request.cart.total_price() + tax_shipping) * \
                Decimal(tax_rate)
            set_salestax(request, _("Flat sales tax"), tax_total)
        else:
            # Sweet: no sales tax
            set_salestax(request, _("Out of state"), Decimal(0))
    else:
        # Use TaxCloud.net SOAP service.
        api_key = settings.TAX_TAXCLOUD_API_KEY
        api_id = settings.TAX_TAXCLOUD_API_ID
        url = "https://api.taxcloud.net/1.0/?wsdl"
        client = suds.client.Client(url)
        order = request.session.get('order')
        settings.use_editable()
        origin = client.factory.create('Address')
        origin.Address1 = settings.TAX_SHOP_ADDRESS
        origin.Address2 = settings.TAX_SHOP_ADDRESS2
        origin.City = settings.TAX_SHOP_CITY
        origin.State = settings.TAX_SHOP_STATE
        origin.Zip5 = settings.TAX_SHOP_POSTCODE
        origin.Zip4 = settings.TAX_SHOP_POSTCODE_PLUS4
        if len(str(order['shipping_detail_postcode']).replace('-','')) == 9:
            shipping_detail_postcode_plus4 = \
                    str(order['shipping_detail_postcode'])[:-4]
            shipping_detail_postcode = \
                    str(order['shipping_detail_postcode'])[0:5]
        else:
            shipping_detail_postcode = \
                    str(order['shipping_detail_postcode'])[0:5]
            shipping_detail_postcode_plus4 = '0000'
        destination = client.factory.create('Address')
        destination.Address1 = order['shipping_detail_street']
        destination.Address2 = ''
        destination.City = order['shipping_detail_city']
        destination.State = order['shipping_detail_state']
        destination.Zip5 = shipping_detail_postcode
        destination.Zip4 = shipping_detail_postcode_plus4
        ArrayOfCartItem = client.factory.create('ArrayOfCartItem')
        items = CartItem.objects.filter(cart_id=request.session.get('cart'))
        for idx, item in enumerate(items):
            cartItem = client.factory.create('CartItem')
            cartItem.Index = idx + 1
            cartItem.ItemID = str(item.sku)
            productVariation = ProductVariation.objects.get(sku=item.sku)
            product = Product.objects.get(id=productVariation.product_id)
            cartItem.TIC = int(product.tic)
            cartItem.Price = float(item.unit_price)
            cartItem.Qty = float(item.quantity)
            ArrayOfCartItem.CartItem.append(cartItem)
        shipping = client.factory.create('CartItem')
        shipping.Index = len(items) + 1
        shipping.ItemID = str('shipping')
        shipping.TIC = int(11010)
        shipping.Price = float(tax_shipping)
        shipping.Qty = float(1)
        ArrayOfCartItem.CartItem.append(shipping)
        cartID = uuid4()
        request.session['cartID'] = cartID
        request.session.modified = True
        try:
            result = client.service.Lookup(str(api_id), str(api_key),
                str(request.user.id),
                cartID,
                ArrayOfCartItem, origin, destination, False
                )
            tax_total = 0
        except:
            raise CheckoutError("Unable to contact the TaxCloud \
            server.")
        if str(result.ResponseType) == 'OK' and \
                result.CartID == cartID:
            for CartItemResponse in result.CartItemsResponse[0]:
                tax_total += CartItemResponse.TaxAmount
        else:
            raise CheckoutError(result.Messages)
        print tax_total
        set_salestax(request, _("Sales tax for shipping address"), tax_total)

def tax_order_handler(request, order_form, order):
    """
    Tax order handler - called when the order is complete and
    contains its final data. Implement your own and specify the path
    to import it from via the setting ``SHOP_HANDLER_ORDER``.
    """
    order.tax_total = Decimal(str(request.session.get('tax_total')))
    order.total += order.tax_total
    if settings.TAX_USE_TAXCLOUD_AUTHORIZATION:
        api_key = settings.TAX_TAXCLOUD_API_KEY
        api_id = settings.TAX_TAXCLOUD_API_ID
        url = "https://api.taxcloud.net/1.0/?wsdl"
        client = suds.client.Client(url)
        result = client.service.Authorized(
                    str(api_id),
                    str(api_key),
                    str(request.user.id),
                    request.session['cartID'],
                    str(order.id),
                    order.time,
                    )
        if str(result.ResponseType) == 'OK':
            captured = client.service.Captured(str(api_id), str(api_key),
                    str(order.id))
            if str(captured.ResponseType) == 'OK':
                pass
            else:
                raise CheckoutError(result.Messages)
        else:
            raise CheckoutError(result.Messages)
    order.save()
    del request.session['tax_type']
    del request.session['tax_total']
    try:
        del request.session['cartID']
    except:
        pass
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-:

from markdown.treeprocessors import Treeprocessor
from markdown.extensions import Extension
from markdown.util import etree

from django.core.urlresolvers import reverse
import re

REPLACE1_REXP = re.compile(r'[\':\?\!,/\.\+\&]+', re.UNICODE)
REPLACE2_REXP = re.compile(r'[^-\w%]', re.UNICODE)

def github_slugify(text):
    text = text.encode('utf-8')
    from urllib import quote_plus
    text = REPLACE1_REXP.sub('', text)
    text = quote_plus(text)
    text = REPLACE2_REXP.sub('-', text.lower())
    return text

def get_unique_slug(slug, all_slugs):
    """
    Iterates until a unique slug is found
    """
    counter = 1
    orig_slug = slug

    while True:
        if slug not in all_slugs:
            return slug

        slug = '%s-%s' % (orig_slug, counter)
        counter += 1
        if counter > 2:
            print "Alalalalaa"

def fixup(elem, alist, all_slugs):
    if elem.tag.startswith('h') and elem.tag[1] >= '1' and elem.tag[1] <= '6':
        a = etree.Element('a')
        a.text = elem.text

        slug = github_slugify(a.text)
        slug = get_unique_slug(slug, all_slugs)
        all_slugs.append(slug)

        a.set("href", '#%s' % slug)
        a.set("name", '%s' % slug)
        a.set("class", "anchor")
        elem.text = None

        elem.append(a)

    if elem.tag == "a":
        url = elem.get("href")
        internal_link = True
        if url is None or len(url) < 1:
            return all_slugs
        try:
            reverse(url)
        except:
            internal_link = False
            if url[:6] == '/link/' or url[:6] == '/list/':
                internal_link = True
            if url[0] == '#':
                internal_link = True
            if elem.get('class') == 'addthis':
                internal_link = True

        from resrc.link.models import Link
        try:
            link = Link.objects.get(url=url)
            link_exists = True
        except Link.DoesNotExist:
            link_exists = False
            try:
                if url[-1] == '/':
                    link = Link.objects.get(url=url[:-1])
                else:
                    url = url + '/'
                    link = Link.objects.get(url=url)
                link_exists = True
            except Link.DoesNotExist:
                link_exists = False

        if elem.text is not None:
            elem.text = elem.text.replace('#!uds!#', '_')
            elem.text = elem.text.replace('#!ast!#', '*')

        if not internal_link:
            if not link_exists:
                elem.set("rel", "external")  # elem.set("rel", "nofollow external")
                a = etree.Element('a')
                a.set("class", "addthis tiny button secondary")
                a.text = u'add'
                elem.append(a)
            else:
                # create link icon
                icon = etree.Element("i")
                icon.text = ""
                icon.set("class", "fi-link")

                # create link to resrc page
                newlink = etree.Element('a')
                newlink.text = elem.text + ' '  # ne pas forcer l'intitulé des liens
                newlink.set(
                    "href",
                    reverse("link-single-slug", args=(link.pk, link.slug))
                )

                elem.text = ''
                # add link icon
                elem.append(icon)
                # add link to resrc page
                elem.append(newlink)

                # add span with e.g. (book)
                span = etree.Element('span')
                span.text = link.get_categories()
                elem.append(span)

        from resrc.list.models import ListLinks
        if link_exists and alist is not None:
            listlink_exists = ListLinks.objects.filter(
                alist=alist, links=link).exists()
            if not listlink_exists:
                ListLinks.objects.create(
                    alist=alist,
                    links=link
                )
            # TODO : Store all the links parsed, compare to ListLinks, remove
            # the one not there anymore

    return all_slugs

class FixupProcessor(Treeprocessor):

    def __init__(self, alist, *args, **kwargs):
        self.alist = alist
        self.all_slugs = []

    def run(self, root):
        for child in root:
            # print self.all_slugs
            self.all_slugs = fixup(child, self.alist, self.all_slugs)
            self.run(child)

        return root

class FixupExtension(Extension):

    def __init__(self, alist):
        self.alist = alist

    def extendMarkdown(self, md, md_globals):
        md.treeprocessors.add('fixup', FixupProcessor(self.alist), '_end')
<commit_msg>bugfix<commit_after># -*- coding: utf-8 -*-:

from markdown.treeprocessors import Treeprocessor
from markdown.extensions import Extension
from markdown.util import etree

from django.core.urlresolvers import reverse
import re

REPLACE1_REXP = re.compile(r'[\':\?\!,/\.\+\&]+', re.UNICODE)
REPLACE2_REXP = re.compile(r'[^-\w%]', re.UNICODE)

def github_slugify(text):
    if text is None:
        return text
    text = text.encode('utf-8')
    from urllib import quote_plus
    text = REPLACE1_REXP.sub('', text)
    text = quote_plus(text)
    text = REPLACE2_REXP.sub('-', text.lower())
    return text

def get_unique_slug(slug, all_slugs):
    """
    Iterates until a unique slug is found
    """
    counter = 1
    orig_slug = slug

    while True:
        if slug not in all_slugs:
            return slug

        slug = '%s-%s' % (orig_slug, counter)
        counter += 1

def fixup(elem, alist, all_slugs):
    if elem.tag.startswith('h') and elem.tag[1] >= '1' and elem.tag[1] <= '6':
        a = etree.Element('a')
        a.text = elem.text

        slug = github_slugify(a.text)
        slug = get_unique_slug(slug, all_slugs)
        all_slugs.append(slug)

        a.set("href", '#%s' % slug)
        a.set("name", '%s' % slug)
        a.set("class", "anchor")
        elem.text = None

        elem.append(a)

    if elem.tag == "a":
        url = elem.get("href")
        internal_link = True
        if url is None or len(url) < 1:
            return all_slugs
        try:
            reverse(url)
        except:
            internal_link = False
            if url[:6] == '/link/' or url[:6] == '/list/':
                internal_link = True
            if url[0] == '#':
                internal_link = True
            if elem.get('class') == 'addthis':
                internal_link = True

        from resrc.link.models import Link
        try:
            link = Link.objects.get(url=url)
            link_exists = True
        except Link.DoesNotExist:
            link_exists = False
            try:
                if url[-1] == '/':
                    link = Link.objects.get(url=url[:-1])
                else:
                    url = url + '/'
                    link = Link.objects.get(url=url)
                link_exists = True
            except Link.DoesNotExist:
                link_exists = False

        if elem.text is not None:
            elem.text = elem.text.replace('#!uds!#', '_')
            elem.text = elem.text.replace('#!ast!#', '*')

        if not internal_link:
            if not link_exists:
                elem.set("rel", "external")  # elem.set("rel", "nofollow external")
                a = etree.Element('a')
                a.set("class", "addthis tiny button secondary")
                a.text = u'add'
                elem.append(a)
            else:
                # create link icon
                icon = etree.Element("i")
                icon.text = ""
                icon.set("class", "fi-link")

                # create link to resrc page
                newlink = etree.Element('a')
                newlink.text = elem.text + ' '  # ne pas forcer l'intitulé des liens
                newlink.set(
                    "href",
                    reverse("link-single-slug", args=(link.pk, link.slug))
                )

                elem.text = ''
                # add link icon
                elem.append(icon)
                # add link to resrc page
                elem.append(newlink)

                # add span with e.g. (book)
                span = etree.Element('span')
                span.text = link.get_categories()
                elem.append(span)

        from resrc.list.models import ListLinks
        if link_exists and alist is not None:
            listlink_exists = ListLinks.objects.filter(
                alist=alist, links=link).exists()
            if not listlink_exists:
                ListLinks.objects.create(
                    alist=alist,
                    links=link
                )
            # TODO : Store all the links parsed, compare to ListLinks, remove
            # the one not there anymore

    return all_slugs

class FixupProcessor(Treeprocessor):

    def __init__(self, alist, *args, **kwargs):
        self.alist = alist
        self.all_slugs = []

    def run(self, root):
        for child in root:
            # print self.all_slugs
            self.all_slugs = fixup(child, self.alist, self.all_slugs)
            self.run(child)

        return root

class FixupExtension(Extension):

    def __init__(self, alist):
        self.alist = alist

    def extendMarkdown(self, md, md_globals):
        md.treeprocessors.add('fixup', FixupProcessor(self.alist), '_end')
<|endoftext|>


<commit_before>from castra import Castra
import pandas as pd
import pandas.util.testing as tm

A = pd.DataFrame({'x': [1, 2],
                  'y': [1., 2.]},
                 columns=['x', 'y'],
                 index=[1, 2])

B = pd.DataFrame({'x': [10, 20],
                  'y': [10., 20.]},
                 columns=['x', 'y'],
                 index=[10, 20])

def test_Castra():
    c = Castra(A.columns, A.dtypes, A.index.dtype)
    c.extend(A)
    c.extend(B)

    assert c.columns == ['x', 'y']

    tm.assert_frame_equal(c[0:100], pd.concat([A, B]))
    tm.assert_frame_equal(c[:5], A)
    tm.assert_frame_equal(c[5:], B)
<commit_msg>test for trimming first and last dataframe<commit_after>from castra import Castra
import pandas as pd
import pandas.util.testing as tm

A = pd.DataFrame({'x': [1, 2],
                  'y': [1., 2.]},
                 columns=['x', 'y'],
                 index=[1, 2])

B = pd.DataFrame({'x': [10, 20],
                  'y': [10., 20.]},
                 columns=['x', 'y'],
                 index=[10, 20])

def test_Castra():
    c = Castra(A.columns, A.dtypes, A.index.dtype)
    c.extend(A)
    c.extend(B)

    assert c.columns == ['x', 'y']

    tm.assert_frame_equal(c[0:100], pd.concat([A, B]))
    tm.assert_frame_equal(c[:5], A)
    tm.assert_frame_equal(c[5:], B)

    tm.assert_frame_equal(c[2:5], A[1:])
    tm.assert_frame_equal(c[2:15], pd.concat([A[1:], B[:1]]))
<|endoftext|>


<commit_before>#!/usr/bin/env python3
from setuptools import setup, find_packages

def get_long_description():
    try:
        import pypandoc
        return pypandoc.convert('README.md', 'rst')
    except (IOError, ImportError, RuntimeError):
        print('WARNING: Please install pypandoc and pandoc. Otherwise long description will not be available.')

setup(
    name='openbrokerapi',
    version='0.1',
    packages=find_packages(),
    install_requires=['flask'],
    test_suite="test",

    # Metadata
    author="Maic Siemering",
    author_email="eruvanos@ewetel.net",
    license="MIT",
    description="A python package for the V2 CF Service Broker API and Open Broker API",
    long_description=get_long_description(),
    url="https://github.com/eruvanos/openbrokerapi",
    keywords=["cloudfoundry", "cfbrokerapi", "openbrokerapi", "servicebroker", "flask"],
    classifiers=[
        # How mature is this project? Common values are
        #   3 - Alpha
        #   4 - Beta
        #   5 - Production/Stable
        'Development Status :: 4 - Beta',

        # Indicate who your project is intended for
        'Intended Audience :: Developers',

        # Pick your license as you wish (should match "license" above)
        'License :: OSI Approved :: MIT License',

        'Operating System :: OS Independent',

        # Specify the Python versions you support here. In particular, ensure
        # that you indicate whether you support Python 2, Python 3 or both.
        'Programming Language :: Python :: 3.6',
    ],

)
<commit_msg>Start developing v0.2<commit_after>#!/usr/bin/env python3
from setuptools import setup, find_packages

def get_long_description():
    try:
        import pypandoc
        return pypandoc.convert('README.md', 'rst')
    except (IOError, ImportError, RuntimeError):
        print('WARNING: Please install pypandoc and pandoc. Otherwise long description will not be available.')

setup(
    name='openbrokerapi',
    version='0.2.dev0',
    packages=find_packages(),
    install_requires=['flask'],
    test_suite="test",

    # Metadata
    author="Maic Siemering",
    author_email="eruvanos@ewetel.net",
    license="MIT",
    description="A python package for the V2 CF Service Broker API and Open Broker API",
    long_description=get_long_description(),
    url="https://github.com/eruvanos/openbrokerapi",
    keywords=["cloudfoundry", "cfbrokerapi", "openbrokerapi", "servicebroker", "flask"],
    classifiers=[
        # How mature is this project? Common values are
        #   3 - Alpha
        #   4 - Beta
        #   5 - Production/Stable
        'Development Status :: 4 - Beta',

        # Indicate who your project is intended for
        'Intended Audience :: Developers',

        # Pick your license as you wish (should match "license" above)
        'License :: OSI Approved :: MIT License',

        'Operating System :: OS Independent',

        # Specify the Python versions you support here. In particular, ensure
        # that you indicate whether you support Python 2, Python 3 or both.
        'Programming Language :: Python :: 3.6',
    ],

)
<|endoftext|>


<commit_before>#
# Copyright (c) 2008 rPath, Inc.
#

import base64
import BaseHTTPServer
import os
import urllib

from catalogService import config
from catalogService import request as brequest
from catalogService import storage
from catalogService import userData

# Make it easy for the producers of responses
Response = brequest.Response

class StorageConfig(config.BaseConfig):
    def __init__(self, storagePath):
        config.BaseConfig.__init__(self)
        self.storagePath = storagePath

class StandaloneRequest(brequest.BaseRequest):
    __slots__ = [ '_req', 'read' ]

    def __init__(self, req):
        brequest.BaseRequest.__init__(self)
        self._req = req
        self.read = self._req.rfile.read

    def getRelativeURI(self):
        return self._req.path

    def getSchemeNetloc(self):
        hostport = self._req.host
        if self._req.port != 80 and ':' not in hostport:
            hostport = "%s:%s" % (self._req.host, self._req.port)
        return "http://%s" % (hostport, )

    def getHeader(self, key):
        return self._req.headers.get(key, None)

    def iterHeaders(self):
        for k, v in self._req.headers.items():
            yield k, v

class BaseRESTHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    toplevel = 'TOPLEVEL'
    storageConfig = StorageConfig(storagePath = "storage")
    logLevel = 1

    def log_message(self, *args, **kwargs):
        if self.logLevel > 0:
            BaseHTTPServer.BaseHTTPRequestHandler.log_message(self,
                *args, **kwargs)

    def do_GET(self):
        return self.processRequest(self._do_GET)

    def do_POST(self):
        return self.processRequest(self._do_POST)

    def do_PUT(self):
        return self.processRequest(self._do_PUT)

    def do_DELETE(self):
        return self.processRequest(self._do_DELETE)

    def processRequest(self, method):
        if self.logLevel > 0:
            # Dump the headers
            for k, v in sorted(self.headers.items()):
                print "    %-20s : %s" % (k, v)
        req = self._createRequest()
        if req is None:
            # _createRequest does all the work to send back the error codes
            return

        try:
            return method(req)
        except:
            # XXX
            raise

    def _do_GET(self, req):
        # we know the method, we're just using common code to strip it.
        path, method = self._get_method(req.getRelativeURI(), 'GET')
        # XXX will have to strip out arguments
        if path == '/crossdomain.xml':
            return self._handleResponse(self.serveCrossDomainFile())
        if path == '/%s/clouds/ec2/images' % self.toplevel:
            return self.enumerateImages(req)
        if path == '/%s/clouds/ec2/instances' % self.toplevel:
            return self.enumerateInstances(req)
        if path == '/%s/clouds/ec2/instanceTypes' % self.toplevel:
            return self.enumerateInstanceTypes(req)
        p = '/%s/users/' % self.toplevel
        if path.startswith(p):
            return self._handleResponse(self.getUserData(req, p, path[len(p):]))
        p = '/%s/clouds/ec2/users/' % self.toplevel
        if self.path.startswith(p):
            rp = self.path[len(p):]
            cloudPrefix = '/%s/clouds/ec2' % self.toplevel
            # Grab the user part
            arr = rp.split('/')
            userId = urllib.unquote(arr[0])
            if userId != req.getUser():
                for k, v in req.iterHeaders():
                    print "%s: %s" % (k, v)
                raise Exception("XXX 1", userId, req.getUser())
            if arr[1:] == ['environment']:
                return self._handleResponse(self.getEnvironment(req,
                    cloudPrefix))

    def _do_PUT(self, req):
        p = '/%s/users/' % self.toplevel
        if self.path.startswith(p):
            return self._handleResponse(self.setUserData(req, self.path[len(p):]))

    def _do_POST(self, req):
        p = '/%s/users/' % self.toplevel
        # Look for a method
        path, method = self._get_method(req.getRelativeURI(), 'POST')
        if method == 'GET':
            return self._do_GET(req)

        if path.startswith(p):
            pRest = path[len(p):]
            if method == 'POST':
                self._handleResponse(self.addUserData(req, pRest))
            elif method == 'DELETE':
                self._handleResponse(self.deleteUserData(req, pRest))
            elif method == 'PUT':
                self._handleResponse(self.setUserData(req, pRest))
            return

        p = '/%s/clouds/ec2/instances' % self.toplevel
        if path == p:
            self._handleResponse(self.newInstance(req))
            return
        p += '/'
        if path.startswith(p):
            pRest = path[len(p):]
            if method == 'DELETE':
                arr = pRest.split('/')
                if arr:
                    instanceId = arr[0]
                    self._handleResponse(self.terminateInstance(req, instanceId,
                                         prefix = p))
            return

    def _do_DELETE(self, req):
        p = '/%s/users/' % self.toplevel
        if self.path.startswith(p):
            self._handleResponse(self.deleteUserData(req, self.path[len(p):]))

        p = '/%s/clouds/ec2/instances/' % self.toplevel
        if self.path.startswith(p):
            arr = self.path[len(p):].split('/')
            if arr:
                instanceId = arr[0]
                self._handleResponse(self.terminateInstance(req, instanceId,
                                     prefix = p))

    @classmethod
    def _get_method(cls, path, defaultMethod):
        """
        Given a path, retrieve the method from it (part of the query)
        Return path and method (None if no method)
        """
        path, query = urllib.splitquery(path)
        if not query:
            return path, defaultMethod
        rMap = cls._split_query(query)
        return path, rMap.get('_method', defaultMethod)

    @staticmethod
    def _split_query(query):
        rMap = {}
        for v in query.split('&'):
            arr = v.split('=', 1)
            if len(arr) != 2:
                continue
            rMap[arr[0]] = arr[1]
        return rMap

    def _createRequest(self):
        req = self._validateHeaders()
        if req is None:
            return None
        if not self._auth(req):
            return None
        return req

    def _validateHeaders(self):
        if 'Host' not in self.headers:
            # Missing Host: header
            self.send_error(400)
            return

        if 'Authorization' not in self.headers:
            self._send_401()
            return

        self.host = self.headers['Host']
        self.port = self.server.server_port
        req = StandaloneRequest(self)
        return req

    def _send_401(self):
        self.send_response(401, "Unauthorized")
        self.send_header('WWW-Authenticate', 'Basic realm="blah"')
        self.send_header('Content-Type', 'text/html')
        self.send_header('Connection', 'close')
        self.end_headers()

    def _auth(self, req):
        authData = self.headers['Authorization']
        if authData[:6] != 'Basic ':
            self._send_401()
            return False
        authData = authData[6:]
        authData = base64.decodestring(authData)
        authData = authData.split(':', 1)
        req.setUser(authData[0])
        req.setPassword(authData[1])
        self.mintClient = self._getMintClient(authData)
        # explicitly authenticate the credentials against rBuilder to get
        # the rBuilder userId
        self.mintAuth = self.mintClient.checkAuth()
        return True

    def _handleResponse(self, response):
        response.addContentLength()
        self.send_response(response.getCode())
        for k, v in response.iterHeaders():
            self.send_header(k, v)
        self.end_headers()

        response.serveResponse(self.wfile.write)

    def _getMintConfig(self):
        import mint.config
        if not hasattr(self, 'mintCfg'):
            self.mintCfg = mint.config.getConfig()
        return self.mintCfg

    def _getMintClient(self, authToken):
        if self.storageConfig.rBuilderUrl:
            import mint.client
            return mint.client.MintClient( \
                    self.storageConfig.rBuilderUrl % tuple(authToken[:2]))
        else:
            import mint.shimclient
            mintCfg = self._getMintConfig()
            return mint.shimclient.ShimMintClient(mintCfg, authToken)

    def getEC2Credentials(self):
        cred = self.mintClient.getEC2CredentialsForUser(self.mintAuth.userId)
        return (cred.get('awsPublicAccessKeyId', cred.get('awsSecretAccessKey'))

    def enumerateImages(self, req):
        import images
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = req.getAbsoluteURI()
        node = drv.getAllImages(prefix = prefix)
        hndlr = images.Handler()
        data = hndlr.toXml(node)

        self.send_response(200)
        self.send_header("Content-Type", "application/xml")
        self.send_header("Content-Length", len(data))
        self.end_headers()
        self.wfile.write(data)

    def enumerateInstances(self, req):
        import images
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = req.getAbsoluteURI()
        node = drv.getAllInstances(prefix = prefix)
        hndlr = images.Handler()
        data = hndlr.toXml(node)

        self.send_response(200)
        self.send_header("Content-Type", "application/xml")
        self.send_header("Content-Length", len(data))
        self.end_headers()
        self.wfile.write(data)

    def enumerateInstanceTypes(self, req):
        import images
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = req.getAbsoluteURI()
        node = drv.getAllInstanceTypes(prefix=prefix)

        hndlr = images.Handler()
        data = hndlr.toXml(node)

        self.send_response(200)
        self.send_header("Content-Type", "application/xml")
        self.send_header("Content-Length", len(data))
        self.end_headers()
        self.wfile.write(data)

    def serveCrossDomainFile(self):
        path = "crossdomain.xml"
        f = open(path)
        return Response(contentType = 'application/xml', fileObj = f)

    def addUserData(self, req, userData):
        # Split the arguments
        userData = userData.split('/')
        if userData[0] != req.getUser():
            raise Exception("XXX 1", userData[0], req.getUser())

        dataLen = req.getContentLength()
        data = req.read(dataLen)
        store = storage.DiskStorage(self.storageConfig)

        keyPrefix = '/'.join(x for x in userData if x not in ('', '.', '..'))

        newId = store.store(data, keyPrefix = keyPrefix)
        response = '<?xml version="1.0" encoding="UTF-8"?><id>%s/%s</id>' % (
            req.getAbsoluteURI(), os.path.basename(newId))
        return Response(contentType = "text/xml", data = response)

    def getUserData(self, req, prefix, keyPath):
        # Split the arguments
        arr = keyPath.split('/')
        if arr[0] != req.getUser():
            raise Exception("XXX 1", arr[0], req.getUser())

        prefix = "%s%s" % (req.getSchemeNetloc(), prefix)
        store = storage.DiskStorage(self.storageConfig)

        key = keyPath.rstrip('/')

        if key != keyPath:
            # A trailing / means retrieving the contents from a collection
            if not store.isCollection(key):
                raise Exception("XXX 2", prefix, keyPath)

        if store.isCollection(key):
            node = userData.IdsNode()
            snodes = store.enumerate(keyPrefix = key)

            if key == keyPath:
                # No trailing /
                snodes = [ userData.IdNode().characters("%s%s" % (prefix, x))
                         for x in snodes ]
                node.extend(snodes)
                return Response(data = node)
            # Grab contents and wrap them in some XML
            data = [ store.get(x) for x in snodes ]
            data = '<list>%s</list>' % ''.join(data)
            return Response(data = data)

        data = store.get(key)
        code = None
        if data is None:
            data = '<?xml version="1.0" encoding="UTF-8"?><error></error>'
            code = 404
        return Response(contentType = "application/xml", data = data,
                        code = code)

    def setUserData(self, req, userData):
        userData = userData.split('/')
        if userData[0] != req.getUser():
            raise Exception("XXX 1")

        dataLen = req.getContentLength()
        data = req.read(dataLen)

        store = storage.DiskStorage(self.storageConfig)
        key = '/'.join(x for x in userData if x not in ('', '.', '..'))
        store.set(key, data)
        response = '<?xml version="1.0" encoding="UTF-8"?><id>%s</id>' % (
            req.getAbsoluteURIPath(), )
        return Response(contentType = "text/xml", data = response)

    def deleteUserData(self, req, userData):
        userData = userData.split('/')
        if userData[0] != req.getUser():
            raise Exception("XXX 1")

        store = storage.DiskStorage(self.storageConfig)
        key = '/'.join(x for x in userData if x not in ('', '.', '..'))
        store.delete(key)
        response = '<?xml version="1.0" encoding="UTF-8"?><id>%s</id>' % (
            req.getAbsoluteURIPath(), )
        return Response(contentType = "text/xml", data = response)

    def getEnvironment(self, req, cloudPrefix):
        import environment
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = "%s%s" % (req.getSchemeNetloc(), cloudPrefix)
        node = drv.getEnvironment(prefix=prefix)

        hndlr = environment.Handler()
        data = hndlr.toXml(node)

        return Response(contentType="application/xml", data = data)

    def newInstance(self, req):
        import newInstance
        import driver_ec2
        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        dataLen = req.getContentLength()
        data = req.read(dataLen)

        prefix = req.getAbsoluteURI()
        response = drv.newInstance(data, prefix = prefix)

        hndlr = newInstance.Handler()
        data = hndlr.toXml(response)

        return Response(contentType="application/xml", data = data)

    def terminateInstance(self, req, instanceId, prefix):
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = req.getSchemeNetloc() + prefix
        response = drv.terminateInstance(instanceId, prefix = prefix)

        hndlr = driver_ec2.instances.Handler()
        data = hndlr.toXml(response)

        return Response(contentType="application/xml", data = data)

class HTTPServer(BaseHTTPServer.HTTPServer):
    pass

if __name__ == '__main__':
    import optparse
    parser = optparse.OptionParser()
    parser.add_option('-c', '--config-file', dest = 'configFile',
            help = 'location of config file to use')
    parser.add_option('-p', '--port', dest = 'port', type = 'int',
            default = 1234, help = 'port to listen on')

    options, args = parser.parse_args()
    storageConfig = StorageConfig(storagePath = "storage")
    if options.configFile:
        storageConfig.read(options.configFile)
    BaseRESTHandler.storageConfig = storageConfig

    h = HTTPServer(("", options.port), BaseRESTHandler)
    h.serve_forever()
<commit_msg>fix typo<commit_after>#
# Copyright (c) 2008 rPath, Inc.
#

import base64
import BaseHTTPServer
import os
import urllib

from catalogService import config
from catalogService import request as brequest
from catalogService import storage
from catalogService import userData

# Make it easy for the producers of responses
Response = brequest.Response

class StorageConfig(config.BaseConfig):
    def __init__(self, storagePath):
        config.BaseConfig.__init__(self)
        self.storagePath = storagePath

class StandaloneRequest(brequest.BaseRequest):
    __slots__ = [ '_req', 'read' ]

    def __init__(self, req):
        brequest.BaseRequest.__init__(self)
        self._req = req
        self.read = self._req.rfile.read

    def getRelativeURI(self):
        return self._req.path

    def getSchemeNetloc(self):
        hostport = self._req.host
        if self._req.port != 80 and ':' not in hostport:
            hostport = "%s:%s" % (self._req.host, self._req.port)
        return "http://%s" % (hostport, )

    def getHeader(self, key):
        return self._req.headers.get(key, None)

    def iterHeaders(self):
        for k, v in self._req.headers.items():
            yield k, v

class BaseRESTHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    toplevel = 'TOPLEVEL'
    storageConfig = StorageConfig(storagePath = "storage")
    logLevel = 1

    def log_message(self, *args, **kwargs):
        if self.logLevel > 0:
            BaseHTTPServer.BaseHTTPRequestHandler.log_message(self,
                *args, **kwargs)

    def do_GET(self):
        return self.processRequest(self._do_GET)

    def do_POST(self):
        return self.processRequest(self._do_POST)

    def do_PUT(self):
        return self.processRequest(self._do_PUT)

    def do_DELETE(self):
        return self.processRequest(self._do_DELETE)

    def processRequest(self, method):
        if self.logLevel > 0:
            # Dump the headers
            for k, v in sorted(self.headers.items()):
                print "    %-20s : %s" % (k, v)
        req = self._createRequest()
        if req is None:
            # _createRequest does all the work to send back the error codes
            return

        try:
            return method(req)
        except:
            # XXX
            raise

    def _do_GET(self, req):
        # we know the method, we're just using common code to strip it.
        path, method = self._get_method(req.getRelativeURI(), 'GET')
        # XXX will have to strip out arguments
        if path == '/crossdomain.xml':
            return self._handleResponse(self.serveCrossDomainFile())
        if path == '/%s/clouds/ec2/images' % self.toplevel:
            return self.enumerateImages(req)
        if path == '/%s/clouds/ec2/instances' % self.toplevel:
            return self.enumerateInstances(req)
        if path == '/%s/clouds/ec2/instanceTypes' % self.toplevel:
            return self.enumerateInstanceTypes(req)
        p = '/%s/users/' % self.toplevel
        if path.startswith(p):
            return self._handleResponse(self.getUserData(req, p, path[len(p):]))
        p = '/%s/clouds/ec2/users/' % self.toplevel
        if self.path.startswith(p):
            rp = self.path[len(p):]
            cloudPrefix = '/%s/clouds/ec2' % self.toplevel
            # Grab the user part
            arr = rp.split('/')
            userId = urllib.unquote(arr[0])
            if userId != req.getUser():
                for k, v in req.iterHeaders():
                    print "%s: %s" % (k, v)
                raise Exception("XXX 1", userId, req.getUser())
            if arr[1:] == ['environment']:
                return self._handleResponse(self.getEnvironment(req,
                    cloudPrefix))

    def _do_PUT(self, req):
        p = '/%s/users/' % self.toplevel
        if self.path.startswith(p):
            return self._handleResponse(self.setUserData(req, self.path[len(p):]))

    def _do_POST(self, req):
        p = '/%s/users/' % self.toplevel
        # Look for a method
        path, method = self._get_method(req.getRelativeURI(), 'POST')
        if method == 'GET':
            return self._do_GET(req)

        if path.startswith(p):
            pRest = path[len(p):]
            if method == 'POST':
                self._handleResponse(self.addUserData(req, pRest))
            elif method == 'DELETE':
                self._handleResponse(self.deleteUserData(req, pRest))
            elif method == 'PUT':
                self._handleResponse(self.setUserData(req, pRest))
            return

        p = '/%s/clouds/ec2/instances' % self.toplevel
        if path == p:
            self._handleResponse(self.newInstance(req))
            return
        p += '/'
        if path.startswith(p):
            pRest = path[len(p):]
            if method == 'DELETE':
                arr = pRest.split('/')
                if arr:
                    instanceId = arr[0]
                    self._handleResponse(self.terminateInstance(req, instanceId,
                                         prefix = p))
            return

    def _do_DELETE(self, req):
        p = '/%s/users/' % self.toplevel
        if self.path.startswith(p):
            self._handleResponse(self.deleteUserData(req, self.path[len(p):]))

        p = '/%s/clouds/ec2/instances/' % self.toplevel
        if self.path.startswith(p):
            arr = self.path[len(p):].split('/')
            if arr:
                instanceId = arr[0]
                self._handleResponse(self.terminateInstance(req, instanceId,
                                     prefix = p))

    @classmethod
    def _get_method(cls, path, defaultMethod):
        """
        Given a path, retrieve the method from it (part of the query)
        Return path and method (None if no method)
        """
        path, query = urllib.splitquery(path)
        if not query:
            return path, defaultMethod
        rMap = cls._split_query(query)
        return path, rMap.get('_method', defaultMethod)

    @staticmethod
    def _split_query(query):
        rMap = {}
        for v in query.split('&'):
            arr = v.split('=', 1)
            if len(arr) != 2:
                continue
            rMap[arr[0]] = arr[1]
        return rMap

    def _createRequest(self):
        req = self._validateHeaders()
        if req is None:
            return None
        if not self._auth(req):
            return None
        return req

    def _validateHeaders(self):
        if 'Host' not in self.headers:
            # Missing Host: header
            self.send_error(400)
            return

        if 'Authorization' not in self.headers:
            self._send_401()
            return

        self.host = self.headers['Host']
        self.port = self.server.server_port
        req = StandaloneRequest(self)
        return req

    def _send_401(self):
        self.send_response(401, "Unauthorized")
        self.send_header('WWW-Authenticate', 'Basic realm="blah"')
        self.send_header('Content-Type', 'text/html')
        self.send_header('Connection', 'close')
        self.end_headers()

    def _auth(self, req):
        authData = self.headers['Authorization']
        if authData[:6] != 'Basic ':
            self._send_401()
            return False
        authData = authData[6:]
        authData = base64.decodestring(authData)
        authData = authData.split(':', 1)
        req.setUser(authData[0])
        req.setPassword(authData[1])
        self.mintClient = self._getMintClient(authData)
        # explicitly authenticate the credentials against rBuilder to get
        # the rBuilder userId
        self.mintAuth = self.mintClient.checkAuth()
        return True

    def _handleResponse(self, response):
        response.addContentLength()
        self.send_response(response.getCode())
        for k, v in response.iterHeaders():
            self.send_header(k, v)
        self.end_headers()

        response.serveResponse(self.wfile.write)

    def _getMintConfig(self):
        import mint.config
        if not hasattr(self, 'mintCfg'):
            self.mintCfg = mint.config.getConfig()
        return self.mintCfg

    def _getMintClient(self, authToken):
        if self.storageConfig.rBuilderUrl:
            import mint.client
            return mint.client.MintClient( \
                    self.storageConfig.rBuilderUrl % tuple(authToken[:2]))
        else:
            import mint.shimclient
            mintCfg = self._getMintConfig()
            return mint.shimclient.ShimMintClient(mintCfg, authToken)

    def getEC2Credentials(self):
        cred = self.mintClient.getEC2CredentialsForUser(self.mintAuth.userId)
        return (cred.get('awsPublicAccessKeyId',
            cred.get('awsSecretAccessKey')))

    def enumerateImages(self, req):
        import images
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = req.getAbsoluteURI()
        node = drv.getAllImages(prefix = prefix)
        hndlr = images.Handler()
        data = hndlr.toXml(node)

        self.send_response(200)
        self.send_header("Content-Type", "application/xml")
        self.send_header("Content-Length", len(data))
        self.end_headers()
        self.wfile.write(data)

    def enumerateInstances(self, req):
        import images
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = req.getAbsoluteURI()
        node = drv.getAllInstances(prefix = prefix)
        hndlr = images.Handler()
        data = hndlr.toXml(node)

        self.send_response(200)
        self.send_header("Content-Type", "application/xml")
        self.send_header("Content-Length", len(data))
        self.end_headers()
        self.wfile.write(data)

    def enumerateInstanceTypes(self, req):
        import images
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = req.getAbsoluteURI()
        node = drv.getAllInstanceTypes(prefix=prefix)

        hndlr = images.Handler()
        data = hndlr.toXml(node)

        self.send_response(200)
        self.send_header("Content-Type", "application/xml")
        self.send_header("Content-Length", len(data))
        self.end_headers()
        self.wfile.write(data)

    def serveCrossDomainFile(self):
        path = "crossdomain.xml"
        f = open(path)
        return Response(contentType = 'application/xml', fileObj = f)

    def addUserData(self, req, userData):
        # Split the arguments
        userData = userData.split('/')
        if userData[0] != req.getUser():
            raise Exception("XXX 1", userData[0], req.getUser())

        dataLen = req.getContentLength()
        data = req.read(dataLen)
        store = storage.DiskStorage(self.storageConfig)

        keyPrefix = '/'.join(x for x in userData if x not in ('', '.', '..'))

        newId = store.store(data, keyPrefix = keyPrefix)
        response = '<?xml version="1.0" encoding="UTF-8"?><id>%s/%s</id>' % (
            req.getAbsoluteURI(), os.path.basename(newId))
        return Response(contentType = "text/xml", data = response)

    def getUserData(self, req, prefix, keyPath):
        # Split the arguments
        arr = keyPath.split('/')
        if arr[0] != req.getUser():
            raise Exception("XXX 1", arr[0], req.getUser())

        prefix = "%s%s" % (req.getSchemeNetloc(), prefix)
        store = storage.DiskStorage(self.storageConfig)

        key = keyPath.rstrip('/')

        if key != keyPath:
            # A trailing / means retrieving the contents from a collection
            if not store.isCollection(key):
                raise Exception("XXX 2", prefix, keyPath)

        if store.isCollection(key):
            node = userData.IdsNode()
            snodes = store.enumerate(keyPrefix = key)

            if key == keyPath:
                # No trailing /
                snodes = [ userData.IdNode().characters("%s%s" % (prefix, x))
                         for x in snodes ]
                node.extend(snodes)
                return Response(data = node)
            # Grab contents and wrap them in some XML
            data = [ store.get(x) for x in snodes ]
            data = '<list>%s</list>' % ''.join(data)
            return Response(data = data)

        data = store.get(key)
        code = None
        if data is None:
            data = '<?xml version="1.0" encoding="UTF-8"?><error></error>'
            code = 404
        return Response(contentType = "application/xml", data = data,
                        code = code)

    def setUserData(self, req, userData):
        userData = userData.split('/')
        if userData[0] != req.getUser():
            raise Exception("XXX 1")

        dataLen = req.getContentLength()
        data = req.read(dataLen)

        store = storage.DiskStorage(self.storageConfig)
        key = '/'.join(x for x in userData if x not in ('', '.', '..'))
        store.set(key, data)
        response = '<?xml version="1.0" encoding="UTF-8"?><id>%s</id>' % (
            req.getAbsoluteURIPath(), )
        return Response(contentType = "text/xml", data = response)

    def deleteUserData(self, req, userData):
        userData = userData.split('/')
        if userData[0] != req.getUser():
            raise Exception("XXX 1")

        store = storage.DiskStorage(self.storageConfig)
        key = '/'.join(x for x in userData if x not in ('', '.', '..'))
        store.delete(key)
        response = '<?xml version="1.0" encoding="UTF-8"?><id>%s</id>' % (
            req.getAbsoluteURIPath(), )
        return Response(contentType = "text/xml", data = response)

    def getEnvironment(self, req, cloudPrefix):
        import environment
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = "%s%s" % (req.getSchemeNetloc(), cloudPrefix)
        node = drv.getEnvironment(prefix=prefix)

        hndlr = environment.Handler()
        data = hndlr.toXml(node)

        return Response(contentType="application/xml", data = data)

    def newInstance(self, req):
        import newInstance
        import driver_ec2
        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        dataLen = req.getContentLength()
        data = req.read(dataLen)

        prefix = req.getAbsoluteURI()
        response = drv.newInstance(data, prefix = prefix)

        hndlr = newInstance.Handler()
        data = hndlr.toXml(response)

        return Response(contentType="application/xml", data = data)

    def terminateInstance(self, req, instanceId, prefix):
        import driver_ec2

        awsPublicKey, awsPrivateKey = self.getEC2Credentials()

        cfg = driver_ec2.Config(awsPublicKey, awsPrivateKey)

        drv = driver_ec2.Driver(cfg)

        prefix = req.getSchemeNetloc() + prefix
        response = drv.terminateInstance(instanceId, prefix = prefix)

        hndlr = driver_ec2.instances.Handler()
        data = hndlr.toXml(response)

        return Response(contentType="application/xml", data = data)

class HTTPServer(BaseHTTPServer.HTTPServer):
    pass

if __name__ == '__main__':
    import optparse
    parser = optparse.OptionParser()
    parser.add_option('-c', '--config-file', dest = 'configFile',
            help = 'location of config file to use')
    parser.add_option('-p', '--port', dest = 'port', type = 'int',
            default = 1234, help = 'port to listen on')

    options, args = parser.parse_args()
    storageConfig = StorageConfig(storagePath = "storage")
    if options.configFile:
        storageConfig.read(options.configFile)
    BaseRESTHandler.storageConfig = storageConfig

    h = HTTPServer(("", options.port), BaseRESTHandler)
    h.serve_forever()
<|endoftext|>


<commit_before>from setuptools import setup

setup(
    name='tangled.website',
    version='0.1.dev0',
    description='tangledframework.org',
    long_description=open('README.rst').read(),
    url='http://tangledframework.org/',
    download_url='https://github.com/TangledWeb/tangled.website/tags',
    author='Wyatt Baldwin',
    author_email='self@wyattbaldwin.com',
    packages=[
        'tangled',
        'tangled.website',
    ],
    include_package_data=True,
    install_requires=[
        'tangled.auth>=0.1a3',
        'tangled.session>=0.1a2',
        'tangled.site>=0.1a2',
        'SQLAlchemy>=1.1.6',
    ],
    extras_require={
        'dev': ['coverage'],
    },
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
    ],
)
<commit_msg>Use the pg8000 pure-Python Postgres DBAPI module<commit_after>from setuptools import setup

setup(
    name='tangled.website',
    version='0.1.dev0',
    description='tangledframework.org',
    long_description=open('README.rst').read(),
    url='http://tangledframework.org/',
    download_url='https://github.com/TangledWeb/tangled.website/tags',
    author='Wyatt Baldwin',
    author_email='self@wyattbaldwin.com',
    packages=[
        'tangled',
        'tangled.website',
    ],
    include_package_data=True,
    install_requires=[
        'pg8000>=1.10.6',
        'tangled.auth>=0.1a3',
        'tangled.session>=0.1a2',
        'tangled.site>=0.1a2',
        'SQLAlchemy>=1.1.6',
    ],
    extras_require={
        'dev': ['coverage'],
    },
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
    ],
)
<|endoftext|>