<commit_before>from __future__ import absolute_import, print_function

from datetime import datetime
import logging
import os
import re
import sh
import shlex

import sys

from .exceptions import BranchError, VersionError

'''
    Uses a slightly modified version of this regex
    https://regex101.com/r/E0iVVS/2
'''
SEMVER_RE = re.compile('''
                       ^(?P<VersionTripple>
                            (?P<Major>0|[1-9][0-9]*)\.
                            (?P<Minor>0|[1-9][0-9]*)\.
                            (?P<Patch>0|[1-9][0-9]*)
                        ){1}
                        (?P<Tags>(?:\-
                            (?P<Prerelease>
                                (?:(?=[0]{1}[0-9A-Za-z-]{0})(?:[0]{1})|(?=[1-9]{1}[0-9]*[A-Za-z]{0})(?:[0-9]+)|(?=[0-9]*[A-Za-z-]+[0-9A-Za-z-]*)(?:[0-9A-Za-z-]+)){1}(?:\.(?=[0]{1}[0-9A-Za-z-]{0})(?:[0]{1})|\.(?=[1-9]{1}[0-9]*[A-Za-z]{0})(?:[0-9]+)|\.(?=[0-9]*[A-Za-z-]+[0-9A-Za-z-]*)(?:[0-9A-Za-z-]+))*){1}
                            ){0,1}(?:\+
                            (?P<Build>
                                (?:[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*
                            ))
                        ){0,1})$
                       ''', re.VERBOSE)

INITIAL_VERSION = '0.0.0'

MAJOR = 0
MINOR = 1
PATCH = 2

def print_error(buf):
    print(buf, file=sys.stderr)

class GitVersion(object):
    """
    Get and set git version tag
    """
    def __init__(self, args=None):
        self.args = args

    @property
    def logger(self):
        return logging.getLogger('{}.{}'.format(
            __name__,
            self.__class__.__name__))

    @property
    def branch(self):
        branch = os.environ.get('GIT_BRANCH')
        if branch is None:
            command = sh.git(*shlex.split('rev-parse --abbrev-ref HEAD'))
            lines = command.stdout.decode('utf8').strip().splitlines()
            branch = lines[0].strip()

            color_marker_idx = branch.find('\x1b')
            if color_marker_idx >= 0:
                self.logger.warning('found color marker in branch={}'.format(
                    branch.encode("utf8")))
                branch = branch[:color_marker_idx]

        # clean string to remove unwanted characters
        branch = branch.replace('/', '--')

        return branch

    @property
    def is_clean(self):
        """
        Returns whether the working copy is clean

        When there are uncommited changes in the working copy return False

        Returns:
            Boolean whether the working copy is clean
        """
        result = False

        command_l = 'git status --untracked --short'.split()
        command = getattr(sh, command_l[0])(command_l[1:])

        lines = command.stdout.decode('utf8').splitlines()
        for line in lines:
            line = line.rstrip()
            print_error('{}'.format(line))

        if not lines:
            result = True

        return result

    @property
    def is_calver(self):
        # ex: 201809.25 from 201809.25.1-rc
        d = '.'.join(self.version.split('.', 2)[:2])
        try:
            datetime.strptime(d, self.args.calver_format)
        except AttributeError:
            return False
        except ValueError:
            return False
        else:
            return True

    @property
    def is_semver(self):
        return SEMVER_RE.match(self.version) is not None

    @property
    def version(self):
        try:
            command = sh.git(*shlex.split('describe --tags --always'))
        except sh.ErrorReturnCode_128:
            return None
        else:
            version = command.stdout.decode('utf8').strip()

            # if the branch flag was given,
            # check to see if we are on a tagged commit
            if self.args.branch:
                try:
                    command = sh.git(*shlex.split('describe --tags --exact-match'))
                except sh.ErrorReturnCode_128:
                    # not an exact match, so append the branch
                    version = '{}-{}'.format(version, self.branch)

            return version

    @classmethod
    def setup_subparser(cls, subcommand):
        parser = subcommand.add_parser('version', help=cls.__doc__)

        parser.set_defaults(cls=cls)
        parser.add_argument(
            '--bump', action='store_true',
            help='perform a version bump, by default the current version is displayed'
        )
        parser.add_argument(
            '--patch', action='store_true', default=True,
            help='bump the patch version, this is the default bump if one is not specified'
        )
        parser.add_argument(
            '--minor', action='store_true',
            help='bump the minor version and reset patch back to 0'
        )
        parser.add_argument(
            '--major', action='store_true',
            help='bump the major version and reset minor and patch back to 0'
        )
        parser.add_argument(
            '--set',
            help='set version to the given version'
        )
        parser.add_argument(
            '--semver', action='store_true',
            help='only print out if the current tag is a semantic version, or exit 1'
        )
        parser.add_argument(
            '--calver', action='store_true',
            help='only print out if the current tag is a calendar version, or exit 1'
        )
        parser.add_argument(
            '--calver-format', action='store_true', default='%Y%m.%d',
            help='set the calver format (ex: \'%Y%m.%d\')'
        )
        parser.add_argument(
            '--no-branch', action='store_false', dest='branch',
            help='do not append branch to the version when current commit is not tagged'
        )

    def get_next_version(self, version):
        # split the version and int'ify major, minor, and patch
        split_version = version.split('-', 1)[0].split('.', 3)
        for i in range(3):
            split_version[i] = int(split_version[i])

        if self.args.major:
            split_version[MAJOR] += 1

            split_version[MINOR] = 0
            split_version[PATCH] = 0
        elif self.args.minor:
            split_version[MINOR] += 1

            split_version[PATCH] = 0
        elif self.args.patch:
            split_version[PATCH] += 1

        return split_version[:3]

    def get_next_calver_version(self, version):
        now = datetime.now().strftime(self.args.calver_format)
        # split the current date
        split_calver = now.split('.', 2)
        for i in range(2):
            split_calver[i] = int(split_calver[i])

        # split the version and int'ify major, minor, and patch
        split_version = version.split('-', 1)[0].split('.', 3)
        for i in range(3):
            split_version[i] = int(split_version[i])

        # don't allow major/minor
        if self.args.major:
            raise VersionError('''
                You can not bump to a major calver release.
                If you want to override this use `--set --force` instead
                ''')
        elif self.args.minor:
            raise VersionError('''
                You can not bump to a minor calver release.
                If you want to override this use `--set --force` instead
                ''')
        elif self.args.patch:
            # if we are on the same day bump the patch
            # otherwise move to the new date
            if (split_calver == split_version[:2]):
                split_version[PATCH] += 1
                split_calver.append(split_version[PATCH])
            else:
                split_calver.append(0)

        return split_calver[:3]

    def bump(self):
        current_version = self.version
        if not current_version:
            current_version = INITIAL_VERSION

        if self.args.calver:
            version = self.get_next_calver_version(current_version)
        else:
            split_dashes = version.split('-')

            if len(split_dashes) == 1:
                raise VersionError(
                    'Is version={} already bumped?'.format(version))

            current_version = split_dashes[0]
            version = self.get_next_version(current_version)

        return version

    def check_bump(self):
        """
        Check to see if a bump request is being made
        """
        if not self.args.bump:
            return False

        return self.bump()

    def check_set(self):
        """
        Check to see if the version is being set
        """
        if not self.args.set:
            return None

        return self.args.set.split('.')

    def run(self):
        if not self.is_clean:
            print_error('Abort: working copy not clean.')

            return 1

        current_version = self.version

        if self.args.semver:
            if not self.is_semver:
                return 1

        if self.args.calver:
            if not self.is_calver:
                return 1

        # check to see if an explicit version is being set
        new_version = self.check_set()
        if not new_version:
            # otherwise, see if the version is being bumped
            try:
                new_version = self.check_bump()
            except VersionError as exc:
                print_error(exc)

                return 1

        status = 0

        if new_version is False:
            if current_version:
                print(self.version)
            else:
                next_version = self.get_next_version(INITIAL_VERSION)
                print_error('No version found, use --bump to set to {}'.format(
                    self.stringify(next_version)
                ))

                status = 1
        else:
            version_str = self.stringify(new_version)
            os.system(' '.join(['git', 'tag', '-a', version_str]))

            print(version_str)

        return status

    def stringify(self, version):
        return '.'.join([str(x) for x in version])
<commit_msg>moved is_calver to a function since we call it with different variables<commit_after>from __future__ import absolute_import, print_function

from datetime import datetime
import logging
import os
import re
import sh
import shlex

import sys

from .exceptions import BranchError, VersionError

'''
    Uses a slightly modified version of this regex
    https://regex101.com/r/E0iVVS/2
'''
SEMVER_RE = re.compile('''
                       ^(?P<VersionTripple>
                            (?P<Major>0|[1-9][0-9]*)\.
                            (?P<Minor>0|[1-9][0-9]*)\.
                            (?P<Patch>0|[1-9][0-9]*)
                        ){1}
                        (?P<Tags>(?:\-
                            (?P<Prerelease>
                                (?:(?=[0]{1}[0-9A-Za-z-]{0})(?:[0]{1})|(?=[1-9]{1}[0-9]*[A-Za-z]{0})(?:[0-9]+)|(?=[0-9]*[A-Za-z-]+[0-9A-Za-z-]*)(?:[0-9A-Za-z-]+)){1}(?:\.(?=[0]{1}[0-9A-Za-z-]{0})(?:[0]{1})|\.(?=[1-9]{1}[0-9]*[A-Za-z]{0})(?:[0-9]+)|\.(?=[0-9]*[A-Za-z-]+[0-9A-Za-z-]*)(?:[0-9A-Za-z-]+))*){1}
                            ){0,1}(?:\+
                            (?P<Build>
                                (?:[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*
                            ))
                        ){0,1})$
                       ''', re.VERBOSE)

INITIAL_VERSION = '0.0.0'

MAJOR = 0
MINOR = 1
PATCH = 2

def print_error(buf):
    print(buf, file=sys.stderr)

def is_calver(calver_version, calver_format):
    # ex: 201809.25 from 201809.25.1-rc
    d = '.'.join(calver_version.split('.', 2)[:2])
    try:
        datetime.strptime(d, calver_format)
    except AttributeError:
        return False
    except ValueError:
        return False
    else:
        return True

def is_semver(semver_version):
    return SEMVER_RE.match(semver_version) is not None

class GitVersion(object):
    """
    Get and set git version tag
    """
    def __init__(self, args=None):
        self.args = args

    @property
    def logger(self):
        return logging.getLogger('{}.{}'.format(
            __name__,
            self.__class__.__name__))

    @property
    def branch(self):
        branch = os.environ.get('GIT_BRANCH')
        if branch is None:
            command = sh.git(*shlex.split('rev-parse --abbrev-ref HEAD'))
            lines = command.stdout.decode('utf8').strip().splitlines()
            branch = lines[0].strip()

            color_marker_idx = branch.find('\x1b')
            if color_marker_idx >= 0:
                self.logger.warning('found color marker in branch={}'.format(
                    branch.encode("utf8")))
                branch = branch[:color_marker_idx]

        # clean string to remove unwanted characters
        branch = branch.replace('/', '--')

        return branch

    @property
    def is_clean(self):
        """
        Returns whether the working copy is clean

        When there are uncommited changes in the working copy return False

        Returns:
            Boolean whether the working copy is clean
        """
        result = False

        command_l = 'git status --untracked --short'.split()
        command = getattr(sh, command_l[0])(command_l[1:])

        lines = command.stdout.decode('utf8').splitlines()
        for line in lines:
            line = line.rstrip()
            print_error('{}'.format(line))

        if not lines:
            result = True

        return result

    @property
    def is_calver(self):
        return(is_calver(self.version, self.args.calver_format))

    @property
    def is_semver(self):
        return(is_semver(self.version))

    @property
    def version(self):
        try:
            command = sh.git(*shlex.split('describe --tags --always'))
        except sh.ErrorReturnCode_128:
            return None
        else:
            version = command.stdout.decode('utf8').strip()

            # if the branch flag was given,
            # check to see if we are on a tagged commit
            if self.args.branch:
                try:
                    command = sh.git(*shlex.split('describe --tags --exact-match'))
                except sh.ErrorReturnCode_128:
                    # not an exact match, so append the branch
                    version = '{}-{}'.format(version, self.branch)

            return version

    @classmethod
    def setup_subparser(cls, subcommand):
        parser = subcommand.add_parser('version', help=cls.__doc__)

        parser.set_defaults(cls=cls)
        parser.add_argument(
            '--bump', action='store_true',
            help='perform a version bump, by default the current version is displayed'
        )
        parser.add_argument(
            '--patch', action='store_true', default=True,
            help='bump the patch version, this is the default bump if one is not specified'
        )
        parser.add_argument(
            '--minor', action='store_true',
            help='bump the minor version and reset patch back to 0'
        )
        parser.add_argument(
            '--major', action='store_true',
            help='bump the major version and reset minor and patch back to 0'
        )
        parser.add_argument(
            '--set',
            help='set version to the given version'
        )
        parser.add_argument(
            '--semver', action='store_true',
            help='only print out if the current tag is a semantic version, or exit 1'
        )
        parser.add_argument(
            '--calver', action='store_true',
            help='only print out if the current tag is a calendar version, or exit 1'
        )
        parser.add_argument(
            '--calver-format', action='store_true', default='%Y%m.%d',
            help='set the calver format (ex: \'%Y%m.%d\')'
        )
        parser.add_argument(
            '--no-branch', action='store_false', dest='branch',
            help='do not append branch to the version when current commit is not tagged'
        )

    def get_next_version(self, version):
        # split the version and int'ify major, minor, and patch
        split_version = version.split('-', 1)[0].split('.', 3)
        for i in range(3):
            split_version[i] = int(split_version[i])

        if self.args.major:
            split_version[MAJOR] += 1
            split_version[MINOR] = 0
            split_version[PATCH] = 0
        elif self.args.minor:
            split_version[MINOR] += 1
            split_version[PATCH] = 0
        elif self.args.patch:
            split_version[PATCH] += 1

        return split_version[:3]

    def get_next_calver_version(self, version):
        # split the current date
        now = datetime.now().strftime(self.args.calver_format)
        split_calver = now.split('.', 2)
        for i in range(2):
            split_calver[i] = int(split_calver[i])

        # split the version and int'ify major, minor, and patch
        split_version = version.split('-', 1)[0].split('.', 3)
        for i in range(3):
            split_version[i] = int(split_version[i])

        # don't allow major/minor
        if self.args.major:
            raise VersionError('''
                You can not bump to a major calver release.
                If you want to override this use `--set --force` instead
                ''')
        elif self.args.minor:
            raise VersionError('''
                You can not bump to a minor calver release.
                If you want to override this use `--set --force` instead
                ''')
        elif self.args.patch:
            # if we are on the same day bump the patch
            # otherwise move to the new date
            if (split_calver == split_version[:2]):
                split_version[PATCH] += 1
                split_calver.append(split_version[PATCH])
            else:
                split_calver.append(0)

        return split_calver[:3]

    def bump(self):
        current_version = self.version
        if not current_version:
            current_version = INITIAL_VERSION

        if self.args.calver:
            version = self.get_next_calver_version(current_version)
        else:
            split_dashes = version.split('-')

            if len(split_dashes) == 1:
                raise VersionError(
                    'Is version={} already bumped?'.format(version))

            current_version = split_dashes[0]
            version = self.get_next_version(current_version)

        return version

    def check_bump(self):
        """
        Check to see if a bump request is being made
        """
        if not self.args.bump:
            return False

        return self.bump()

    def check_set(self):
        """
        Check to see if the version is being set
        """
        if not self.args.set:
            return None

        # if there's a calver flag, can only set to a correct calver version
        if self.args.calver:
            if not is_calver(self.args.set, self.args.calver_format):
                raise VersionError(
                    'Trying to set a non-calver version: {}'.format(self.args.set))

        version = self.args.set.split('.')
        return self.args.set.split('.')

    def run(self):
        if not self.is_clean:
            print_error('Abort: working copy not clean.')

            return 1

        current_version = self.version

        if self.args.semver:
            if not self.is_semver:
                return 1

        if self.args.calver:
            if not self.is_calver:
                return 1

        # check to see if an explicit version is being set
        new_version = self.check_set()
        if not new_version:
            # otherwise, see if the version is being bumped
            try:
                new_version = self.check_bump()
            except VersionError as exc:
                print_error(exc)

                return 1

        status = 0

        if new_version is False:
            if current_version:
                print(self.version)
            else:
                next_version = self.get_next_version(INITIAL_VERSION)
                print_error('No version found, use --bump to set to {}'.format(
                    self.stringify(next_version)
                ))

                status = 1
        else:
            version_str = self.stringify(new_version)
            os.system(' '.join(['git', 'tag', '-a', version_str]))

            print(version_str)

        return status

    def stringify(self, version):
        return '.'.join([str(x) for x in version])
<|endoftext|>


<commit_before>"""
PostgreSQL database backend for Django.

Requires psycopg 1: http://initd.org/projects/psycopg1
"""

import sys

from django.db import utils
from django.db.backends import *
from django.db.backends.signals import connection_created
from django.db.backends.postgresql.client import DatabaseClient
from django.db.backends.postgresql.creation import DatabaseCreation
from django.db.backends.postgresql.introspection import DatabaseIntrospection
from django.db.backends.postgresql.operations import DatabaseOperations
from django.db.backends.postgresql.version import get_version
from django.utils.encoding import smart_str, smart_unicode

try:
    import psycopg as Database
except ImportError, e:
    from django.core.exceptions import ImproperlyConfigured
    raise ImproperlyConfigured("Error loading psycopg module: %s" % e)

DatabaseError = Database.DatabaseError
IntegrityError = Database.IntegrityError

class UnicodeCursorWrapper(object):
    """
    A thin wrapper around psycopg cursors that allows them to accept Unicode
    strings as params.

    This is necessary because psycopg doesn't apply any DB quoting to
    parameters that are Unicode strings. If a param is Unicode, this will
    convert it to a bytestring using database client's encoding before passing
    it to psycopg.

    All results retrieved from the database are converted into Unicode strings
    before being returned to the caller.
    """
    def __init__(self, cursor, charset):
        self.cursor = cursor
        self.charset = charset

    def format_params(self, params):
        if isinstance(params, dict):
            result = {}
            charset = self.charset
            for key, value in params.items():
                result[smart_str(key, charset)] = smart_str(value, charset)
            return result
        else:
            return tuple([smart_str(p, self.charset, True) for p in params])

    def execute(self, sql, params=()):
        try:
            return self.cursor.execute(smart_str(sql, self.charset), self.format_params(params))
        except Database.IntegrityError, e:
            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
        except Database.DatabaseError, e:
            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]

    def executemany(self, sql, param_list):
        try:
            new_param_list = [self.format_params(params) for params in param_list]
            return self.cursor.executemany(sql, new_param_list)
        except Database.IntegrityError, e:
            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
        except Database.DatabaseError, e:
            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]

    def __getattr__(self, attr):
        if attr in self.__dict__:
            return self.__dict__[attr]
        else:
            return getattr(self.cursor, attr)

    def __iter__(self):
        return iter(self.cursor)

class DatabaseFeatures(BaseDatabaseFeatures):
    uses_savepoints = True

class DatabaseWrapper(BaseDatabaseWrapper):
    operators = {
        'exact': '= %s',
        'iexact': '= UPPER(%s)',
        'contains': 'LIKE %s',
        'icontains': 'LIKE UPPER(%s)',
        'regex': '~ %s',
        'iregex': '~* %s',
        'gt': '> %s',
        'gte': '>= %s',
        'lt': '< %s',
        'lte': '<= %s',
        'startswith': 'LIKE %s',
        'endswith': 'LIKE %s',
        'istartswith': 'LIKE UPPER(%s)',
        'iendswith': 'LIKE UPPER(%s)',
    }

    def __init__(self, *args, **kwargs):
        super(DatabaseWrapper, self).__init__(*args, **kwargs)

        import warnings
        warnings.warn(
            'The "postgresql" backend has been deprecated. Use "postgresql_psycopg2" instead.',
            PendingDeprecationWarning
        )

        self.features = DatabaseFeatures()
        self.ops = DatabaseOperations(self)
        self.client = DatabaseClient(self)
        self.creation = DatabaseCreation(self)
        self.introspection = DatabaseIntrospection(self)
        self.validation = BaseDatabaseValidation(self)

    def _cursor(self):
        new_connection = False
        set_tz = False
        settings_dict = self.settings_dict
        if self.connection is None:
            new_connection = True
            set_tz = settings_dict.get('TIME_ZONE')
            if settings_dict['NAME'] == '':
                from django.core.exceptions import ImproperlyConfigured
                raise ImproperlyConfigured("You need to specify NAME in your Django settings file.")
            conn_string = "dbname=%s" % settings_dict['NAME']
            if settings_dict['USER']:
                conn_string = "user=%s %s" % (settings_dict['USER'], conn_string)
            if settings_dict['PASSWORD']:
                conn_string += " password='%s'" % settings_dict['PASSWORD']
            if settings_dict['HOST']:
                conn_string += " host=%s" % settings_dict['HOST']
            if settings_dict['PORT']:
                conn_string += " port=%s" % settings_dict['PORT']
            self.connection = Database.connect(conn_string, **settings_dict['OPTIONS'])
            self.connection.set_isolation_level(1) # make transactions transparent to all cursors
            connection_created.send(sender=self.__class__)
        cursor = self.connection.cursor()
        if new_connection:
            if set_tz:
                cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
            if not hasattr(self, '_version'):
                self.__class__._version = get_version(cursor)
            if self._version[0:2] < (8, 0):
                # No savepoint support for earlier version of PostgreSQL.
                self.features.uses_savepoints = False
        cursor.execute("SET client_encoding to 'UNICODE'")
        cursor = UnicodeCursorWrapper(cursor, 'utf-8')
        return cursor

def typecast_string(s):
    """
    Cast all returned strings to unicode strings.
    """
    if not s and not isinstance(s, str):
        return s
    return smart_unicode(s)

# Register these custom typecasts, because Django expects dates/times to be
# in Python's native (standard-library) datetime/time format, whereas psycopg
# use mx.DateTime by default.
try:
    Database.register_type(Database.new_type((1082,), "DATE", util.typecast_date))
except AttributeError:
    raise Exception("You appear to be using psycopg version 2. Set your DATABASES.ENGINE to 'postgresql_psycopg2' instead of 'postgresql'.")
Database.register_type(Database.new_type((1083,1266), "TIME", util.typecast_time))
Database.register_type(Database.new_type((1114,1184), "TIMESTAMP", util.typecast_timestamp))
Database.register_type(Database.new_type((16,), "BOOLEAN", util.typecast_boolean))
Database.register_type(Database.new_type((1700,), "NUMERIC", util.typecast_decimal))
Database.register_type(Database.new_type(Database.types[1043].values, 'STRING', typecast_string))
<commit_msg>Fixed #12759 -- Fixed the iterator method on psycopg1 cursors, which was preventing the raw_query tests from passing.<commit_after>"""
PostgreSQL database backend for Django.

Requires psycopg 1: http://initd.org/projects/psycopg1
"""

import sys

from django.db import utils
from django.db.backends import *
from django.db.backends.signals import connection_created
from django.db.backends.postgresql.client import DatabaseClient
from django.db.backends.postgresql.creation import DatabaseCreation
from django.db.backends.postgresql.introspection import DatabaseIntrospection
from django.db.backends.postgresql.operations import DatabaseOperations
from django.db.backends.postgresql.version import get_version
from django.utils.encoding import smart_str, smart_unicode

try:
    import psycopg as Database
except ImportError, e:
    from django.core.exceptions import ImproperlyConfigured
    raise ImproperlyConfigured("Error loading psycopg module: %s" % e)

DatabaseError = Database.DatabaseError
IntegrityError = Database.IntegrityError

class UnicodeCursorWrapper(object):
    """
    A thin wrapper around psycopg cursors that allows them to accept Unicode
    strings as params.

    This is necessary because psycopg doesn't apply any DB quoting to
    parameters that are Unicode strings. If a param is Unicode, this will
    convert it to a bytestring using database client's encoding before passing
    it to psycopg.

    All results retrieved from the database are converted into Unicode strings
    before being returned to the caller.
    """
    def __init__(self, cursor, charset):
        self.cursor = cursor
        self.charset = charset

    def format_params(self, params):
        if isinstance(params, dict):
            result = {}
            charset = self.charset
            for key, value in params.items():
                result[smart_str(key, charset)] = smart_str(value, charset)
            return result
        else:
            return tuple([smart_str(p, self.charset, True) for p in params])

    def execute(self, sql, params=()):
        try:
            return self.cursor.execute(smart_str(sql, self.charset), self.format_params(params))
        except Database.IntegrityError, e:
            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
        except Database.DatabaseError, e:
            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]

    def executemany(self, sql, param_list):
        try:
            new_param_list = [self.format_params(params) for params in param_list]
            return self.cursor.executemany(sql, new_param_list)
        except Database.IntegrityError, e:
            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
        except Database.DatabaseError, e:
            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]

    def __getattr__(self, attr):
        if attr in self.__dict__:
            return self.__dict__[attr]
        else:
            return getattr(self.cursor, attr)

    def __iter__(self):
        return iter(self.cursor.fetchall())

class DatabaseFeatures(BaseDatabaseFeatures):
    uses_savepoints = True

class DatabaseWrapper(BaseDatabaseWrapper):
    operators = {
        'exact': '= %s',
        'iexact': '= UPPER(%s)',
        'contains': 'LIKE %s',
        'icontains': 'LIKE UPPER(%s)',
        'regex': '~ %s',
        'iregex': '~* %s',
        'gt': '> %s',
        'gte': '>= %s',
        'lt': '< %s',
        'lte': '<= %s',
        'startswith': 'LIKE %s',
        'endswith': 'LIKE %s',
        'istartswith': 'LIKE UPPER(%s)',
        'iendswith': 'LIKE UPPER(%s)',
    }

    def __init__(self, *args, **kwargs):
        super(DatabaseWrapper, self).__init__(*args, **kwargs)

        import warnings
        warnings.warn(
            'The "postgresql" backend has been deprecated. Use "postgresql_psycopg2" instead.',
            PendingDeprecationWarning
        )

        self.features = DatabaseFeatures()
        self.ops = DatabaseOperations(self)
        self.client = DatabaseClient(self)
        self.creation = DatabaseCreation(self)
        self.introspection = DatabaseIntrospection(self)
        self.validation = BaseDatabaseValidation(self)

    def _cursor(self):
        new_connection = False
        set_tz = False
        settings_dict = self.settings_dict
        if self.connection is None:
            new_connection = True
            set_tz = settings_dict.get('TIME_ZONE')
            if settings_dict['NAME'] == '':
                from django.core.exceptions import ImproperlyConfigured
                raise ImproperlyConfigured("You need to specify NAME in your Django settings file.")
            conn_string = "dbname=%s" % settings_dict['NAME']
            if settings_dict['USER']:
                conn_string = "user=%s %s" % (settings_dict['USER'], conn_string)
            if settings_dict['PASSWORD']:
                conn_string += " password='%s'" % settings_dict['PASSWORD']
            if settings_dict['HOST']:
                conn_string += " host=%s" % settings_dict['HOST']
            if settings_dict['PORT']:
                conn_string += " port=%s" % settings_dict['PORT']
            self.connection = Database.connect(conn_string, **settings_dict['OPTIONS'])
            self.connection.set_isolation_level(1) # make transactions transparent to all cursors
            connection_created.send(sender=self.__class__)
        cursor = self.connection.cursor()
        if new_connection:
            if set_tz:
                cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
            if not hasattr(self, '_version'):
                self.__class__._version = get_version(cursor)
            if self._version[0:2] < (8, 0):
                # No savepoint support for earlier version of PostgreSQL.
                self.features.uses_savepoints = False
        cursor.execute("SET client_encoding to 'UNICODE'")
        cursor = UnicodeCursorWrapper(cursor, 'utf-8')
        return cursor

def typecast_string(s):
    """
    Cast all returned strings to unicode strings.
    """
    if not s and not isinstance(s, str):
        return s
    return smart_unicode(s)

# Register these custom typecasts, because Django expects dates/times to be
# in Python's native (standard-library) datetime/time format, whereas psycopg
# use mx.DateTime by default.
try:
    Database.register_type(Database.new_type((1082,), "DATE", util.typecast_date))
except AttributeError:
    raise Exception("You appear to be using psycopg version 2. Set your DATABASES.ENGINE to 'postgresql_psycopg2' instead of 'postgresql'.")
Database.register_type(Database.new_type((1083,1266), "TIME", util.typecast_time))
Database.register_type(Database.new_type((1114,1184), "TIMESTAMP", util.typecast_timestamp))
Database.register_type(Database.new_type((16,), "BOOLEAN", util.typecast_boolean))
Database.register_type(Database.new_type((1700,), "NUMERIC", util.typecast_decimal))
Database.register_type(Database.new_type(Database.types[1043].values, 'STRING', typecast_string))
<|endoftext|>


<commit_before>#!/usr/bin/env python3
"""Check a font family using Google Fonts QA tools.

Examples:
Check a local family against the same family hosted on Google Fonts:
`gftools qa -f [fonts.ttf] -gfb -a -o qa`

Check a local family against another local family and generate reports
for Font Diffenator only:
`gftools qa -f [fonts_a.ttf] -fb [fonts_b.ttf] --diffenator -o qa`

Check a local family against the same family hosted on Google Fonts and
generate reports for Diffbrowsers only:
`gftools qa -f [fonts.ttf] -gf --diffbrowsers -o qa

Compare a pull request against the same family hosted on Google Fonts:
`gftools qa -pr www.github.com/user/repo/pull/1 -gfb -a -o qa`

Compare a github folder of fonts against the same family hosted on Google
Fonts:
`gftools qa -gh www.github.com/user/repo/tree/fonts/ttf -gfb -a -o qa`
"""
from fontTools.ttLib import TTFont
import argparse
import os
import shutil
import logging
from gftools.utils import (
    download_family_from_Google_Fonts,
    download_files_in_github_pr,
    download_files_in_github_dir,
    download_files_from_archive,
    Google_Fonts_has_family,
    mkdir,
)
from gftools.qa import FontQA

__version__ = "2.2.0"
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

def family_name_from_fonts(fonts):
    results = []
    for font in fonts:
        family_name = font["name"].getName(1, 3, 1, 1033)
        typo_family_name = font["name"].getName(16, 3, 1, 1033)

        if typo_family_name:
            results.append(typo_family_name.toUnicode())
        elif family_name:
            results.append(family_name.toUnicode())
        else:
            raise Exception(
                "Font: {} has no family name records".format(
                    os.path.basename(font.reader.file.name)
                )
            )
    if len(set(results)) > 1:
        raise Exception("Multiple family names found: [{}]".format(", ".join(results)))
    return results[0]

def main():
    parser = argparse.ArgumentParser(
        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
    )

    font_group = parser.add_argument_group(title="Fonts to qa")
    font_input_group = font_group.add_mutually_exclusive_group(required=True)
    font_input_group.add_argument("-f", "--fonts", nargs="+",
        help="Paths to fonts")
    font_input_group.add_argument("-pr", "--pull-request",
        help="Get fonts from a Github pull request")
    font_input_group.add_argument("-gh", "--github-dir",
        help="Get fonts from a Github directory")
    font_input_group.add_argument("-gf", "--googlefonts",
        help="Get fonts from Google Fonts")
    font_before_input_group.add_argument("-ar", "--archive",
        help="Get fonts from a zip file URL")

    font_before_group = parser.add_argument_group(title="Fonts before input")
    font_before_input_group = font_before_group.add_mutually_exclusive_group(
        required=False
    )
    font_before_input_group.add_argument(
        "-fb", "--fonts-before", nargs="+",
        help="Paths to previous fonts"
    )
    font_before_input_group.add_argument("-prb", "--pull-request-before",
        help="Get previous fonts from a Github pull request")
    font_before_input_group.add_argument("-ghb", "--github-dir-before",
        help="Get previous fonts from a Github dir")
    font_before_input_group.add_argument("-arb", "--archive-before",
        help="Get previous fonts from a zip file URL")
    font_before_input_group.add_argument(
        "-gfb",
        "--googlefonts-before",
        action="store_true",
        help="Get previous fonts from Google Fonts",
    )

    check_group = parser.add_argument_group(title="QA checks")
    check_group.add_argument(
        "-a",
        "--auto-qa",
        action="store_true",
        help="Check fonts against against the same fonts hosted on Google Fonts",
    )
    check_group.add_argument(
        "--diffenator", action="store_true", help="Run Fontdiffenator"
    )
    check_group.add_argument(
        "--diffbrowsers", action="store_true", help="Run Diffbrowsers"
    )
    check_group.add_argument(
        "--fontbakery", action="store_true", help="Run FontBakery"
    )
    check_group.add_argument(
        "--plot-glyphs",
        action="store_true",
        help="Gen images of full charset, useful for new familes",
    )
    check_group.add_argument(
        "--browser-previews",
        action="store_true",
        help="Gen images on diff browsers, useful for new families",
    )
    check_group.add_argument(
        "-dm", "--diff-mode", choices=("weak", "normal", "strict"), default="normal"
    )
    parser.add_argument("-re", "--filter-fonts", help="Filter fonts by regex")
    parser.add_argument(
        "-o", "--out", default="out", help="Output path for check results"
    )
    parser.add_argument(
        "-ogh",
        "--out-github",
        action="store_true",
        help=(
            "Post report data to either the pull request as a comment "
            "open a new issue. This can only be used if fonts have been "
            "fetched from either a pull request or github dir."
        ),
    )
    parser.add_argument(
        "--out-url",
        help=(
            "Post report data to a github pr. This can be used with any font "
            "fetching method."
        )
    )
    parser.add_argument("--version", action="version", version=__version__)
    args = parser.parse_args()
    if args.out_github and not any([args.pull_request, args.github_dir]):
        raise Exception(
            "Cannot upload results to a github issue or pr. "
            "Font input must either a github dir or a pull request"
        )
    if not any([args.auto_qa,
                args.fontbakery,
                args.plot_glyphs,
                args.diffbrowsers,
                args.diffenator,
                args.browser_previews]):
        raise Exception("Terminating. No checks selected. Run gftools qa "
                        "--help to see all possible commands.")

    # Retrieve fonts and store in out dir
    mkdir(args.out)
    fonts_dir = os.path.join(args.out, "fonts")
    mkdir(fonts_dir)
    if args.fonts:
        [shutil.copy(f, fonts_dir) for f in args.fonts]
        fonts = args.fonts
    elif args.pull_request:
        fonts = download_files_in_github_pr(
            args.pull_request,
            fonts_dir,
            ignore_static_dir=False,
        )
        if not fonts:
            logger.info("No fonts found in pull request. Skipping")
            return
    elif args.github_dir:
        fonts = download_files_in_github_dir(args.github_dir, fonts_dir)
        if not fonts:
            logger.info("No fonts found in github dir. Skipping")
            return
    elif args.archive:
        fonts = download_files_from_archive(args.archive, fonts_dir)
    elif args.googlefonts:
        fonts = download_family_from_Google_Fonts(args.googlefonts, fonts_dir)

    if args.filter_fonts:
        re_filter = re.compile(args.filter_fonts)
        fonts = [f for f in fonts if re_filter.search(f)]

    ttfonts = [TTFont(f) for f in fonts if f.endswith((".ttf", ".otf"))
               and "static" not in f]
    family_name = family_name_from_fonts(ttfonts)
    family_on_gf = Google_Fonts_has_family(family_name)

    # Retrieve fonts_before and store in out dir
    fonts_before = None
    if any([args.fonts_before, args.pull_request_before, args.github_dir_before, args.archive_before]) or \
           (args.googlefonts_before and family_on_gf):
        fonts_before_dir = os.path.join(args.out, "fonts_before")
        mkdir(fonts_before_dir, overwrite=False)
    if args.fonts_before:
        [shutil.copy(f, fonts_before_dir) for f in args.fonts_before]
        fonts_before = args.fonts_before
    elif args.pull_request_before:
        fonts_before = download_files_in_github_pr(
            args.pull_request_before,
            fonts_before_dir,
            ignore_static_dir=False
        )
    elif args.github_dir_before:
        fonts_before = download_files_in_github_dir(
            args.github_dir_before, fonts_before_dir
        )
    elif args.archive_before:
        fonts_before = download_files_from_archive(
            args.archive_before, fonts_before_dir
        )
    elif args.googlefonts_before and family_on_gf:
        fonts_before = download_family_from_Google_Fonts(
            family_name, fonts_before_dir
        )

    if fonts_before:
        ttfonts_before = [TTFont(f) for f in fonts_before if f.endswith((".ttf", ".otf"))
                          and "static" not in f]
        qa = FontQA(ttfonts, ttfonts_before, args.out)
    else:
        qa = FontQA(ttfonts, out=args.out)

    if args.auto_qa and family_on_gf:
        qa.googlefonts_upgrade()
    elif args.auto_qa and not family_on_gf:
        qa.googlefonts_new()
    if args.plot_glyphs:
        qa.plot_glyphs()
    if args.browser_previews:
        qa.browser_previews()
    if args.fontbakery:
        qa.fontbakery()
    if args.diffenator:
        qa.diffenator()
    if args.diffbrowsers:
        qa.diffbrowsers()

    if args.out_url:
        qa.post_to_github(args.out_url)
    elif args.out_github and args.pull_request:
        qa.post_to_github(args.pull_request)
    elif args.out_github and args.github_dir:
        qa.post_to_github(args.github_dir)

if __name__ == "__main__":
    main()
<commit_msg>fix typo<commit_after>#!/usr/bin/env python3
"""Check a font family using Google Fonts QA tools.

Examples:
Check a local family against the same family hosted on Google Fonts:
`gftools qa -f [fonts.ttf] -gfb -a -o qa`

Check a local family against another local family and generate reports
for Font Diffenator only:
`gftools qa -f [fonts_a.ttf] -fb [fonts_b.ttf] --diffenator -o qa`

Check a local family against the same family hosted on Google Fonts and
generate reports for Diffbrowsers only:
`gftools qa -f [fonts.ttf] -gf --diffbrowsers -o qa

Compare a pull request against the same family hosted on Google Fonts:
`gftools qa -pr www.github.com/user/repo/pull/1 -gfb -a -o qa`

Compare a github folder of fonts against the same family hosted on Google
Fonts:
`gftools qa -gh www.github.com/user/repo/tree/fonts/ttf -gfb -a -o qa`
"""
from fontTools.ttLib import TTFont
import argparse
import os
import shutil
import logging
from gftools.utils import (
    download_family_from_Google_Fonts,
    download_files_in_github_pr,
    download_files_in_github_dir,
    download_files_from_archive,
    Google_Fonts_has_family,
    mkdir,
)
from gftools.qa import FontQA

__version__ = "2.2.0"
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

def family_name_from_fonts(fonts):
    results = []
    for font in fonts:
        family_name = font["name"].getName(1, 3, 1, 1033)
        typo_family_name = font["name"].getName(16, 3, 1, 1033)

        if typo_family_name:
            results.append(typo_family_name.toUnicode())
        elif family_name:
            results.append(family_name.toUnicode())
        else:
            raise Exception(
                "Font: {} has no family name records".format(
                    os.path.basename(font.reader.file.name)
                )
            )
    if len(set(results)) > 1:
        raise Exception("Multiple family names found: [{}]".format(", ".join(results)))
    return results[0]

def main():
    parser = argparse.ArgumentParser(
        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
    )

    font_group = parser.add_argument_group(title="Fonts to qa")
    font_input_group = font_group.add_mutually_exclusive_group(required=True)
    font_input_group.add_argument("-f", "--fonts", nargs="+",
        help="Paths to fonts")
    font_input_group.add_argument("-pr", "--pull-request",
        help="Get fonts from a Github pull request")
    font_input_group.add_argument("-gh", "--github-dir",
        help="Get fonts from a Github directory")
    font_input_group.add_argument("-gf", "--googlefonts",
        help="Get fonts from Google Fonts")
    font_input_group.add_argument("-ar", "--archive",
        help="Get fonts from a zip file URL")

    font_before_group = parser.add_argument_group(title="Fonts before input")
    font_before_input_group = font_before_group.add_mutually_exclusive_group(
        required=False
    )
    font_before_input_group.add_argument(
        "-fb", "--fonts-before", nargs="+",
        help="Paths to previous fonts"
    )
    font_before_input_group.add_argument("-prb", "--pull-request-before",
        help="Get previous fonts from a Github pull request")
    font_before_input_group.add_argument("-ghb", "--github-dir-before",
        help="Get previous fonts from a Github dir")
    font_before_input_group.add_argument("-arb", "--archive-before",
        help="Get previous fonts from a zip file URL")
    font_before_input_group.add_argument(
        "-gfb",
        "--googlefonts-before",
        action="store_true",
        help="Get previous fonts from Google Fonts",
    )

    check_group = parser.add_argument_group(title="QA checks")
    check_group.add_argument(
        "-a",
        "--auto-qa",
        action="store_true",
        help="Check fonts against against the same fonts hosted on Google Fonts",
    )
    check_group.add_argument(
        "--diffenator", action="store_true", help="Run Fontdiffenator"
    )
    check_group.add_argument(
        "--diffbrowsers", action="store_true", help="Run Diffbrowsers"
    )
    check_group.add_argument(
        "--fontbakery", action="store_true", help="Run FontBakery"
    )
    check_group.add_argument(
        "--plot-glyphs",
        action="store_true",
        help="Gen images of full charset, useful for new familes",
    )
    check_group.add_argument(
        "--browser-previews",
        action="store_true",
        help="Gen images on diff browsers, useful for new families",
    )
    check_group.add_argument(
        "-dm", "--diff-mode", choices=("weak", "normal", "strict"), default="normal"
    )
    parser.add_argument("-re", "--filter-fonts", help="Filter fonts by regex")
    parser.add_argument(
        "-o", "--out", default="out", help="Output path for check results"
    )
    parser.add_argument(
        "-ogh",
        "--out-github",
        action="store_true",
        help=(
            "Post report data to either the pull request as a comment "
            "open a new issue. This can only be used if fonts have been "
            "fetched from either a pull request or github dir."
        ),
    )
    parser.add_argument(
        "--out-url",
        help=(
            "Post report data to a github pr. This can be used with any font "
            "fetching method."
        )
    )
    parser.add_argument("--version", action="version", version=__version__)
    args = parser.parse_args()
    if args.out_github and not any([args.pull_request, args.github_dir]):
        raise Exception(
            "Cannot upload results to a github issue or pr. "
            "Font input must either a github dir or a pull request"
        )
    if not any([args.auto_qa,
                args.fontbakery,
                args.plot_glyphs,
                args.diffbrowsers,
                args.diffenator,
                args.browser_previews]):
        raise Exception("Terminating. No checks selected. Run gftools qa "
                        "--help to see all possible commands.")

    # Retrieve fonts and store in out dir
    mkdir(args.out)
    fonts_dir = os.path.join(args.out, "fonts")
    mkdir(fonts_dir)
    if args.fonts:
        [shutil.copy(f, fonts_dir) for f in args.fonts]
        fonts = args.fonts
    elif args.pull_request:
        fonts = download_files_in_github_pr(
            args.pull_request,
            fonts_dir,
            ignore_static_dir=False,
        )
        if not fonts:
            logger.info("No fonts found in pull request. Skipping")
            return
    elif args.github_dir:
        fonts = download_files_in_github_dir(args.github_dir, fonts_dir)
        if not fonts:
            logger.info("No fonts found in github dir. Skipping")
            return
    elif args.archive:
        fonts = download_files_from_archive(args.archive, fonts_dir)
    elif args.googlefonts:
        fonts = download_family_from_Google_Fonts(args.googlefonts, fonts_dir)

    if args.filter_fonts:
        re_filter = re.compile(args.filter_fonts)
        fonts = [f for f in fonts if re_filter.search(f)]

    ttfonts = [TTFont(f) for f in fonts if f.endswith((".ttf", ".otf"))
               and "static" not in f]
    family_name = family_name_from_fonts(ttfonts)
    family_on_gf = Google_Fonts_has_family(family_name)

    # Retrieve fonts_before and store in out dir
    fonts_before = None
    if any([args.fonts_before, args.pull_request_before, args.github_dir_before, args.archive_before]) or \
           (args.googlefonts_before and family_on_gf):
        fonts_before_dir = os.path.join(args.out, "fonts_before")
        mkdir(fonts_before_dir, overwrite=False)
    if args.fonts_before:
        [shutil.copy(f, fonts_before_dir) for f in args.fonts_before]
        fonts_before = args.fonts_before
    elif args.pull_request_before:
        fonts_before = download_files_in_github_pr(
            args.pull_request_before,
            fonts_before_dir,
            ignore_static_dir=False
        )
    elif args.github_dir_before:
        fonts_before = download_files_in_github_dir(
            args.github_dir_before, fonts_before_dir
        )
    elif args.archive_before:
        fonts_before = download_files_from_archive(
            args.archive_before, fonts_before_dir
        )
    elif args.googlefonts_before and family_on_gf:
        fonts_before = download_family_from_Google_Fonts(
            family_name, fonts_before_dir
        )

    if fonts_before:
        ttfonts_before = [TTFont(f) for f in fonts_before if f.endswith((".ttf", ".otf"))
                          and "static" not in f]
        qa = FontQA(ttfonts, ttfonts_before, args.out)
    else:
        qa = FontQA(ttfonts, out=args.out)

    if args.auto_qa and family_on_gf:
        qa.googlefonts_upgrade()
    elif args.auto_qa and not family_on_gf:
        qa.googlefonts_new()
    if args.plot_glyphs:
        qa.plot_glyphs()
    if args.browser_previews:
        qa.browser_previews()
    if args.fontbakery:
        qa.fontbakery()
    if args.diffenator:
        qa.diffenator()
    if args.diffbrowsers:
        qa.diffbrowsers()

    if args.out_url:
        qa.post_to_github(args.out_url)
    elif args.out_github and args.pull_request:
        qa.post_to_github(args.pull_request)
    elif args.out_github and args.github_dir:
        qa.post_to_github(args.github_dir)

if __name__ == "__main__":
    main()
<|endoftext|>


<commit_before># Copyright (c) 2015 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.

from PyQt5.QtCore import Qt, pyqtSlot, pyqtProperty, pyqtSignal

from UM.Qt.ListModel import ListModel
from UM.Resources import Resources
from UM.Application import Application
from UM.Logger import Logger
from UM.Settings.MachineSettings import MachineSettings

import os
import os.path
import json

class AvailableMachinesModel(ListModel):
    IdRole = Qt.UserRole + 1
    FileRole = Qt.UserRole + 2
    NameRole = Qt.UserRole + 3
    ManufacturerRole = Qt.UserRole + 4
    AuthorRole = Qt.UserRole + 5
    PagesRole = Qt.UserRole + 6

    def __init__(self, parent = None):
        super().__init__(parent)

        self.addRoleName(self.IdRole, "id")
        self.addRoleName(self.FileRole, "file")
        self.addRoleName(self.NameRole, "name")
        self.addRoleName(self.ManufacturerRole, "manufacturer")
        self.addRoleName(self.AuthorRole, "author")
        self.addRoleName(self.PagesRole, "pages")

        self._updateModel()

    @pyqtSlot(int,str)
    def createMachine(self, index, name):
        file = self.getItem(index)["file"]

        machine = MachineSettings()
        machine.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, file))
        machine.setName(name)

        app = Application.getInstance()
        index = app.addMachine(machine)
        app.setActiveMachine(app.getMachines()[index])

    def _createPagesModel(self, steps):
        model = ListModel()
        model.addRoleName(self.NameRole,"page")
        model.addRoleName(self.NameRole,"title")
        for step in steps:
            _page = step.get("page")
            _title = step.get("title")
            model.appendItem({"title": str(_title), "page": str(_page)})
        return model

    def _updateModel(self):
        dirs = Resources.getLocation(Resources.SettingsLocation)
        _machines_by_ultimaker = []
        _machines_by_other = []

        for dir in dirs:
            if not os.path.isdir(dir):
                continue

            for file in os.listdir(dir):
                data = None
                path = os.path.join(dir, file)

                if os.path.isdir(path):
                    continue

                with open(path, "rt", -1, "utf-8") as f:
                    try:
                        data = json.load(f)
                    except ValueError as e:
                        Logger.log("e", "Error when loading file {0}: {1}".format(file, e))
                        continue

                # Ignore any file that is explicitly marked as non-visible
                if not data.get("visible", True):
                    continue

                # Ignore any file that is marked as non-visible for the current application.
                appname = Application.getInstance().getApplicationName()
                if appname in data:
                    if not data[appname].get("visible", True):
                        continue

                _id = data.get("id")
                _file = file
                _name = data.get("name")
                _manufacturer = data.get("manufacturer")
                _author = data.get("author")
                _pages = data.get("add_pages")
                while _pages == None:
                    searchPath = os.path.join(dir, data.get("inherits"))
                    json_data = open(searchPath).read()
                    data = json.loads(json_data)
                    _pages = data.get("add_pages")
                _pages = self._createPagesModel(_pages)

                #makes sure that if Cura tries to load a faulty settings file, that it ignores the file and that Cura at least still loads
                if _id == None or _file == None or _name == None or _manufacturer == None:
                    continue

                #if the file is missing an author, it displays the author as "unspecified" instead of other
                if _author == None:
                    _author = "unspecified"

                if _manufacturer != "Ultimaker":
                    _machines_by_other.append([_manufacturer, _id, _file, _name, _author, _pages])

                if _manufacturer == "Ultimaker":
                     _machines_by_ultimaker.append([_id, _file, _name, _manufacturer, _author,_pages])

            for item in sorted(_machines_by_ultimaker):
                self.appendItem({ "id": item[0], "file": item[1], "name": item[2], "manufacturer": item[3], "author": item[4],"pages": item[5]})

            for item in sorted(_machines_by_other):
                self.appendItem({ "id": item[1], "file": item[2], "name": item[3], "manufacturer": item[0], "author": item[4],"pages": item[5]})
<commit_msg>Added explicit key parameter to sort<commit_after># Copyright (c) 2015 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.

from PyQt5.QtCore import Qt, pyqtSlot, pyqtProperty, pyqtSignal

from UM.Qt.ListModel import ListModel
from UM.Resources import Resources
from UM.Application import Application
from UM.Logger import Logger
from UM.Settings.MachineSettings import MachineSettings

import os
import os.path
import json

class AvailableMachinesModel(ListModel):
    IdRole = Qt.UserRole + 1
    FileRole = Qt.UserRole + 2
    NameRole = Qt.UserRole + 3
    ManufacturerRole = Qt.UserRole + 4
    AuthorRole = Qt.UserRole + 5
    PagesRole = Qt.UserRole + 6

    def __init__(self, parent = None):
        super().__init__(parent)

        self.addRoleName(self.IdRole, "id")
        self.addRoleName(self.FileRole, "file")
        self.addRoleName(self.NameRole, "name")
        self.addRoleName(self.ManufacturerRole, "manufacturer")
        self.addRoleName(self.AuthorRole, "author")
        self.addRoleName(self.PagesRole, "pages")

        self._updateModel()

    @pyqtSlot(int,str)
    def createMachine(self, index, name):
        file = self.getItem(index)["file"]

        machine = MachineSettings()
        machine.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, file))
        machine.setName(name)

        app = Application.getInstance()
        index = app.addMachine(machine)
        app.setActiveMachine(app.getMachines()[index])

    def _createPagesModel(self, steps):
        model = ListModel()
        model.addRoleName(self.NameRole,"page")
        model.addRoleName(self.NameRole,"title")
        for step in steps:
            _page = step.get("page")
            _title = step.get("title")
            model.appendItem({"title": str(_title), "page": str(_page)})
        return model

    def _updateModel(self):
        dirs = Resources.getLocation(Resources.SettingsLocation)
        _machines_by_ultimaker = []
        _machines_by_other = []

        for dir in dirs:
            if not os.path.isdir(dir):
                continue

            for file in os.listdir(dir):
                data = None
                path = os.path.join(dir, file)

                if os.path.isdir(path):
                    continue

                with open(path, "rt", -1, "utf-8") as f:
                    try:
                        data = json.load(f)
                    except ValueError as e:
                        Logger.log("e", "Error when loading file {0}: {1}".format(file, e))
                        continue

                # Ignore any file that is explicitly marked as non-visible
                if not data.get("visible", True):
                    continue

                # Ignore any file that is marked as non-visible for the current application.
                appname = Application.getInstance().getApplicationName()
                if appname in data:
                    if not data[appname].get("visible", True):
                        continue

                _id = data.get("id")
                _file = file
                _name = data.get("name")
                _manufacturer = data.get("manufacturer")
                _author = data.get("author")
                _pages = data.get("add_pages")
                while _pages == None:
                    searchPath = os.path.join(dir, data.get("inherits"))
                    json_data = open(searchPath).read()
                    data = json.loads(json_data)
                    _pages = data.get("add_pages")
                _pages = self._createPagesModel(_pages)

                #makes sure that if Cura tries to load a faulty settings file, that it ignores the file and that Cura at least still loads
                if _id == None or _file == None or _name == None or _manufacturer == None:
                    continue

                #if the file is missing an author, it displays the author as "unspecified" instead of other
                if _author == None:
                    _author = "unspecified"

                if _manufacturer != "Ultimaker":
                    _machines_by_other.append([_manufacturer, _id, _file, _name, _author, _pages])

                if _manufacturer == "Ultimaker":
                     _machines_by_ultimaker.append([_id, _file, _name, _manufacturer, _author,_pages])

            for item in sorted(_machines_by_ultimaker, key = lambda item: item[2]):
                self.appendItem({ "id": item[0], "file": item[1], "name": item[2], "manufacturer": item[3], "author": item[4],"pages": item[5]})

            for item in sorted(_machines_by_other, key = lambda item: item[2]):
                self.appendItem({ "id": item[1], "file": item[2], "name": item[3], "manufacturer": item[0], "author": item[4],"pages": item[5]})
<|endoftext|>


<commit_before>from __future__ import absolute_import, print_function

from datetime import datetime
import json
import logging
import os
import re
import sh
import shlex

import sys

from .exceptions import BranchError, VersionError

'''
    Uses a slightly modified version of this regex
    https://regex101.com/r/E0iVVS/2
'''
SEMVER_RE = re.compile('''
                       ^(?P<VersionTripple>
                            (?P<Major>0|[1-9][0-9]*)\.
                            (?P<Minor>0|[1-9][0-9]*)\.
                            (?P<Patch>0|[1-9][0-9]*)
                        ){1}
                        (?P<Tags>(?:\-
                            (?P<Prerelease>
                                (?:(?=[0]{1}[0-9A-Za-z-]{0})(?:[0]{1})|(?=[1-9]{1}[0-9]*[A-Za-z]{0})(?:[0-9]+)|(?=[0-9]*[A-Za-z-]+[0-9A-Za-z-]*)(?:[0-9A-Za-z-]+)){1}(?:\.(?=[0]{1}[0-9A-Za-z-]{0})(?:[0]{1})|\.(?=[1-9]{1}[0-9]*[A-Za-z]{0})(?:[0-9]+)|\.(?=[0-9]*[A-Za-z-]+[0-9A-Za-z-]*)(?:[0-9A-Za-z-]+))*){1}
                            ){0,1}(?:\+
                            (?P<Build>
                                (?:[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*
                            ))
                        ){0,1})$
                       ''', re.VERBOSE)

RC_RE = re.compile(r'(?P<full_version>.*-rc(?P<rc_number>\d+)).*')

INITIAL_VERSION = '0.0.0'

MAJOR = 0
MINOR = 1
PATCH = 2

def print_error(buf):
    print(buf, file=sys.stderr)

def is_calver(calver_version, calver_format):
    # ex: 201809.25 from 201809.25.1-rc
    d = '.'.join(calver_version.split('.', 2)[:2])
    try:
        datetime.strptime(d, calver_format)
    except AttributeError:
        return False
    except ValueError:
        return False
    else:
        return True

def is_semver(semver_version):
    return SEMVER_RE.match(semver_version) is not None

def is_rc(version):
    return RC_RE.match(version) is not None

class GitVersion(object):
    """
    Get and set git version tag
    """
    def __init__(self, args=None):
        self.args = args

    @property
    def logger(self):
        return logging.getLogger('{}.{}'.format(
            __name__,
            self.__class__.__name__))

    @property
    def branch(self):
        branch = os.environ.get('GIT_BRANCH')
        if branch is None:
            command = sh.git(*shlex.split('rev-parse --abbrev-ref HEAD'))
            lines = command.stdout.decode('utf8').strip().splitlines()
            branch = lines[0].strip()

            color_marker_idx = branch.find('\x1b')
            if color_marker_idx >= 0:
                self.logger.warning('found color marker in branch={}'.format(
                    branch.encode("utf8")))
                branch = branch[:color_marker_idx]

        # clean string to remove unwanted characters
        branch = branch.replace('/', '--')

        return branch

    @property
    def is_clean(self):
        """
        Returns whether the working copy is clean

        When there are uncommited changes in the working copy return False

        Returns:
            Boolean whether the working copy is clean
        """
        result = False

        command_l = 'git status --untracked --short'.split()
        command = getattr(sh, command_l[0])(command_l[1:])

        lines = command.stdout.decode('utf8').splitlines()
        for line in lines:
            line = line.rstrip()
            print_error('{}'.format(line))

        if not lines:
            result = True

        return result

    @property
    def is_calver(self):
        return(is_calver(self.version, self.args.calver_format))

    @property
    def is_semver(self):
        return(is_semver(self.version))

    @property
    def is_rc(self):
        return(is_rc(self.version))

    @property
    def version(self):
        try:
            command = sh.git(*shlex.split('describe --tags --always'))
        except sh.ErrorReturnCode_128:  # pylint: disable=E1101
            return None
        else:
            version = command.stdout.decode('utf8').strip()

            # if the branch flag was given,
            # check to see if we are on a tagged commit
            if self.args.branch:
                try:
                    command = sh.git(*shlex.split('describe --tags --exact-match'))
                except sh.ErrorReturnCode_128:  # pylint: disable=E1101
                    # not an exact match, so append the branch
                    version = '{}-{}'.format(version, self.branch)

            return version

    @classmethod
    def setup_subparser(cls, subcommand):
        parser = subcommand.add_parser('version', help=cls.__doc__)

        parser.set_defaults(cls=cls)
        parser.add_argument(
            '--bump', action='store_true',
            help='perform a version bump, by default the current version is displayed'
        )
        parser.add_argument(
            '-f', '--force', action='store_true',
            help='perform the operation even if the working copy is dirty'
        )
        parser.add_argument(
            '--patch', action='store_true', default=True,
            help='bump the patch version, this is the default bump if one is not specified'
        )
        parser.add_argument(
            '--minor', action='store_true',
            help='bump the minor version and reset patch back to 0'
        )
        parser.add_argument(
            '--major', action='store_true',
            help='bump the major version and reset minor and patch back to 0'
        )
        parser.add_argument(
            '--set',
            help='set version to the given version'
        )
        parser.add_argument(
            '--semver', action='store_true',
            help='only print out if the current tag is a semantic version, or exit 1'
        )
        parser.add_argument(
            '--calver', action='store_true',
            help='only print out if the current tag is a calendar version, or exit 1'
        )
        parser.add_argument(
            '--calver-format', action='store_true', default='%Y%m.%d',
            help='set the calver format (ex: \'%%Y%%m.%%d\')'
        )
        parser.add_argument(
            '--rc', action='store_true',
            help='when bumping, generate a release candidate tag instead of a proper version'
        )
        parser.add_argument(
            '-m', '--message',
            help='set the git tag message on the command line'
        )
        parser.add_argument(
            '--no-branch', action='store_false', dest='branch',
            help='do not append branch to the version when current commit is not tagged'
        )

    def get_next_version(self, version):
        # split the version and int'ify major, minor, and patch
        split_version = version.split('-', 1)[0].split('.', 3)
        for i in range(3):
            split_version[i] = int(split_version[i])

        if self.args.major:
            split_version[MAJOR] += 1
            split_version[MINOR] = 0
            split_version[PATCH] = 0
        elif self.args.minor:
            split_version[MINOR] += 1
            split_version[PATCH] = 0
        elif self.args.patch:
            split_version[PATCH] += 1

        return split_version[:3]

    def get_split_version(self, version):
        """Split the provided version and int'ify major, minor, and patch"""
        split_version = version.split('-', 1)[0].split('.', 3)
        for i in range(3):
            split_version[i] = int(split_version[i])

        return split_version

    def get_next_calver_version(self, version):
        # split the current date
        now = datetime.now().strftime(self.args.calver_format)
        split_calver = now.split('.', 2)
        for i in range(2):
            split_calver[i] = int(split_calver[i])

        # don't allow major/minor
        if self.args.major:
            raise VersionError('''
                You can not bump to a major calver release.
                If you want to override this use `--set --force` instead
                ''')
        elif self.args.minor:
            raise VersionError('''
                You can not bump to a minor calver release.
                If you want to override this use `--set --force` instead
                ''')
        elif self.args.patch:
            # if there are existing tags from today, bump the patch on the last one
            # otherwise move to the new date
            todays_tags = sh.git(*shlex.split(f'tag --list {now}*'))

            if todays_tags:
                last_tag = sorted(todays_tags.split('\n'))[-1]
                last_tag_split = self.get_split_version(last_tag)

                if not is_rc(last_tag):
                    last_tag_split[PATCH] += 1

                split_calver.append(last_tag_split[PATCH])
            else:
                split_calver.append(0)

        return split_calver[:3]

    @staticmethod
    def get_next_rc_version(version):
        matches = RC_RE.match(version)

        current_rc = int(matches.group('rc_number'))
        next_rc = current_rc + 1

        full_version = matches.group('full_version')
        next_version = full_version.replace('-rc{}'.format(current_rc), '-rc{}'.format(next_rc))

        return next_version.split('.')

    def bump(self):
        current_version = self.version
        if not current_version:
            current_version = INITIAL_VERSION

        if self.args.rc and self.is_rc:
            self.logger.info('Latest version is a release candidate, incrementing...')
            next_version = self.get_next_rc_version(current_version)
        elif self.args.calver:
            next_version = self.get_next_calver_version(current_version)
        else:
            split_dashes = current_version.split('-')

            if len(split_dashes) == 1:
                raise VersionError(
                    'Is version={} already bumped?'.format(current_version))

            current_version = split_dashes[0]

            if self.is_rc:
                next_version = [int(x) for x in current_version.split('.')]
            else:
                next_version = self.get_next_version(current_version)

        if self.args.rc and not self.is_rc:
            self.logger.info('Latest version is not a release candidate, generating initial rc tag...')
            next_version[-1] = str(next_version[-1]) + '-rc1'

        return next_version

    def check_bump(self):
        """
        Check to see if a bump request is being made
        """
        if not self.args.bump:
            return False

        return self.bump()

    def check_set(self):
        """
        Check to see if the version is being set
        """
        if not self.args.set:
            return None

        # if there's a calver flag, can only set to a correct calver version
        if self.args.calver:
            if not is_calver(self.args.set, self.args.calver_format):
                raise VersionError(
                    'Trying to set a non-calver version: {}'.format(self.args.set))

        return self.args.set.split('.')

    def get_tag_command(self, new_version):
        tag_command = 'git tag -a '

        if self.args.message:
            tag_command += '-m {} '.format(json.dumps(self.args.message))

        tag_command += new_version
        return tag_command

    def run(self):
        if not self.is_clean and not self.args.force:
            print_error('Abort: working copy not clean.')

            return 1

        current_version = self.version

        # check to see if an explicit version is being set
        new_version = self.check_set()
        if not new_version:
            # otherwise, see if the version is being bumped
            try:
                new_version = self.check_bump()
            except VersionError as exc:
                print_error(exc)

                return 1

        status = 0

        if new_version is False:
            if current_version:
                print(self.version)
            else:
                next_version = self.get_next_version(INITIAL_VERSION)
                print_error('No version found, use --bump to set to {}'.format(
                    self.stringify(next_version)
                ))

                status = 1
        else:
            version_str = self.stringify(new_version)
            tag_command = self.get_tag_command(version_str)
            os.system(tag_command)

            print(version_str)

        if self.args.rc:
            if not self.is_rc:
                return 1

        if self.args.semver:
            if not self.is_semver:
                return 1

        if self.args.calver:
            if not self.is_calver:
                return 1

        return status

    def stringify(self, version):
        return '.'.join([str(x) for x in version])
<commit_msg>Add comments<commit_after>from __future__ import absolute_import, print_function

from datetime import datetime
import json
import logging
import os
import re
import sh
import shlex

import sys

from .exceptions import BranchError, VersionError

'''
    Uses a slightly modified version of this regex
    https://regex101.com/r/E0iVVS/2
'''
SEMVER_RE = re.compile('''
                       ^(?P<VersionTripple>
                            (?P<Major>0|[1-9][0-9]*)\.
                            (?P<Minor>0|[1-9][0-9]*)\.
                            (?P<Patch>0|[1-9][0-9]*)
                        ){1}
                        (?P<Tags>(?:\-
                            (?P<Prerelease>
                                (?:(?=[0]{1}[0-9A-Za-z-]{0})(?:[0]{1})|(?=[1-9]{1}[0-9]*[A-Za-z]{0})(?:[0-9]+)|(?=[0-9]*[A-Za-z-]+[0-9A-Za-z-]*)(?:[0-9A-Za-z-]+)){1}(?:\.(?=[0]{1}[0-9A-Za-z-]{0})(?:[0]{1})|\.(?=[1-9]{1}[0-9]*[A-Za-z]{0})(?:[0-9]+)|\.(?=[0-9]*[A-Za-z-]+[0-9A-Za-z-]*)(?:[0-9A-Za-z-]+))*){1}
                            ){0,1}(?:\+
                            (?P<Build>
                                (?:[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*
                            ))
                        ){0,1})$
                       ''', re.VERBOSE)

RC_RE = re.compile(r'(?P<full_version>.*-rc(?P<rc_number>\d+)).*')

INITIAL_VERSION = '0.0.0'

MAJOR = 0
MINOR = 1
PATCH = 2

def print_error(buf):
    print(buf, file=sys.stderr)

def is_calver(calver_version, calver_format):
    # ex: 201809.25 from 201809.25.1-rc
    d = '.'.join(calver_version.split('.', 2)[:2])
    try:
        datetime.strptime(d, calver_format)
    except AttributeError:
        return False
    except ValueError:
        return False
    else:
        return True

def is_semver(semver_version):
    return SEMVER_RE.match(semver_version) is not None

def is_rc(version):
    return RC_RE.match(version) is not None

class GitVersion(object):
    """
    Get and set git version tag
    """
    def __init__(self, args=None):
        self.args = args

    @property
    def logger(self):
        return logging.getLogger('{}.{}'.format(
            __name__,
            self.__class__.__name__))

    @property
    def branch(self):
        branch = os.environ.get('GIT_BRANCH')
        if branch is None:
            command = sh.git(*shlex.split('rev-parse --abbrev-ref HEAD'))
            lines = command.stdout.decode('utf8').strip().splitlines()
            branch = lines[0].strip()

            color_marker_idx = branch.find('\x1b')
            if color_marker_idx >= 0:
                self.logger.warning('found color marker in branch={}'.format(
                    branch.encode("utf8")))
                branch = branch[:color_marker_idx]

        # clean string to remove unwanted characters
        branch = branch.replace('/', '--')

        return branch

    @property
    def is_clean(self):
        """
        Returns whether the working copy is clean

        When there are uncommited changes in the working copy return False

        Returns:
            Boolean whether the working copy is clean
        """
        result = False

        command_l = 'git status --untracked --short'.split()
        command = getattr(sh, command_l[0])(command_l[1:])

        lines = command.stdout.decode('utf8').splitlines()
        for line in lines:
            line = line.rstrip()
            print_error('{}'.format(line))

        if not lines:
            result = True

        return result

    @property
    def is_calver(self):
        return(is_calver(self.version, self.args.calver_format))

    @property
    def is_semver(self):
        return(is_semver(self.version))

    @property
    def is_rc(self):
        return(is_rc(self.version))

    @property
    def version(self):
        try:
            command = sh.git(*shlex.split('describe --tags --always'))
        except sh.ErrorReturnCode_128:  # pylint: disable=E1101
            return None
        else:
            version = command.stdout.decode('utf8').strip()

            # if the branch flag was given,
            # check to see if we are on a tagged commit
            if self.args.branch:
                try:
                    command = sh.git(*shlex.split('describe --tags --exact-match'))
                except sh.ErrorReturnCode_128:  # pylint: disable=E1101
                    # not an exact match, so append the branch
                    version = '{}-{}'.format(version, self.branch)

            return version

    @classmethod
    def setup_subparser(cls, subcommand):
        parser = subcommand.add_parser('version', help=cls.__doc__)

        parser.set_defaults(cls=cls)
        parser.add_argument(
            '--bump', action='store_true',
            help='perform a version bump, by default the current version is displayed'
        )
        parser.add_argument(
            '-f', '--force', action='store_true',
            help='perform the operation even if the working copy is dirty'
        )
        parser.add_argument(
            '--patch', action='store_true', default=True,
            help='bump the patch version, this is the default bump if one is not specified'
        )
        parser.add_argument(
            '--minor', action='store_true',
            help='bump the minor version and reset patch back to 0'
        )
        parser.add_argument(
            '--major', action='store_true',
            help='bump the major version and reset minor and patch back to 0'
        )
        parser.add_argument(
            '--set',
            help='set version to the given version'
        )
        parser.add_argument(
            '--semver', action='store_true',
            help='only print out if the current tag is a semantic version, or exit 1'
        )
        parser.add_argument(
            '--calver', action='store_true',
            help='only print out if the current tag is a calendar version, or exit 1'
        )
        parser.add_argument(
            '--calver-format', action='store_true', default='%Y%m.%d',
            help='set the calver format (ex: \'%%Y%%m.%%d\')'
        )
        parser.add_argument(
            '--rc', action='store_true',
            help='when bumping, generate a release candidate tag instead of a proper version'
        )
        parser.add_argument(
            '-m', '--message',
            help='set the git tag message on the command line'
        )
        parser.add_argument(
            '--no-branch', action='store_false', dest='branch',
            help='do not append branch to the version when current commit is not tagged'
        )

    def get_next_version(self, version):
        # split the version and int'ify major, minor, and patch
        split_version = version.split('-', 1)[0].split('.', 3)
        for i in range(3):
            split_version[i] = int(split_version[i])

        if self.args.major:
            split_version[MAJOR] += 1
            split_version[MINOR] = 0
            split_version[PATCH] = 0
        elif self.args.minor:
            split_version[MINOR] += 1
            split_version[PATCH] = 0
        elif self.args.patch:
            split_version[PATCH] += 1

        return split_version[:3]

    def get_split_version(self, version):
        """Split the provided version and int'ify major, minor, and patch"""
        split_version = version.split('-', 1)[0].split('.', 3)
        for i in range(3):
            split_version[i] = int(split_version[i])

        return split_version

    def get_next_calver_version(self, version):
        # split the current date
        now = datetime.now().strftime(self.args.calver_format)
        split_calver = now.split('.', 2)
        for i in range(2):
            split_calver[i] = int(split_calver[i])

        # don't allow major/minor
        if self.args.major:
            raise VersionError('''
                You can not bump to a major calver release.
                If you want to override this use `--set --force` instead
                ''')
        elif self.args.minor:
            raise VersionError('''
                You can not bump to a minor calver release.
                If you want to override this use `--set --force` instead
                ''')
        elif self.args.patch:
            # if there are existing tags from today, bump the patch on the last one
            # otherwise move to the new date
            todays_tags = sh.git(*shlex.split(f'tag --list {now}*'))

            if todays_tags:
                last_tag = sorted(todays_tags.split('\n'))[-1]
                last_tag_split = self.get_split_version(last_tag)

                if not is_rc(last_tag):
                    last_tag_split[PATCH] += 1

                split_calver.append(last_tag_split[PATCH])
            else:
                split_calver.append(0)

        return split_calver[:3]

    @staticmethod
    def get_next_rc_version(version):
        matches = RC_RE.match(version)

        current_rc = int(matches.group('rc_number'))
        next_rc = current_rc + 1

        # use the full_version match in order to remove any git version suffix
        full_version = matches.group('full_version')
        next_version = full_version.replace('-rc{}'.format(current_rc), '-rc{}'.format(next_rc))

        return next_version.split('.')

    def bump(self):
        current_version = self.version
        if not current_version:
            current_version = INITIAL_VERSION

        if self.args.rc and self.is_rc:
            self.logger.info('Latest version is a release candidate, incrementing...')
            next_version = self.get_next_rc_version(current_version)
        elif self.args.calver:
            next_version = self.get_next_calver_version(current_version)
        else:
            split_dashes = current_version.split('-')

            if len(split_dashes) == 1:
                raise VersionError(
                    'Is version={} already bumped?'.format(current_version))

            current_version = split_dashes[0]

            # when the versio is an RC, don't bump any version number, just strip off the RC suffix
            if self.is_rc:
                next_version = [int(x) for x in current_version.split('.')]
            else:
                next_version = self.get_next_version(current_version)

        if self.args.rc and not self.is_rc:
            self.logger.info('Latest version is not a release candidate, generating initial rc tag...')
            next_version[-1] = str(next_version[-1]) + '-rc1'

        return next_version

    def check_bump(self):
        """
        Check to see if a bump request is being made
        """
        if not self.args.bump:
            return False

        return self.bump()

    def check_set(self):
        """
        Check to see if the version is being set
        """
        if not self.args.set:
            return None

        # if there's a calver flag, can only set to a correct calver version
        if self.args.calver:
            if not is_calver(self.args.set, self.args.calver_format):
                raise VersionError(
                    'Trying to set a non-calver version: {}'.format(self.args.set))

        return self.args.set.split('.')

    def get_tag_command(self, new_version):
        tag_command = 'git tag -a '

        if self.args.message:
            tag_command += '-m {} '.format(json.dumps(self.args.message))

        tag_command += new_version
        return tag_command

    def run(self):
        if not self.is_clean and not self.args.force:
            print_error('Abort: working copy not clean.')

            return 1

        current_version = self.version

        # check to see if an explicit version is being set
        new_version = self.check_set()
        if not new_version:
            # otherwise, see if the version is being bumped
            try:
                new_version = self.check_bump()
            except VersionError as exc:
                print_error(exc)

                return 1

        status = 0

        if new_version is False:
            if current_version:
                print(self.version)
            else:
                next_version = self.get_next_version(INITIAL_VERSION)
                print_error('No version found, use --bump to set to {}'.format(
                    self.stringify(next_version)
                ))

                status = 1
        else:
            version_str = self.stringify(new_version)
            tag_command = self.get_tag_command(version_str)
            os.system(tag_command)

            print(version_str)

        if self.args.rc:
            if not self.is_rc:
                return 1

        if self.args.semver:
            if not self.is_semver:
                return 1

        if self.args.calver:
            if not self.is_calver:
                return 1

        return status

    def stringify(self, version):
        return '.'.join([str(x) for x in version])
<|endoftext|>


<commit_before># importing required packages
'''
How to initiate bokeh server using this file:

type bokeh serve --port 5002 widgets_part2.py in your terminal
Then you may go to the FirstStop landing page to click the bidding price link

'''

from bokeh.io import curdoc, output_file, show, reset_output
from bokeh.layouts import widgetbox, layout
from bokeh.models.widgets import Button, TextInput, RadioButtonGroup, Select, Slider, Paragraph, Div
import numpy as np
import pandas as pd

Logo = Div(text="""""")

# Create Input Controls
listprice = TextInput(title="enter list price/predict price here ($)")
zipcode = TextInput(title="enter zipcode here")

button_1 = Button(label="Submit")
button_2 = Button(label="Reset")
output = Paragraph(width=600, height=300) #or use pretext, for a
 tag in html

hottest = [98004, 98006, 98007, 98008, 98112, 98033, 98034, 98039, 98040,
           98052, 98053, 98074, 98075, 98077, 98103, 98112, 98177, 98115, 98117]
medium_hot = [98001, 98005, 98023, 98027, 98028, 98029, 98056, 98059, 98105,
              98107, 98116, 98118, 98119, 98122, 98125, 98133, 98155, 98199]

def bidding_price(zipcode, list_price):
    if zipcode in hottest:
        add_price=(np.random.randint(12, 18, None, int)/100)*list_price
        bid_price = list_price + add_price
    elif zipcode in medium_hot:
        add_price=(np.random.randint(5, 10, None, int)/100)*list_price
        bid_price = list_price + add_price
    else:
        add_price = (np.random.randint(5, 10, None, int) / 100) * list_price
        bid_price = list_price - add_price

    return bid_price

def submit():
    #these are made up coefficients for now
    value = bidding_price(float(zipcode.value), float(listprice.value))
    output.text = 'Your suggested bidding price is: ' + str(int(value)) + ' $'

def reset():
    #reset_output()
    output.text = None

button_1.on_click(submit)
button_2.on_click(reset)

#lay_out = layout([[select1, select2, select3, select4], [button_1, button_2], [output]])
lay_out = layout(children=[[Logo], [listprice, zipcode], [button_1], [button_2], [output]],
            sizing_mode='fixed')
curdoc().add_root(lay_out)
curdoc().title = "Predict the bidding price of your first home"
<commit_msg>cleaned up part2_bid_price.py<commit_after># importing required packages
'''
How to initiate bokeh server using this file:

type bokeh serve --port 5002 widgets_part2.py in your terminal
Then you may go to the FirstStop landing page to click the bidding price link

'''

from bokeh.io import curdoc
from bokeh.layouts import layout
from bokeh.models.widgets import Button, TextInput, Paragraph, Div
import numpy as np

LOGO = Div(text="""""")

# Create Input Controls
LISTPRICE = TextInput(title="enter list price/predict price here ($)")
ZIPCODE = TextInput(title="enter zipcode here")

BUTTON_1 = Button(label="Submit")
BUTTON_2 = Button(label="Reset")
OUTPUT = Paragraph(width=600, height=300) #or use pretext, for a
 tag in html

HOTTEST = [98004, 98006, 98007, 98008, 98112, 98033, 98034, 98039, 98040,
           98052, 98053, 98074, 98075, 98077, 98103, 98112, 98177, 98115, 98117]
MEDIUM_HOT = [98001, 98005, 98023, 98027, 98028, 98029, 98056, 98059, 98105,
              98107, 98116, 98118, 98119, 98122, 98125, 98133, 98155, 98199]

def bidding_price(zipcode, list_price):
    """
    This function implements a mathematical model to calculate bidding price of a house
    :param zipcode: Zipcode of house entered by user
    :param list_price: List price of house entered by user
    :return: returns the estimated bidding price
    """
    if zipcode in HOTTEST:
        add_price = (np.random.randint(12, 18, None, int)/100)*list_price
        bid_price = list_price + add_price
    elif zipcode in MEDIUM_HOT:
        add_price = (np.random.randint(5, 10, None, int)/100)*list_price
        bid_price = list_price + add_price
    else:
        add_price = (np.random.randint(5, 10, None, int) / 100) * list_price
        bid_price = list_price - add_price

    return bid_price

def submit():
    """
    these are made up coefficients for now
    """
    value = bidding_price(float(ZIPCODE.value), float(LISTPRICE.value))
    OUTPUT.text = 'Your suggested bidding price is: ' + str(int(value)) + ' $'

def reset():
    """
    This function resets the output
    """
    OUTPUT.text = None

BUTTON_1.on_click(submit)
BUTTON_2.on_click(reset)

LAY_OUT = layout(children=[[LOGO], [LISTPRICE, ZIPCODE], [BUTTON_1], [BUTTON_2], [OUTPUT]],
                 sizing_mode='fixed')
curdoc().add_root(LAY_OUT)
curdoc().title = "Predict the bidding price of your first home"
<|endoftext|>