<commit_before># ex: set expandtab softtabstop=4 shiftwidth=4: -*- cpy-indent-level: 4; indent-tabs-mode: nil -*-
#
# Copyright (C) 2011,2012  Contributor
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the EU DataGrid Software License.  You should
# have received a copy of the license with this program, and the
# license is published at
# http://eu-datagrid.web.cern.ch/eu-datagrid/license.html.
#
# THE FOLLOWING DISCLAIMER APPLIES TO ALL SOFTWARE CODE AND OTHER
# MATERIALS CONTRIBUTED IN CONNECTION WITH THIS PROGRAM.
#
# THIS SOFTWARE IS LICENSED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE AND ANY WARRANTY OF NON-INFRINGEMENT, ARE
# DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THIS
# SOFTWARE MAY BE REDISTRIBUTED TO OTHERS ONLY BY EFFECTIVELY USING
# THIS OR ANOTHER EQUIVALENT DISCLAIMER AS WELL AS ANY OTHER LICENSE
# TERMS THAT MAY APPLY.
""" Representation of Fully Qualified Domain Names """

from datetime import datetime

from sqlalchemy import (Integer, DateTime, Sequence, Column, ForeignKey,
                        UniqueConstraint)
from sqlalchemy.orm import relation, deferred
from sqlalchemy.orm.session import Session

from aquilon.exceptions_ import InternalError, ArgumentError
from aquilon.aqdb.model import Base, DnsDomain, DnsEnvironment
from aquilon.aqdb.model.base import _raise_custom
from aquilon.aqdb.model.dns_domain import parse_fqdn
from aquilon.aqdb.column_types import AqStr

_TN = "fqdn"

class Fqdn(Base):
    __tablename__ = _TN
    _instance_label = 'fqdn'

    id = Column(Integer, Sequence('%s_id_seq' % _TN), primary_key=True)

    name = Column(AqStr(63), nullable=False)

    dns_domain_id = Column(Integer, ForeignKey('dns_domain.id',
                                               name='%s_dns_domain_fk' % _TN),
                           nullable=False)

    dns_environment_id = Column(Integer, ForeignKey('dns_environment.id',
                                                    name='%s_dns_env_fk' % _TN),
                                nullable=False)

    creation_date = deferred(Column(DateTime, default=datetime.now,
                                    nullable=False))

    dns_domain = relation(DnsDomain, innerjoin=True)

    dns_environment = relation(DnsEnvironment, innerjoin=True)

    @property
    def fqdn(self):
        return self.name + '.' + self.dns_domain.name

    @classmethod
    def get_unique(cls, session, fqdn=None, dns_environment=None, name=None,
                   dns_domain=None, **kwargs):
        if fqdn:
            if name or dns_domain:  # pragma: no cover
                raise TypeError("fqdn and name/dns_domain should not be mixed")
            (name, dns_domain) = parse_fqdn(session, fqdn)

        if not isinstance(dns_environment, DnsEnvironment):
            dns_environment = DnsEnvironment.get_unique_or_default(session,
                                                                   dns_environment)
        return super(Fqdn, cls).get_unique(session, name=name,
                                           dns_domain=dns_domain,
                                           dns_environment=dns_environment,
                                           **kwargs)

    @classmethod
    def get_or_create(cls, session, dns_environment=None, preclude=False,
                      ignore_name_check=False, **kwargs):
        fqdn = cls.get_unique(session, dns_environment=dns_environment, **kwargs)
        if fqdn:
            if preclude:
                _raise_custom(preclude, ArgumentError, "{0} already exists.")
            return fqdn

        if not isinstance(dns_environment, DnsEnvironment):
            dns_environment = DnsEnvironment.get_unique_or_default(session,
                                                                   dns_environment)

        fqdn = cls(session=session, dns_environment=dns_environment,
                   ignore_name_check=ignore_name_check, **kwargs)
        session.add(fqdn)
        session.flush()
        return fqdn

    @classmethod
    def check_name(cls, name, dns_domain, ignore_name_check=False):
        """ Validate the name parameter """

        if not isinstance(name, basestring):  # pragma: no cover
            raise TypeError("%s: name must be a string." % cls.name)
        if not isinstance(dns_domain, DnsDomain):  # pragma: no cover
            raise TypeError("%s: dns_domain must be a DnsDomain." % cls.name)

        # Allow SRV records to opt out from this test
        if not ignore_name_check:
            DnsDomain.check_label(name)

        # The limit for DNS name length is 255, assuming wire format. This
        # translates to 253 for simple ASCII text; see:
        # http://www.ops.ietf.org/lists/namedroppers/namedroppers.2003/msg00964.html
        if len(name) + 1 + len(dns_domain.name) > 253:
            raise ArgumentError('The fully qualified domain name is too long.')

    def _check_session(self, session):
        if not session or not isinstance(session, Session):  # pragma: no cover
            raise InternalError("%s needs a session." % self._get_class_label())

    def __init__(self, session=None, name=None, dns_domain=None, fqdn=None,
                 dns_environment=None, ignore_name_check=False, **kwargs):
        if fqdn:
            if name or dns_domain:  # pragma: no cover
                raise TypeError("fqdn and name/dns_domain should not be mixed")
            self._check_session(session)
            (name, dns_domain) = parse_fqdn(session, fqdn)

        self.check_name(name, dns_domain, ignore_name_check)

        if not isinstance(dns_environment, DnsEnvironment):
            self._check_session(session)
            dns_environment = DnsEnvironment.get_unique_or_default(session,
                                                                   dns_environment)

        super(Fqdn, self).__init__(name=name, dns_domain=dns_domain,
                                   dns_environment=dns_environment, **kwargs)

fqdn = Fqdn.__table__  # pylint: disable=C0103, E1101
fqdn.primary_key.name = '%s_pk' % _TN
fqdn.append_constraint(UniqueConstraint('name', 'dns_domain_id',
                                        'dns_environment_id',
                                        name='%s_name_domain_env_uk' % _TN))

fqdn.info['unique_fields'] = ['dns_environment', 'dns_domain', 'name']
<commit_msg>Allow passing query options to Fqdn.get_or_create()<commit_after># ex: set expandtab softtabstop=4 shiftwidth=4: -*- cpy-indent-level: 4; indent-tabs-mode: nil -*-
#
# Copyright (C) 2011,2012  Contributor
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the EU DataGrid Software License.  You should
# have received a copy of the license with this program, and the
# license is published at
# http://eu-datagrid.web.cern.ch/eu-datagrid/license.html.
#
# THE FOLLOWING DISCLAIMER APPLIES TO ALL SOFTWARE CODE AND OTHER
# MATERIALS CONTRIBUTED IN CONNECTION WITH THIS PROGRAM.
#
# THIS SOFTWARE IS LICENSED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE AND ANY WARRANTY OF NON-INFRINGEMENT, ARE
# DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THIS
# SOFTWARE MAY BE REDISTRIBUTED TO OTHERS ONLY BY EFFECTIVELY USING
# THIS OR ANOTHER EQUIVALENT DISCLAIMER AS WELL AS ANY OTHER LICENSE
# TERMS THAT MAY APPLY.
""" Representation of Fully Qualified Domain Names """

from datetime import datetime

from sqlalchemy import (Integer, DateTime, Sequence, Column, ForeignKey,
                        UniqueConstraint)
from sqlalchemy.orm import relation, deferred
from sqlalchemy.orm.session import Session

from aquilon.exceptions_ import InternalError, ArgumentError
from aquilon.aqdb.model import Base, DnsDomain, DnsEnvironment
from aquilon.aqdb.model.base import _raise_custom
from aquilon.aqdb.model.dns_domain import parse_fqdn
from aquilon.aqdb.column_types import AqStr

_TN = "fqdn"

class Fqdn(Base):
    __tablename__ = _TN
    _instance_label = 'fqdn'

    id = Column(Integer, Sequence('%s_id_seq' % _TN), primary_key=True)

    name = Column(AqStr(63), nullable=False)

    dns_domain_id = Column(Integer, ForeignKey('dns_domain.id',
                                               name='%s_dns_domain_fk' % _TN),
                           nullable=False)

    dns_environment_id = Column(Integer, ForeignKey('dns_environment.id',
                                                    name='%s_dns_env_fk' % _TN),
                                nullable=False)

    creation_date = deferred(Column(DateTime, default=datetime.now,
                                    nullable=False))

    dns_domain = relation(DnsDomain, innerjoin=True)

    dns_environment = relation(DnsEnvironment, innerjoin=True)

    @property
    def fqdn(self):
        return self.name + '.' + self.dns_domain.name

    @classmethod
    def get_unique(cls, session, fqdn=None, dns_environment=None, name=None,
                   dns_domain=None, **kwargs):
        if fqdn:
            if name or dns_domain:  # pragma: no cover
                raise TypeError("fqdn and name/dns_domain should not be mixed")
            (name, dns_domain) = parse_fqdn(session, fqdn)

        if not isinstance(dns_environment, DnsEnvironment):
            dns_environment = DnsEnvironment.get_unique_or_default(session,
                                                                   dns_environment)
        return super(Fqdn, cls).get_unique(session, name=name,
                                           dns_domain=dns_domain,
                                           dns_environment=dns_environment,
                                           **kwargs)

    @classmethod
    def get_or_create(cls, session, dns_environment=None, preclude=False,
                      ignore_name_check=False, query_options=None, **kwargs):
        fqdn = cls.get_unique(session, dns_environment=dns_environment,
                              query_options=query_options, **kwargs)
        if fqdn:
            if preclude:
                _raise_custom(preclude, ArgumentError, "{0} already exists.")
            return fqdn

        if not isinstance(dns_environment, DnsEnvironment):
            dns_environment = DnsEnvironment.get_unique_or_default(session,
                                                                   dns_environment)

        fqdn = cls(session=session, dns_environment=dns_environment,
                   ignore_name_check=ignore_name_check, **kwargs)
        session.add(fqdn)
        session.flush()
        return fqdn

    @classmethod
    def check_name(cls, name, dns_domain, ignore_name_check=False):
        """ Validate the name parameter """

        if not isinstance(name, basestring):  # pragma: no cover
            raise TypeError("%s: name must be a string." % cls.name)
        if not isinstance(dns_domain, DnsDomain):  # pragma: no cover
            raise TypeError("%s: dns_domain must be a DnsDomain." % cls.name)

        # Allow SRV records to opt out from this test
        if not ignore_name_check:
            DnsDomain.check_label(name)

        # The limit for DNS name length is 255, assuming wire format. This
        # translates to 253 for simple ASCII text; see:
        # http://www.ops.ietf.org/lists/namedroppers/namedroppers.2003/msg00964.html
        if len(name) + 1 + len(dns_domain.name) > 253:
            raise ArgumentError('The fully qualified domain name is too long.')

    def _check_session(self, session):
        if not session or not isinstance(session, Session):  # pragma: no cover
            raise InternalError("%s needs a session." % self._get_class_label())

    def __init__(self, session=None, name=None, dns_domain=None, fqdn=None,
                 dns_environment=None, ignore_name_check=False, **kwargs):
        if fqdn:
            if name or dns_domain:  # pragma: no cover
                raise TypeError("fqdn and name/dns_domain should not be mixed")
            self._check_session(session)
            (name, dns_domain) = parse_fqdn(session, fqdn)

        self.check_name(name, dns_domain, ignore_name_check)

        if not isinstance(dns_environment, DnsEnvironment):
            self._check_session(session)
            dns_environment = DnsEnvironment.get_unique_or_default(session,
                                                                   dns_environment)

        super(Fqdn, self).__init__(name=name, dns_domain=dns_domain,
                                   dns_environment=dns_environment, **kwargs)

fqdn = Fqdn.__table__  # pylint: disable=C0103, E1101
fqdn.primary_key.name = '%s_pk' % _TN
fqdn.append_constraint(UniqueConstraint('name', 'dns_domain_id',
                                        'dns_environment_id',
                                        name='%s_name_domain_env_uk' % _TN))

fqdn.info['unique_fields'] = ['dns_environment', 'dns_domain', 'name']
<|endoftext|>


<commit_before>from app import db

class Post(db.Model):

	__tablename__ = "post"

	id        = db.Column(db.Integer, primary_key = True)
	title     = db.Column(db.String(256), nullable = False)
	author    = db.Column(db.String(128), nullable = False)
	create_at = db.Column(db.DateTime(), default = db.func.current_timestamp())
	content   = db.Column(db.Text())

	def __init__(self, title, author, content):
		self.title   = title
		self.author  = author
		self.content = content

	def __repr__(self):
		return "<Post {}>".format(self.title)<commit_msg>Added slug field<commit_after>from app import db

class Post(db.Model):

	__tablename__ = "post"

	id        = db.Column(db.Integer, primary_key = True)
	slug      = db.Column(db.String(256), nullable = False)
	title     = db.Column(db.String(256), nullable = False)
	author    = db.Column(db.String(128), nullable = False)
	create_at = db.Column(db.DateTime(), default = db.func.current_timestamp())
	content   = db.Column(db.Text())

	def __init__(self, title, author, content):
		self.title   = title
		self.author  = author
		self.content = content

	def __repr__(self):
		return "<Post {}>".format(self.title)<|endoftext|>


<commit_before>#!python3
from daterobot import lstnuevafecha
#from input import jornada as lunes
import datetime
import time

diadef=[]

#for special matchdays with three matches on sunday, beginning season 2017/2018.
#Replace/check items in array every new season
specialMD = [7,9,29]
conlunes = [13,22,23,25]
english = [5,16]
sevenplustwo = [0]

#print lstnuevafecha
#print lunes
for date in lstnuevafecha:
	jornada = len(diadef)//9
	jornada +=1
	#print jornada
	#datelst=[]
	fecha = date.split('-')
	dia = fecha[0]
	mes = fecha[1]
	yyear = fecha[2]
	strdate = dia+','+mes+','+yyear

	for i in range(0, len(fecha)):
		date1 = datetime.datetime.strptime(strdate, "%Y,%m,%d")
		date2 = date1.strftime('%A')

#special matchdays with five matches on saturday, two on sunday, one on monday
#no need to change this every season. just change items in conlunes

#TODO CHECAR COMPUTO DE FECHAS: ESTA FALLANDO CONLUNES Y QUIZA OTRAS ESPECIALES EN PYTHON 3.
	if jornada in conlunes:
		#print "Si es de la jornada"
		if date2 == 'Friday':
			diadef.append(date)
		elif date2 == 'Saturday':
			for i in range(0,5):
				diadef.append(date)
		elif date2 == 'Sunday':
			for i in range(0,2):
				diadef.append(date)
		else:
			if date2 == 'Monday':
				for i in range(0, 1):
					diadef.append(date)

	#for wednesday matches on english weeks
	elif jornada in english:
		if date2 == 'Tuesday':
			for i in range(0,4):
				diadef.append(date)
		if date2 == 'Wednesday':
			for i in range(0,5):
				diadef.append(date)

	#new MD model with seven days on sat + 2
	elif jornada in sevenplustwo:
		if date2 == 'Saturday':
			for i in range(0,7):
				diadef.append(date)
		if date2 == 'Sunday':
			for i in range(0,2):
				diadef.append(date)

#special matchdays with three matches on sunday, five on saturday
#no need to change this every season. just change items in specialMD

	elif jornada in specialMD:
		if date2 == "Friday":
			diadef.append(date)

		elif date2 == "Saturday":
			for i in range(0,5):
				diadef.append(date)

		else:
			for i in range(0, 3):
				diadef.append(date)

#MD on Easter Week. Delete or adjust MD Number for other seasons
	#elif jornada == 28:
		#for i in range(0,6):
			#diadef.append(date)

#for the last two matchdays of each tournament,
#all matches in one day
# to be verified at the end of this tournament
	elif jornada>32:
		for i in range(0,9):
			diadef.append(date)

	else:
		if date2=="Friday":
			diadef.append(date)

		if date2=="Saturday":
			for i in range(0,6):
				diadef.append(date)

		if date2=="Sunday":
			for i in range(0,2):
				diadef.append(date)

#print diadef
#print len(diadef)
<commit_msg>Add files via upload<commit_after># !python3
from daterobot import lstnuevafecha
# from input import jornada as lunes
import datetime
# import time

diadef = []

# special matchday formats
# choose format array and append matchdays as items accordingly
# array items change every season
specialMD = [7, 9, 29, 32]
conlunes = [13, 22, 23, 25]
english = [5, 16]
sevenplustwo = [0]
sinviernes = [30]

# print lstnuevafecha
# print lunes
# len(diadef) must be == len(lsthome) == len(lstaway)
# SOLVED: operator // floor division instead of / por python 3.x
for date in lstnuevafecha:
	jornada = len(diadef) // 9
	jornada +=1
	#print jornada
	#datelst=[]
	fecha = date.split('-')
	dia = fecha[0]
	mes = fecha[1]
	yyear = fecha[2]
	strdate = dia+','+mes+','+yyear
# extract weekday of date using datetime, strftime
	for i in range(0, len(fecha)):
		date1 = datetime.datetime.strptime(strdate, "%Y,%m,%d")
		date2 = date1.strftime('%A')

# proof if machday is of special format

# matchdays with five matches on saturday, two on sunday, one on monday
# no need to change this every season. just change items in conlunes
# matchday with one match on monday
	if jornada in conlunes:
		if date2 == 'Friday':
			diadef.append(date)
		elif date2 == 'Saturday':
			for i in range(0,5):
				diadef.append(date)
		elif date2 == 'Sunday':
			for i in range(0,2):
				diadef.append(date)
		else:
			if date2 == 'Monday':
				for i in range(0, 1):
					diadef.append(date)

	# matchday on tuesday and wednesday
	elif jornada in english:
		if date2 == 'Tuesday':
			for i in range(0,4):
				diadef.append(date)
		if date2 == 'Wednesday':
			for i in range(0,5):
				diadef.append(date)

	# seven matches on sat + 2 sunday
	elif jornada in sevenplustwo:
		if date2 == 'Saturday':
			for i in range(0,7):
				diadef.append(date)
		if date2 == 'Sunday':
			for i in range(0,2):
				diadef.append(date)

# three matches on sunday, five on saturday, one friday
	elif jornada in specialMD:
		if date2 == "Friday":
			diadef.append(date)

		elif date2 == "Saturday":
			for i in range(0,5):
				diadef.append(date)

		else:
			for i in range(0, 3):
				diadef.append(date)

# six matches on saturday, two sunday, one monday
	elif jornada in sinviernes:
		if date2 == "Saturday":
			for i in range(0,6):
				diadef.append(date)

		elif date2 == "Sunday":
			for i in range(0, 2):
				diadef.append(date)

		else:
			diadef.append(date)

# MD on Easter Week. Delete or adjust MD Number for other seasons
	# elif jornada == 28:
		# for i in range(0,6):
			# diadef.append(date)

# for the last two matchdays of each tournament,
# all matches in one day
	elif jornada > 32:
		for i in range(0, 9):
			diadef.append(date)

# if matchday is not special format, then traditional
# traditional matchdays: one friday, six saturday, two sunday
	else:
		if date2 == "Friday":
			diadef.append(date)

		if date2 == "Saturday":
			for i in range(0,6):
				diadef.append(date)

		if date2 == "Sunday":
			for i in range(0,2):
				diadef.append(date)

# print diadef
# print len(diadef)
<|endoftext|>


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

""" cluster.py

Cluster functionality
"""
__copyright__ = 'Copyright 2013 Vanderbilt University. All Rights Reserved'

import subprocess,os
from subprocess import CalledProcessError
from datetime import datetime
from dax_settings import PBS_TEMPLATE,CMD_SUBMIT_PBS,CMD_COUNT_NB_JOBS,CMD_GET_JOB_STATUS,CMD_GET_JOB_DONE_INFO,PREFIX_WALLTIME,SUFFIX_WALLTIME,PREFIX_MEMORY,SUFFIX_MEMORY,EXIT_STATUS,RUNNING_STATUS,QUEUE_STATUS,PREFIX_JOBID,SUFFIX_JOBID

MAX_TRACE_DAYS=30

def count_jobs():
    cmd = CMD_COUNT_NB_JOBS
    try:
        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
        return int(output)
    except (CalledProcessError,ValueError):
        return -1

def job_status(jobid):
    cmd=CMD_GET_JOB_STATUS.safe_substitute(**{'jobid':jobid})
    try:
        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
        output = output.strip()
        if output==RUNNING_STATUS:
            return 'R'
        elif output==QUEUE_STATUS:
            return 'Q'
        else:
            return 'C'
    except CalledProcessError:
        return ''

def is_traceable_date(jobdate):
    try:
        trace_date = datetime.strptime(jobdate,"%Y-%m-%d")
        diff_days = (datetime.today() - trace_date).days
        return (diff_days <= MAX_TRACE_DAYS)
    except ValueError:
        return False

def get_specific_str(big_str,prefix,suffix):
    specific_str = big_str
    if prefix and len(specific_str.split(prefix))>1:
        specific_str = specific_str.split(prefix)[1]
    if suffix and len(specific_str.split(suffix))>1:
        specific_str = specific_str.split(suffix)[0]
    if specific_str!=big_str:
        return specific_str
    else:
        return ''

def tracejob_info(jobid, jobdate):
    d = datetime.strptime(jobdate, "%Y-%m-%d")
    diff_days = (datetime.today() - d).days + 1
    jobinfo = {'mem_used' : '', 'walltime_used' : ''}

    cmd = CMD_GET_JOB_DONE_INFO.safe_substitute(**{'numberofdays':diff_days,'jobid':jobid})
    try:
        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
        if EXIT_STATUS and EXIT_STATUS in output:
            #get the walltime used
            jobinfo['walltime_used'] = get_specific_str(output,PREFIX_WALLTIME,SUFFIX_WALLTIME)
            #get the mem used
            jobinfo['mem_used'] = get_specific_str(output,PREFIX_MEMORY,SUFFIX_MEMORY)

    except CalledProcessError:
        pass

    if jobinfo['walltime_used'] == '' and diff_days > 3:
        jobinfo['walltime_used'] = 'NotFound'

    return jobinfo

class PBS:
    #constructor
    def __init__(self,filename,outfile,cmds,walltime_str,mem_mb=2048,ppn=1,email=None,email_options='bae'):
        self.filename=filename
        self.outfile=outfile
        self.cmds=cmds
        self.walltime_str=walltime_str
        self.mem_mb=mem_mb
        self.email=email
        self.email_options=email_options
        self.ppn=ppn

    def write(self):
        #pbs_dir
        pbs_dir = os.path.dirname(self.filename)
        if not os.path.exists(pbs_dir):
            os.makedirs(pbs_dir)
        # Write the Bedpost script (default value)
        PBS_data = {'pbs_email': self.email,
                    'pbs_email_options': self.email_options,
                    'pbs_ppn': str(self.ppn),
                    'pbs_walltime': str(self.walltime_str),
                    'pbs_memory': str(self.mem_mb),
                    'pbs_output_file': self.outfile,
                    'pbs_output_file_options': 'oe',
                    'pbs_cmds':'\n'.join(self.cmds)}
        with open(self.filename, 'w') as f:
            f.write(PBS_TEMPLATE.safe_substitute(**PBS_data))

    def submit(self):
        try:
            cmd = CMD_SUBMIT_PBS +' '+ self.filename
            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
            jobid = get_specific_str(output,PREFIX_JOBID,SUFFIX_JOBID)
        except CalledProcessError:
            jobid = '0'

        return jobid.strip()

<commit_msg>Update cluster.py<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

""" cluster.py

Cluster functionality
"""
__copyright__ = 'Copyright 2013 Vanderbilt University. All Rights Reserved'

import subprocess,os
from subprocess import CalledProcessError
from datetime import datetime
from dax_settings import DEFAULT_EMAIL,JOB_TEMPLATE,CMD_SUBMIT,CMD_COUNT_NB_JOBS,CMD_GET_JOB_STATUS,CMD_GET_JOB_DONE_INFO,PREFIX_WALLTIME,SUFFIX_WALLTIME,PREFIX_MEMORY,SUFFIX_MEMORY,EXIT_STATUS,RUNNING_STATUS,QUEUE_STATUS,PREFIX_JOBID,SUFFIX_JOBID

MAX_TRACE_DAYS=30

def count_jobs():
    cmd = CMD_COUNT_NB_JOBS
    try:
        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
        return int(output)
    except (CalledProcessError,ValueError):
        return -1

def job_status(jobid):
    cmd=CMD_GET_JOB_STATUS.safe_substitute(**{'jobid':jobid})
    try:
        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
        output = output.strip()
        if output==RUNNING_STATUS:
            return 'R'
        elif output==QUEUE_STATUS:
            return 'Q'
        else:
            return 'C'
    except CalledProcessError:
        return ''

def is_traceable_date(jobdate):
    try:
        trace_date = datetime.strptime(jobdate,"%Y-%m-%d")
        diff_days = (datetime.today() - trace_date).days
        return (diff_days <= MAX_TRACE_DAYS)
    except ValueError:
        return False

def get_specific_str(big_str,prefix,suffix):
    specific_str = big_str
    if prefix and len(specific_str.split(prefix))>1:
        specific_str = specific_str.split(prefix)[1]
    if suffix and len(specific_str.split(suffix))>1:
        specific_str = specific_str.split(suffix)[0]
    if specific_str!=big_str:
        return specific_str
    else:
        return ''

def tracejob_info(jobid, jobdate):
    d = datetime.strptime(jobdate, "%Y-%m-%d")
    diff_days = (datetime.today() - d).days + 1
    jobinfo = {'mem_used' : '', 'walltime_used' : ''}

    cmd = CMD_GET_JOB_DONE_INFO.safe_substitute(**{'numberofdays':diff_days,'jobid':jobid})
    try:
        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
        if EXIT_STATUS and EXIT_STATUS in output:
            #get the walltime used
            jobinfo['walltime_used'] = get_specific_str(output,PREFIX_WALLTIME,SUFFIX_WALLTIME)
            #get the mem used
            jobinfo['mem_used'] = get_specific_str(output,PREFIX_MEMORY,SUFFIX_MEMORY)

    except CalledProcessError:
        pass

    if jobinfo['walltime_used'] == '' and diff_days > 3:
        jobinfo['walltime_used'] = 'NotFound'

    return jobinfo

class PBS:   #The script file generator class
    #constructor
    def __init__(self,filename,outfile,cmds,walltime_str,mem_mb=2048,ppn=1,email=None,email_options=DEFAULT_EMAIL):
        self.filename=filename
        self.outfile=outfile
        self.cmds=cmds
        self.walltime_str=walltime_str
        self.mem_mb=mem_mb
        self.email=email
        self.email_options=email_options
        self.ppn=ppn

    def write(self):
        #pbs_dir
        job_dir = os.path.dirname(self.filename)
        if not os.path.exists(job_dir):
            os.makedirs(job_dir)
        # Write the Bedpost script (default value)
        JOB_data = {'job_email': self.email,
                    'job_email_options': self.email_options,
                    'job_ppn': str(self.ppn),
                    'job_walltime': str(self.walltime_str),
                    'job_memory': str(self.mem_mb),
                    'job_output_file': self.outfile,
                    'job_output_file_options': 'oe',
                    'job_cmds':'\n'.join(self.cmds)}
        with open(self.filename, 'w') as f:
            f.write(JOB_TEMPLATE.safe_substitute(**JOB_data))

    def submit(self):
        try:
            cmd = CMD_SUBMIT +' '+ self.filename
            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
            jobid = get_specific_str(output,PREFIX_JOBID,SUFFIX_JOBID)
        except CalledProcessError:
            jobid = '0'

        return jobid.strip()

<|endoftext|>


<commit_before>import numpy
import six

from chainer import cuda
from chainer import function
from chainer.utils import type_check

class GetItem(function.Function):

    """Get elements stored in given indicies."""

    def check_type_forward(self, in_types):
        type_check.expect(in_types.size() == 2)

        x_type, t_type = in_types
        type_check.expect(
            x_type.dtype.kind == 'f',
            t_type.dtype.kind == 'i',
            x_type.ndim == 2,
            t_type.ndim == 1,
            x_type.shape[0] == t_type.shape[0],
        )

    def forward_cpu(self, inputs):
        x, t = inputs
        return x[six.moves.range(t.size), t],

    def forward_gpu(self, inputs):
        x, t = inputs
        y = cuda.elementwise(
            'S t, raw T x, int32 n_channel',
            'T y',
            'y = x[i * n_channel + t]',
            'getitem_fwd'
        )(t, x, x.shape[1])
        return y,

    def backward_cpu(self, inputs, grad_outputs):
        x, t = inputs
        gloss = grad_outputs[0]
        gx = numpy.zeros_like(x)
        gx[six.moves.range(t.size), t] = gloss
        return gx, None

    def backward_gpu(self, inputs, grad_outputs):
        x, t = inputs
        gloss = grad_outputs[0]
        gx = cuda.cupy.zeros_like(x)
        gx = cuda.elementwise(
            'S t, T gloss, int32 n_channel',
            'raw T gx',
            'gx[i * n_channel + t] = gloss',
            'getitem_bwd'
        )(t, gloss, x.shape[1], gx)
        return gx, None

def getitem(x, t):
    """Get elements stored in given indicies.

    This function returns ```x[range(t.size), t]```.

    Args:
        x (Variable): Variable storing arrays.
        t (Variable): Variable storing index numbers.

    Returns:
        ~chainer.Variable: Variable that holds ```t```-th element of ```x```.

    """
    return GetItem()(x, t)
<commit_msg>Use choose instead of advanced indexing<commit_after>import numpy
import six

from chainer import cuda
from chainer import function
from chainer.utils import type_check

class GetItem(function.Function):

    """Get elements stored in given indicies."""

    def check_type_forward(self, in_types):
        type_check.expect(in_types.size() == 2)

        x_type, t_type = in_types
        type_check.expect(
            x_type.dtype.kind == 'f',
            t_type.dtype.kind == 'i',
            x_type.ndim == 2,
            t_type.ndim == 1,
            x_type.shape[0] == t_type.shape[0],
        )

    def forward_cpu(self, inputs):
        x, t = inputs
        return t.choose(x.T),

    def forward_gpu(self, inputs):
        x, t = inputs
        y = cuda.elementwise(
            'S t, raw T x, int32 n_channel',
            'T y',
            'y = x[i * n_channel + t]',
            'getitem_fwd'
        )(t, x, x.shape[1])
        return y,

    def backward_cpu(self, inputs, grad_outputs):
        x, t = inputs
        gloss = grad_outputs[0]
        gx = numpy.zeros_like(x)
        gx[six.moves.range(t.size), t] = gloss
        return gx, None

    def backward_gpu(self, inputs, grad_outputs):
        x, t = inputs
        gloss = grad_outputs[0]
        gx = cuda.cupy.zeros_like(x)
        gx = cuda.elementwise(
            'S t, T gloss, int32 n_channel',
            'raw T gx',
            'gx[i * n_channel + t] = gloss',
            'getitem_bwd'
        )(t, gloss, x.shape[1], gx)
        return gx, None

def getitem(x, t):
    """Get elements stored in given indicies.

    This function returns ```x[range(t.size), t]```.

    Args:
        x (Variable): Variable storing arrays.
        t (Variable): Variable storing index numbers.

    Returns:
        ~chainer.Variable: Variable that holds ```t```-th element of ```x```.

    """
    return GetItem()(x, t)
<|endoftext|>


<commit_before>import numpy as np
import pandas as pd
import talib

from zipline.lib.adjusted_array import AdjustedArray
from zipline.pipeline import TermGraph
from zipline.pipeline.data import USEquityPricing
from zipline.pipeline.engine import SimplePipelineEngine
from zipline.pipeline.term import AssetExists
from zipline.pipeline.factors import BollingerBands
from zipline.testing import ExplodingObject, parameter_space
from zipline.testing.fixtures import WithAssetFinder, ZiplineTestCase
from zipline.testing.predicates import assert_equal

class WithTechnicalFactor(WithAssetFinder):
    """ZiplineTestCase fixture for testing technical factors.
    """
    ASSET_FINDER_EQUITY_SIDS = tuple(range(5))
    START_DATE = pd.Timestamp('2014-01-01', tz='utc')

    @classmethod
    def init_class_fixtures(cls):
        super(WithTechnicalFactor, cls).init_class_fixtures()
        cls.ndays = ndays = 24
        cls.nassets = nassets = len(cls.ASSET_FINDER_EQUITY_SIDS)
        cls.dates = dates = pd.date_range(cls.START_DATE, periods=ndays)
        cls.assets = pd.Index(cls.asset_finder.sids)
        cls.engine = SimplePipelineEngine(
            lambda column: ExplodingObject(),
            dates,
            cls.asset_finder,
        )
        cls.asset_exists = exists = np.full((ndays, nassets), True, dtype=bool)
        cls.asset_exists_masked = masked = exists.copy()
        masked[:, -1] = False

    def run_graph(self, graph, initial_workspace, mask_sid):
        initial_workspace.setdefault(
            AssetExists(),
            self.asset_exists_masked if mask_sid else self.asset_exists,
        )
        return self.engine.compute_chunk(
            graph,
            self.dates,
            self.assets,
            initial_workspace,
        )

class BollingerBandsTestCase(WithTechnicalFactor, ZiplineTestCase):
    @classmethod
    def init_class_fixtures(cls):
        super(BollingerBandsTestCase, cls).init_class_fixtures()
        cls._closes = closes = (
            np.arange(cls.ndays, dtype=float)[:, np.newaxis] +
            np.arange(cls.nassets, dtype=float) * 100
        )
        cls._closes_masked = masked = closes.copy()
        masked[:, -1] = np.nan

    def closes(self, masked):
        return self._closes_masked if masked else self._closes

    def expected(self, window_length, k, closes):
        """Compute the expected data (without adjustments) for the given
        window, k, and closes array.

        This uses talib.BBANDS to generate the expected data.
        """
        lower_cols = []
        middle_cols = []
        upper_cols = []
        for n in range(self.nassets):
            try:
                upper, middle, lower = talib.BBANDS(
                    closes[:, n],
                    window_length,
                    k,
                    k,
                )
            except Exception:
                # If the input array is all nan then talib raises an instance
                # of Exception.
                upper, middle, lower = [np.full(self.ndays, np.nan)] * 3

            upper_cols.append(upper)
            middle_cols.append(middle)
            lower_cols.append(lower)

        # Stack all of our uppers, middles, lowers into three 2d arrays
        # whose columns are the sids. After that, slice off only the
        # rows we care about.
        where = np.s_[window_length - 1:]
        uppers = np.column_stack(upper_cols)[where]
        middles = np.column_stack(middle_cols)[where]
        lowers = np.column_stack(lower_cols)[where]
        return uppers, middles, lowers

    @parameter_space(
        window_length={5, 10, 20},
        k={1.5, 2, 2.5},
        mask_sid={True, False},
    )
    def test_bollinger_bands(self, window_length, k, mask_sid):
        closes = self.closes(mask_sid)
        result = self.run_graph(
            TermGraph({
                'f': BollingerBands(
                    window_length=window_length,
                    k=k,
                ),
            }),
            initial_workspace={
                USEquityPricing.close: AdjustedArray(
                    closes,
                    np.full_like(closes, True, dtype=bool),
                    {},
                    np.nan,
                ),
            },
            mask_sid=mask_sid,
        )['f']

        expected_upper, expected_middle, expected_lower = self.expected(
            window_length,
            k,
            closes,
        )

        assert_equal(
            result.upper,
            expected_upper,
        )
        assert_equal(
            result.middle,
            expected_middle,
        )
        assert_equal(
            result.lower,
            expected_lower,
        )
<commit_msg>STY: No need for these to be vertical.<commit_after>import numpy as np
import pandas as pd
import talib

from zipline.lib.adjusted_array import AdjustedArray
from zipline.pipeline import TermGraph
from zipline.pipeline.data import USEquityPricing
from zipline.pipeline.engine import SimplePipelineEngine
from zipline.pipeline.term import AssetExists
from zipline.pipeline.factors import BollingerBands
from zipline.testing import ExplodingObject, parameter_space
from zipline.testing.fixtures import WithAssetFinder, ZiplineTestCase
from zipline.testing.predicates import assert_equal

class WithTechnicalFactor(WithAssetFinder):
    """ZiplineTestCase fixture for testing technical factors.
    """
    ASSET_FINDER_EQUITY_SIDS = tuple(range(5))
    START_DATE = pd.Timestamp('2014-01-01', tz='utc')

    @classmethod
    def init_class_fixtures(cls):
        super(WithTechnicalFactor, cls).init_class_fixtures()
        cls.ndays = ndays = 24
        cls.nassets = nassets = len(cls.ASSET_FINDER_EQUITY_SIDS)
        cls.dates = dates = pd.date_range(cls.START_DATE, periods=ndays)
        cls.assets = pd.Index(cls.asset_finder.sids)
        cls.engine = SimplePipelineEngine(
            lambda column: ExplodingObject(),
            dates,
            cls.asset_finder,
        )
        cls.asset_exists = exists = np.full((ndays, nassets), True, dtype=bool)
        cls.asset_exists_masked = masked = exists.copy()
        masked[:, -1] = False

    def run_graph(self, graph, initial_workspace, mask_sid):
        initial_workspace.setdefault(
            AssetExists(),
            self.asset_exists_masked if mask_sid else self.asset_exists,
        )
        return self.engine.compute_chunk(
            graph,
            self.dates,
            self.assets,
            initial_workspace,
        )

class BollingerBandsTestCase(WithTechnicalFactor, ZiplineTestCase):
    @classmethod
    def init_class_fixtures(cls):
        super(BollingerBandsTestCase, cls).init_class_fixtures()
        cls._closes = closes = (
            np.arange(cls.ndays, dtype=float)[:, np.newaxis] +
            np.arange(cls.nassets, dtype=float) * 100
        )
        cls._closes_masked = masked = closes.copy()
        masked[:, -1] = np.nan

    def closes(self, masked):
        return self._closes_masked if masked else self._closes

    def expected(self, window_length, k, closes):
        """Compute the expected data (without adjustments) for the given
        window, k, and closes array.

        This uses talib.BBANDS to generate the expected data.
        """
        lower_cols = []
        middle_cols = []
        upper_cols = []
        for n in range(self.nassets):
            try:
                upper, middle, lower = talib.BBANDS(
                    closes[:, n],
                    window_length,
                    k,
                    k,
                )
            except Exception:
                # If the input array is all nan then talib raises an instance
                # of Exception.
                upper, middle, lower = [np.full(self.ndays, np.nan)] * 3

            upper_cols.append(upper)
            middle_cols.append(middle)
            lower_cols.append(lower)

        # Stack all of our uppers, middles, lowers into three 2d arrays
        # whose columns are the sids. After that, slice off only the
        # rows we care about.
        where = np.s_[window_length - 1:]
        uppers = np.column_stack(upper_cols)[where]
        middles = np.column_stack(middle_cols)[where]
        lowers = np.column_stack(lower_cols)[where]
        return uppers, middles, lowers

    @parameter_space(
        window_length={5, 10, 20},
        k={1.5, 2, 2.5},
        mask_sid={True, False},
    )
    def test_bollinger_bands(self, window_length, k, mask_sid):
        closes = self.closes(mask_sid)
        result = self.run_graph(
            TermGraph({
                'f': BollingerBands(
                    window_length=window_length,
                    k=k,
                ),
            }),
            initial_workspace={
                USEquityPricing.close: AdjustedArray(
                    closes,
                    np.full_like(closes, True, dtype=bool),
                    {},
                    np.nan,
                ),
            },
            mask_sid=mask_sid,
        )['f']

        expected_upper, expected_middle, expected_lower = self.expected(
            window_length,
            k,
            closes,
        )

        assert_equal(result.upper, expected_upper)
        assert_equal(result.middle, expected_middle)
        assert_equal(result.lower, expected_lower)
<|endoftext|>


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

sign = lambda a: (a>0) - (a<0)

filename = "pdg-SMASH.dat"
pdg_list = []
with open(filename) as fp:
    line = fp.readline()
    while line:
        pdg_list.append(line.split()[0])
        line = fp.readline()
pdg_list = list(set(pdg_list))

pdg_list_final = []
for ipart in pdg_list:
    temp = int(ipart)
    pdg_code_dissected = [int(d) for d in str(abs(temp))]
    if len(pdg_code_dissected) < 3:
        # photon
        continue
    if pdg_code_dissected[-2] > 3 or pdg_code_dissected[-3] > 3:
        # heavy quark mesons or baryons
        continue
    if len(pdg_code_dissected) > 3 and pdg_code_dissected[-4] > 3:
        # heavy quark baryons
        continue
    if len(pdg_code_dissected) > 3 and pdg_code_dissected[-4] != 0:
        # baryons
        pdg_list_final.append(-temp)
    pdg_list_final.append(temp)

for ipart in pdg_list_final:
    print(ipart)
<commit_msg>add some comments in the python script<commit_after>#!/usr/bin/env python

filename = "pdg-SMASH.dat"
pdg_list = []
with open(filename) as fp:
    line = fp.readline()
    while line:
        pdg_list.append(line.split()[0])
        line = fp.readline()
pdg_list = list(set(pdg_list))

pdg_list_final = []
for ipart in pdg_list:
    ipart = int(ipart)
    pdg_code_dissected = [int(d) for d in str(abs(ipart))]

    # here are filters
    if len(pdg_code_dissected) < 3:
        # photon
        continue
    if pdg_code_dissected[-2] > 3 or pdg_code_dissected[-3] > 3:
        # heavy quark mesons or baryons
        continue
    if len(pdg_code_dissected) > 3 and pdg_code_dissected[-4] > 3:
        # heavy quark baryons
        continue

    # passed all the filters, add it to the final pdg list
    pdg_list_final.append(ipart)

    if len(pdg_code_dissected) > 3 and pdg_code_dissected[-4] != 0:
        # it is baryons: we need to add anti-baryons in the final pdg list
        if ipart < 0:
            print("something wrong!")
            exit(1)
        pdg_list_final.append(-ipart)

for ipart in pdg_list_final:
    print(ipart)
<|endoftext|>


<commit_before>"""
    selenium_data_attributes.element
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    This module implements the core object used to create selenium structures.

    :copyright: (c) 2016 FanThreeSixty
    :author: John Lane <jlane@fanthreesixty.com>
    :license: MIT, see LICENSE for more details.
"""

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select as SeleniumSelect
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.common.exceptions import ElementNotVisibleException, WebDriverException, NoSuchElementException, \
    InvalidSelectorException

__author__ = 'jlane'
__copyright__ = 'Copyright (c) 2016 FanThreeSixty'
__license__ = "MIT"
__version__ = '0.3.8'
__contact__ = 'jlane@fanthreesixty.com'
__status__ = 'Alpha'
__docformat__ = 'reStructuredText'

__all__ = ['Element']

class Element(object):
    """Abstract web structure class
    """

    def __init__(self, web_driver, value, by=By.XPATH):
        """Basic Selenium element

        :param web_driver: Selenium webdriver
        :param str by: By selector
        :param str value: selection value
        :return:
        """

        self.driver = web_driver
        self.search_term = (by, value)

    def __contains__(self, attribute):
        """Returns True if element contains attribute

        :param str attribute: Element attribute
        :return: True, if the element contains that attribute
        :rtype: bool
        """

        if self.exists() and isinstance(attribute, str):

            try:

                self.element().find_element_by_xpath('//self::*[@{0}]'.format(attribute))
                return True

            except NoSuchElementException:
                pass

        return False

    def __getattr__(self, attribute):
        """Returns the value of an attribute

        :param str attribute: Element attribute
        :return: Returns the string value
        :rtype: str
        """

        if self.exists():

            if attribute == "cls":
                    attribute = "class"

            attribute = attribute.replace('_', '-')

            return self.element().get_attribute(attribute).encode('ascii', 'ignore')

        return ''

    def __repr__(self):
        """Returns HTML representation of the element

        :return: HTML representation of the element
        :rtype: str
        """

        if self.exists():
            return self.outerHTML

        return ''

    def angular_hidden(self):
        """Returns True if the element is hidden by angular

        :return: True, if the element is hidden by angular
        :rtype: bool
        """

        if 'ng-hide' in self.cls:
            return True

        return False

    def blur(self):
        """Simulate moving the cursor out of focus of this element

        :return:
        """

        if not self.angular_hidden():
            if self.exists():
                self.driver.execute_script('arguments[0].blur();', self.element())

    def element(self):
        """Return the selenium webelement object

        :return: Selenium WebElement
        :rtype: WebElement
        """

        # If the search term passed through was an element
        if self.search_term[0] == 'element' and isinstance(self.search_term[1], WebElement):
            return self.search_term[1]

        # If the search term is a valid term
        elif By.is_valid(self.search_term[0]):

            try:

                # Locate element
                element = self.driver.find_elements(*self.search_term)

            except InvalidSelectorException:
                element = []

            if len(element) > 0:
                return element[0]

        return None

    def _click(self):
        """Click element

        :return:
        """

        if self.exists():

            try:
                self.element().click()

            # If the object is not within the view try to scroll to the element
            except (ElementNotVisibleException, WebDriverException):

                # Scroll to Element
                self._scroll_to()

                try:
                    self.element().click()

                except (ElementNotVisibleException, WebDriverException):
                    pass

    def _deselect_by_index(self, option):
        """Deselect option by index [i]

        :param option: Select option index
        :return: True, if option is deselected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                if isinstance(option, int):

                    select = SeleniumSelect(element)

                    try:
                        select.deselect_by_index(option)
                        return True

                    except NoSuchElementException:
                        pass

                elif isinstance(option, str):

                    if option.isdigit():

                        select = SeleniumSelect(element)

                        try:
                            select.deselect_by_index(int(option))
                            return True

                        except NoSuchElementException:
                            pass

        return False

    def _deselect_by_text(self, option):
        """Deselect option by display text

        :param option: Select option
        :return: True, if option is deselected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select' and isinstance(option, str):

                select = SeleniumSelect(element)

                try:

                    select.deselect_by_visible_text(option)
                    return True

                except NoSuchElementException:
                    pass

        return False

    def _deselect_by_value(self, option):
        """Deselect option by option value

        :param option: Select option value
        :return: True, if option is deselected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select' and isinstance(option, str):

                select = SeleniumSelect(element)

                try:

                    select.deselect_by_value(option)
                    return True

                except NoSuchElementException:
                    pass

        return False

    def _deselect_all(self):
        """Deselect all selected options

        :return: True, if all options are deselected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                select = SeleniumSelect(element)

                try:

                    select.deselect_all()
                    return True

                except NotImplementedError:
                    pass

        return False

    def exists(self):
        """Returns True if element can be located by selenium

        :return: Returns True, if the element can be located
        :rtype: bool
        """

        element = self.element()

        if element:
            return True

        return False

    def focus(self):
        """Simulate element being in focus

        :return:
        """

        if self.angular_hidden():
            if self.exists():
                self.driver.execute_script('arguments[0].focus();', self.element())

    def _input(self, text, clear=True):
        """Send text to a input field

        :param str text: Text to send to the input field
        :param bool clear: True if user wants to clear the field before assigning text
        :return: True, if text is assigned
        :rtype: bool
        """

        if self.exists() and isinstance(text, str):

            element = self.element()

            if clear:
                element.clear()

            element.send_keys(text)

            return True

        return False

    def is_displayed(self):
        """Return True, if the element is visible

        :return: True, if element is visible
        :rtype: bool
        """

        if self.exists():

            return self.element().is_displayed()

        return False

    def _options(self):
        """Returns all Select options

        :return: List of options
        :rtype: list
        """

        if self.exists():

            element = self.element()

            if element.tag_name == u'select':

                select = SeleniumSelect(element)

                options = []

                for option in select.options:
                    options.append(option.text.encode('ascii', 'ignore'))

                return options

        return []

    def _scroll_to(self):
        """Scroll to the location of the element

        :return:
        """

        if self.exists():

            element = self.element()

            # Scroll to Element
            self.driver.execute_script("window.scrollTo(0, %i)" % (element.location['y'] - element.size['height']))

    def _selected(self):
        """Return True if element is selected

        :return: True, if the element is selected
        :rtype: bool
        """

        if self.exists():
            return self.element().is_selected()

        return False

    def _selected_options(self):
        """Returns a list of selected options

        :return: List of options
        :rtype: list
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                select = SeleniumSelect(element)
                options = []

                for option in select.all_selected_options:
                    options.append(option.text.encode('ascii', 'ignore'))

                return options

        return []

    def _selected_first(self):
        """Select first option

        :return:
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                select = SeleniumSelect(element)
                options = select.all_selected_options

                if len(options) > 0:
                    return options[0]

        return None

    def _select_by_index(self, option):
        """Select option at index [i]

        :param int option: Select index
        :return: True, if the option is selected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                if isinstance(option, int):

                    select = SeleniumSelect(element)

                    try:
                        select.select_by_index(option)
                        return True

                    except NoSuchElementException:
                        pass

                elif isinstance(option, str):

                    if option.isdigit():

                        select = SeleniumSelect(element)

                        try:
                            select.select_by_index(int(option))
                            return True

                        except NoSuchElementException:
                            pass

        return False

    def _select_by_text(self, option):
        """Select option by display text

        :param str option: Select option
        :return: True, if the option is selected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select' and isinstance(option, str):

                select = SeleniumSelect(element)

                try:

                    select.select_by_visible_text(option)
                    return True

                except NoSuchElementException:
                    pass

        return False

    def _select_by_value(self, option):
        """Select option by option value

        :param str option: Select option value
        :return: True, if the option is selected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select' and isinstance(option, str):

                select = SeleniumSelect(element)

                try:

                    select.select_by_value(option)
                    return True

                except NoSuchElementException:
                    pass

        return False

    def _text(self):
        """Returns the text within an element

        :return: Element text
        :rtype: str
        """

        if self.exists():

            element = self.element()
            text = element.text.encode('ascii', 'ignore').strip()

            if text == '':
                return self.driver.execute_script('return arguments[0].textContent',
                                                  element).encode('ascii', 'ignore').strip()

            return text

    def wait_until_present(self):
        """Wait until element is present

        :return:
        """

        wait = WebDriverWait(self.driver, 30)
        wait.until(ec.presence_of_element_located((By.XPATH, self.search_term[1])))

    def wait_until_disappears(self):
        """Wait until the element disappears

        :return:
        """

        wait = WebDriverWait(self.driver, 30)
        wait.until(ec.invisibility_of_element_located((By.XPATH, self.search_term[1])))
<commit_msg>Add argument for timeout<commit_after>"""
    selenium_data_attributes.element
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    This module implements the core object used to create selenium structures.

    :copyright: (c) 2016 FanThreeSixty
    :author: John Lane <jlane@fanthreesixty.com>
    :license: MIT, see LICENSE for more details.
"""

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select as SeleniumSelect
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.common.exceptions import ElementNotVisibleException, WebDriverException, NoSuchElementException, \
    InvalidSelectorException

__author__ = 'jlane'
__copyright__ = 'Copyright (c) 2016 FanThreeSixty'
__license__ = "MIT"
__version__ = '0.3.8'
__contact__ = 'jlane@fanthreesixty.com'
__status__ = 'Alpha'
__docformat__ = 'reStructuredText'

__all__ = ['Element']

class Element(object):
    """Abstract web structure class
    """

    def __init__(self, web_driver, value, by=By.XPATH):
        """Basic Selenium element

        :param web_driver: Selenium webdriver
        :param str by: By selector
        :param str value: selection value
        :return:
        """

        self.driver = web_driver
        self.search_term = (by, value)

    def __contains__(self, attribute):
        """Returns True if element contains attribute

        :param str attribute: Element attribute
        :return: True, if the element contains that attribute
        :rtype: bool
        """

        if self.exists() and isinstance(attribute, str):

            try:

                self.element().find_element_by_xpath('//self::*[@{0}]'.format(attribute))
                return True

            except NoSuchElementException:
                pass

        return False

    def __getattr__(self, attribute):
        """Returns the value of an attribute

        :param str attribute: Element attribute
        :return: Returns the string value
        :rtype: str
        """

        if self.exists():

            if attribute == "cls":
                    attribute = "class"

            attribute = attribute.replace('_', '-')

            return self.element().get_attribute(attribute).encode('ascii', 'ignore')

        return ''

    def __repr__(self):
        """Returns HTML representation of the element

        :return: HTML representation of the element
        :rtype: str
        """

        if self.exists():
            return self.outerHTML

        return ''

    def angular_hidden(self):
        """Returns True if the element is hidden by angular

        :return: True, if the element is hidden by angular
        :rtype: bool
        """

        if 'ng-hide' in self.cls:
            return True

        return False

    def blur(self):
        """Simulate moving the cursor out of focus of this element

        :return:
        """

        if not self.angular_hidden():
            if self.exists():
                self.driver.execute_script('arguments[0].blur();', self.element())

    def element(self):
        """Return the selenium webelement object

        :return: Selenium WebElement
        :rtype: WebElement
        """

        # If the search term passed through was an element
        if self.search_term[0] == 'element' and isinstance(self.search_term[1], WebElement):
            return self.search_term[1]

        # If the search term is a valid term
        elif By.is_valid(self.search_term[0]):

            try:

                # Locate element
                element = self.driver.find_elements(*self.search_term)

            except InvalidSelectorException:
                element = []

            if len(element) > 0:
                return element[0]

        return None

    def _click(self):
        """Click element

        :return:
        """

        if self.exists():

            try:
                self.element().click()

            # If the object is not within the view try to scroll to the element
            except (ElementNotVisibleException, WebDriverException):

                # Scroll to Element
                self._scroll_to()

                try:
                    self.element().click()

                except (ElementNotVisibleException, WebDriverException):
                    pass

    def _deselect_by_index(self, option):
        """Deselect option by index [i]

        :param option: Select option index
        :return: True, if option is deselected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                if isinstance(option, int):

                    select = SeleniumSelect(element)

                    try:
                        select.deselect_by_index(option)
                        return True

                    except NoSuchElementException:
                        pass

                elif isinstance(option, str):

                    if option.isdigit():

                        select = SeleniumSelect(element)

                        try:
                            select.deselect_by_index(int(option))
                            return True

                        except NoSuchElementException:
                            pass

        return False

    def _deselect_by_text(self, option):
        """Deselect option by display text

        :param option: Select option
        :return: True, if option is deselected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select' and isinstance(option, str):

                select = SeleniumSelect(element)

                try:

                    select.deselect_by_visible_text(option)
                    return True

                except NoSuchElementException:
                    pass

        return False

    def _deselect_by_value(self, option):
        """Deselect option by option value

        :param option: Select option value
        :return: True, if option is deselected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select' and isinstance(option, str):

                select = SeleniumSelect(element)

                try:

                    select.deselect_by_value(option)
                    return True

                except NoSuchElementException:
                    pass

        return False

    def _deselect_all(self):
        """Deselect all selected options

        :return: True, if all options are deselected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                select = SeleniumSelect(element)

                try:

                    select.deselect_all()
                    return True

                except NotImplementedError:
                    pass

        return False

    def exists(self):
        """Returns True if element can be located by selenium

        :return: Returns True, if the element can be located
        :rtype: bool
        """

        element = self.element()

        if element:
            return True

        return False

    def focus(self):
        """Simulate element being in focus

        :return:
        """

        if self.angular_hidden():
            if self.exists():
                self.driver.execute_script('arguments[0].focus();', self.element())

    def _input(self, text, clear=True):
        """Send text to a input field

        :param str text: Text to send to the input field
        :param bool clear: True if user wants to clear the field before assigning text
        :return: True, if text is assigned
        :rtype: bool
        """

        if self.exists() and isinstance(text, str):

            element = self.element()

            if clear:
                element.clear()

            element.send_keys(text)

            return True

        return False

    def is_displayed(self):
        """Return True, if the element is visible

        :return: True, if element is visible
        :rtype: bool
        """

        if self.exists():

            return self.element().is_displayed()

        return False

    def _options(self):
        """Returns all Select options

        :return: List of options
        :rtype: list
        """

        if self.exists():

            element = self.element()

            if element.tag_name == u'select':

                select = SeleniumSelect(element)

                options = []

                for option in select.options:
                    options.append(option.text.encode('ascii', 'ignore'))

                return options

        return []

    def _scroll_to(self):
        """Scroll to the location of the element

        :return:
        """

        if self.exists():

            element = self.element()

            # Scroll to Element
            self.driver.execute_script("window.scrollTo(0, %i)" % (element.location['y'] - element.size['height']))

    def _selected(self):
        """Return True if element is selected

        :return: True, if the element is selected
        :rtype: bool
        """

        if self.exists():
            return self.element().is_selected()

        return False

    def _selected_options(self):
        """Returns a list of selected options

        :return: List of options
        :rtype: list
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                select = SeleniumSelect(element)
                options = []

                for option in select.all_selected_options:
                    options.append(option.text.encode('ascii', 'ignore'))

                return options

        return []

    def _selected_first(self):
        """Select first option

        :return:
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                select = SeleniumSelect(element)
                options = select.all_selected_options

                if len(options) > 0:
                    return options[0]

        return None

    def _select_by_index(self, option):
        """Select option at index [i]

        :param int option: Select index
        :return: True, if the option is selected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select':

                if isinstance(option, int):

                    select = SeleniumSelect(element)

                    try:
                        select.select_by_index(option)
                        return True

                    except NoSuchElementException:
                        pass

                elif isinstance(option, str):

                    if option.isdigit():

                        select = SeleniumSelect(element)

                        try:
                            select.select_by_index(int(option))
                            return True

                        except NoSuchElementException:
                            pass

        return False

    def _select_by_text(self, option):
        """Select option by display text

        :param str option: Select option
        :return: True, if the option is selected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select' and isinstance(option, str):

                select = SeleniumSelect(element)

                try:

                    select.select_by_visible_text(option)
                    return True

                except NoSuchElementException:
                    pass

        return False

    def _select_by_value(self, option):
        """Select option by option value

        :param str option: Select option value
        :return: True, if the option is selected
        :rtype: bool
        """

        element = self.element()

        if element:

            if element.tag_name == u'select' and isinstance(option, str):

                select = SeleniumSelect(element)

                try:

                    select.select_by_value(option)
                    return True

                except NoSuchElementException:
                    pass

        return False

    def _text(self):
        """Returns the text within an element

        :return: Element text
        :rtype: str
        """

        if self.exists():

            element = self.element()
            text = element.text.encode('ascii', 'ignore').strip()

            if text == '':
                return self.driver.execute_script('return arguments[0].textContent',
                                                  element).encode('ascii', 'ignore').strip()

            return text

    def wait_until_present(self, timeout=30):
        """Wait until the element is present

        :param timeout: Wait timeout in seconds
        :return:
        """

        if isinstance(timeout, int):
            wait = WebDriverWait(self.driver, timeout)

        else:
            wait = WebDriverWait(self.driver, 30)

        wait.until(ec.presence_of_element_located((By.XPATH, self.search_term[1])))

    def wait_until_disappears(self, timeout=30):
        """Wait until the element disappears

        :param timeout: Wait timeout in seconds
        :return:
        """

        if isinstance(timeout, int):
            wait = WebDriverWait(self.driver, timeout)

        else:
            wait = WebDriverWait(self.driver, 30)

        wait.until(ec.invisibility_of_element_located((By.XPATH, self.search_term[1])))
<|endoftext|>


<commit_before>from collections import namedtuple
import pprint
from enum import Enum

class Direction(Enum):
    NO_SIDE = 0
    LEFT = 1
    RIGHT = 2
    TOP = 3
    BOTTOM = 4

# Track (aka Channel) is a wire that runs from one position to another along X or Y axis
Track = namedtuple('Track', 'direction x_low x_high y_low y_high')

def print_tracks(tracks):
    pprint.pprint(tracks)

def make_tracks(xs, ys, points, grid_width=None, grid_height=None):
    """ Give a list of xs columns and ys rows and points, return a list of
        Track's and connections between the tracks.

        An assert will fail if each point in the point list is not covered by
        a column in xs or a row in ys.

        Connections will be models as indicies into the track list.

        Return:
        [Track], [(index into track list, index into track list)]

    >>> pos = [
    ... (1,1),        (3,1),
    ... (1,2), (2,2), (3,2),
    ... (1,3),        (3,3),
    ... (1,4), (2,4), (3,4),
    ... (1,5),        (3,5),
    ... ]
    >>> xs = [1, 3]
    >>> ys = [2, 4]
    >>> tracks, connections = make_tracks(xs, ys, pos)
    >>> print_tracks(tracks)
    [Track(direction='Y', x_low=1, x_high=1, y_low=1, y_high=5),
     Track(direction='Y', x_low=3, x_high=3, y_low=1, y_high=5),
     Track(direction='X', x_low=1, x_high=3, y_low=2, y_high=2),
     Track(direction='X', x_low=1, x_high=3, y_low=4, y_high=4)]
    >>> print(sorted(connections))
    [(2, 0), (2, 1), (3, 0)]

    >>> pos = [
    ... (68,48), (69,48),
    ... (68,49), (69,49),
    ...          (69,50),
    ...          (69,51),
    ...          (69,52),
    ...          (69,53), (70,53), (71,53), (72,53)]
    >>> xs = [68, 69]
    >>> ys = [53]
    >>> tracks, connections = make_tracks(xs, ys, pos)
    >>> print_tracks(tracks)
    [Track(direction='Y', x_low=68, x_high=68, y_low=48, y_high=53),
     Track(direction='Y', x_low=69, x_high=69, y_low=48, y_high=53),
     Track(direction='X', x_low=68, x_high=72, y_low=53, y_high=53)]
    >>> print(connections)
    [(2, 0), (2, 1)]

    """
    x_set = set(xs)
    y_set = set(ys)

    for x, y in points:
        if x > 0:
            in_x_set = x in x_set or x - 1 in x_set, (x, x_set)
        else:
            in_x_set = x in x_set

        if y > 0:
            in_y_set = y in y_set or y - 1 in y_set, (y, y_set)
        else:
            in_y_set = y in y_set

        assert in_x_set or in_y_set

    all_xs, all_ys = zip(*points)
    x_min = min(all_xs)
    x_max = max(all_xs)
    y_min = min(all_ys)
    y_max = max(all_ys)

    tracks = []
    x_tracks = []
    y_tracks = []
    for x in xs:
        y_low = max(y_min, 1)
        y_high = y_max
        if grid_height is not None:
            y_high = min(y_max, grid_height - 2)

        tracks.append(
            Track(
                direction='Y',
                x_low=x,
                x_high=x,
                y_low=y_low,
                y_high=y_high,
            )
        )
        y_tracks.append(len(tracks) - 1)

    for y in ys:
        x_low = max(x_min, 1)
        x_high = x_max
        if grid_width is not None:
            x_high = min(x_high, grid_width - 2)

        tracks.append(
            Track(
                direction='X',
                x_low=x_low,
                x_high=x_high,
                y_low=y,
                y_high=y,
            )
        )
        x_tracks.append(len(tracks) - 1)

    if len(tracks) == 1:
        return tracks, []

    # If there is more than 1 track, there must be a track in each dimension
    assert len(xs) >= 1 and len(ys) >= 1

    connections = set()

    # Always just connect X tracks to the first Y track, and Y tracks to the
    # first X tracks.
    #
    # To dedup connections, the x channel track will appear first in the
    # connection list.
    for idx, track in enumerate(tracks):
        if track.direction == 'X':
            connections.add((idx, y_tracks[0]))
        else:
            assert track.direction == 'Y'
            connections.add((x_tracks[0], idx))

    return tracks, list(connections)

class Tracks(object):
    """Tracks groups tracks and their connections (AKA Node).
    """

    def __init__(self, tracks, track_connections):
        self.tracks = tracks
        self.track_connections = track_connections

        self.track_cache = {}

    def verify_tracks(self):
        """ Verify that all tracks are connected to all other tracks. """
        track_connections = {}

        for idx, _ in enumerate(self.tracks):
            track_connections[idx] = set((idx, ))

        for conn_a, conn_b in self.track_connections:
            if track_connections[conn_a] is track_connections[conn_b]:
                continue

            assert self.tracks[conn_a].direction != self.tracks[conn_b
                                                                ].direction

            track_connections[conn_a] |= track_connections[conn_b]

            for track_idx in track_connections[conn_a]:
                track_connections[track_idx] = track_connections[conn_a]

        assert len(
            set(id(s) for s in track_connections.values())
        ) == 1, track_connections

    def is_wire_adjacent_to_track(self, idx, coord):
        """returns direction if wire at coord is adjacent to track at index idx
        returns NO_SIDE if not adjacent.
        """
        track = self.tracks[idx]
        wire_x, wire_y = coord

        if track.direction == 'X':
            pin_top = track.y_low == wire_y
            pin_bottom = track.y_low == wire_y - 1
            adjacent_channel = (pin_top or pin_bottom) and (
                track.x_low <= wire_x and wire_x <= track.x_high
            )

            if adjacent_channel:
                if pin_top:
                    return Direction.TOP
                elif pin_bottom:
                    return Direction.BOTTOM
                else:
                    assert False, (coord, track)
            else:
                return Direction.NO_SIDE

        elif track.direction == 'Y':
            pin_right = track.x_low == wire_x
            pin_left = track.x_low == wire_x - 1
            adjacent_channel = (pin_right or pin_left) and (
                track.y_low <= wire_y and wire_y <= track.y_high
            )

            if adjacent_channel:
                if pin_right:
                    return Direction.RIGHT
                elif pin_left:
                    return Direction.LEFT
                else:
                    assert False, (coord, track)
            else:
                return Direction.NO_SIDE
        else:
            assert False, track

    def get_tracks_for_wire_at_coord(self, coord):
        """Returns map of direction to track indicies for valid connections.

        There may be multiple connections to tracks at a particular coordinate,
        this method only returns a possible connection in each direction to
        this track.

        Parameters
        ----------
        coord : (int, int)
            Coordinate to attach to track

        Returns
        -------
        dict(Direction -> int)
            Dictionary of pin direction to track index.

        """

        if coord in self.track_cache:
            return self.track_cache[coord]
        else:
            wire_x, wire_y = coord

            conns = {}
            for idx, track in enumerate(self.tracks):
                pin_dir = self.is_wire_adjacent_to_track(idx, coord)
                if pin_dir != Direction.NO_SIDE:
                    conns[pin_dir] = idx

            self.track_cache[coord] = conns
            return conns

def main():
    import doctest

    print('Doctest begin')
    failure_count, test_count = doctest.testmod(optionflags=doctest.ELLIPSIS)
    assert test_count > 0
    assert failure_count == 0, "Doctests failed!"
    print('Doctest end')

if __name__ == "__main__":
    main()
<commit_msg>tracks: add missing nodes sides<commit_after>from collections import namedtuple
import pprint
from enum import Enum

class Direction(Enum):
    NO_SIDE = 0
    LEFT = 1
    RIGHT = 2
    TOP = 3
    BOTTOM = 4
    RIGHT_LEFT = 5
    RIGHT_BOTTOM = 6
    RIGHT_BOTTOM_LEFT = 7
    TOP_RIGHT = 8
    TOP_BOTTOM = 9
    TOP_LEFT = 10
    TOP_RIGHT_BOTTOM = 11
    TOP_RIGHT_LEFT = 12
    TOP_BOTTOM_LEFT = 13
    TOP_RIGHT_BOTTOM_LEFT = 14
    BOTTOM_LEFT = 15

# Track (aka Channel) is a wire that runs from one position to another along X or Y axis
Track = namedtuple('Track', 'direction x_low x_high y_low y_high')

def print_tracks(tracks):
    pprint.pprint(tracks)

def make_tracks(xs, ys, points, grid_width=None, grid_height=None):
    """ Give a list of xs columns and ys rows and points, return a list of
        Track's and connections between the tracks.

        An assert will fail if each point in the point list is not covered by
        a column in xs or a row in ys.

        Connections will be models as indicies into the track list.

        Return:
        [Track], [(index into track list, index into track list)]

    >>> pos = [
    ... (1,1),        (3,1),
    ... (1,2), (2,2), (3,2),
    ... (1,3),        (3,3),
    ... (1,4), (2,4), (3,4),
    ... (1,5),        (3,5),
    ... ]
    >>> xs = [1, 3]
    >>> ys = [2, 4]
    >>> tracks, connections = make_tracks(xs, ys, pos)
    >>> print_tracks(tracks)
    [Track(direction='Y', x_low=1, x_high=1, y_low=1, y_high=5),
     Track(direction='Y', x_low=3, x_high=3, y_low=1, y_high=5),
     Track(direction='X', x_low=1, x_high=3, y_low=2, y_high=2),
     Track(direction='X', x_low=1, x_high=3, y_low=4, y_high=4)]
    >>> print(sorted(connections))
    [(2, 0), (2, 1), (3, 0)]

    >>> pos = [
    ... (68,48), (69,48),
    ... (68,49), (69,49),
    ...          (69,50),
    ...          (69,51),
    ...          (69,52),
    ...          (69,53), (70,53), (71,53), (72,53)]
    >>> xs = [68, 69]
    >>> ys = [53]
    >>> tracks, connections = make_tracks(xs, ys, pos)
    >>> print_tracks(tracks)
    [Track(direction='Y', x_low=68, x_high=68, y_low=48, y_high=53),
     Track(direction='Y', x_low=69, x_high=69, y_low=48, y_high=53),
     Track(direction='X', x_low=68, x_high=72, y_low=53, y_high=53)]
    >>> print(connections)
    [(2, 0), (2, 1)]

    """
    x_set = set(xs)
    y_set = set(ys)

    for x, y in points:
        if x > 0:
            in_x_set = x in x_set or x - 1 in x_set, (x, x_set)
        else:
            in_x_set = x in x_set

        if y > 0:
            in_y_set = y in y_set or y - 1 in y_set, (y, y_set)
        else:
            in_y_set = y in y_set

        assert in_x_set or in_y_set

    all_xs, all_ys = zip(*points)
    x_min = min(all_xs)
    x_max = max(all_xs)
    y_min = min(all_ys)
    y_max = max(all_ys)

    tracks = []
    x_tracks = []
    y_tracks = []
    for x in xs:
        y_low = max(y_min, 1)
        y_high = y_max
        if grid_height is not None:
            y_high = min(y_max, grid_height - 2)

        tracks.append(
            Track(
                direction='Y',
                x_low=x,
                x_high=x,
                y_low=y_low,
                y_high=y_high,
            )
        )
        y_tracks.append(len(tracks) - 1)

    for y in ys:
        x_low = max(x_min, 1)
        x_high = x_max
        if grid_width is not None:
            x_high = min(x_high, grid_width - 2)

        tracks.append(
            Track(
                direction='X',
                x_low=x_low,
                x_high=x_high,
                y_low=y,
                y_high=y,
            )
        )
        x_tracks.append(len(tracks) - 1)

    if len(tracks) == 1:
        return tracks, []

    # If there is more than 1 track, there must be a track in each dimension
    assert len(xs) >= 1 and len(ys) >= 1

    connections = set()

    # Always just connect X tracks to the first Y track, and Y tracks to the
    # first X tracks.
    #
    # To dedup connections, the x channel track will appear first in the
    # connection list.
    for idx, track in enumerate(tracks):
        if track.direction == 'X':
            connections.add((idx, y_tracks[0]))
        else:
            assert track.direction == 'Y'
            connections.add((x_tracks[0], idx))

    return tracks, list(connections)

class Tracks(object):
    """Tracks groups tracks and their connections (AKA Node).
    """

    def __init__(self, tracks, track_connections):
        self.tracks = tracks
        self.track_connections = track_connections

        self.track_cache = {}

    def verify_tracks(self):
        """ Verify that all tracks are connected to all other tracks. """
        track_connections = {}

        for idx, _ in enumerate(self.tracks):
            track_connections[idx] = set((idx, ))

        for conn_a, conn_b in self.track_connections:
            if track_connections[conn_a] is track_connections[conn_b]:
                continue

            assert self.tracks[conn_a].direction != self.tracks[conn_b
                                                                ].direction

            track_connections[conn_a] |= track_connections[conn_b]

            for track_idx in track_connections[conn_a]:
                track_connections[track_idx] = track_connections[conn_a]

        assert len(
            set(id(s) for s in track_connections.values())
        ) == 1, track_connections

    def is_wire_adjacent_to_track(self, idx, coord):
        """returns direction if wire at coord is adjacent to track at index idx
        returns NO_SIDE if not adjacent.
        """
        track = self.tracks[idx]
        wire_x, wire_y = coord

        if track.direction == 'X':
            pin_top = track.y_low == wire_y
            pin_bottom = track.y_low == wire_y - 1
            adjacent_channel = (pin_top or pin_bottom) and (
                track.x_low <= wire_x and wire_x <= track.x_high
            )

            if adjacent_channel:
                if pin_top:
                    return Direction.TOP
                elif pin_bottom:
                    return Direction.BOTTOM
                else:
                    assert False, (coord, track)
            else:
                return Direction.NO_SIDE

        elif track.direction == 'Y':
            pin_right = track.x_low == wire_x
            pin_left = track.x_low == wire_x - 1
            adjacent_channel = (pin_right or pin_left) and (
                track.y_low <= wire_y and wire_y <= track.y_high
            )

            if adjacent_channel:
                if pin_right:
                    return Direction.RIGHT
                elif pin_left:
                    return Direction.LEFT
                else:
                    assert False, (coord, track)
            else:
                return Direction.NO_SIDE
        else:
            assert False, track

    def get_tracks_for_wire_at_coord(self, coord):
        """Returns map of direction to track indicies for valid connections.

        There may be multiple connections to tracks at a particular coordinate,
        this method only returns a possible connection in each direction to
        this track.

        Parameters
        ----------
        coord : (int, int)
            Coordinate to attach to track

        Returns
        -------
        dict(Direction -> int)
            Dictionary of pin direction to track index.

        """

        if coord in self.track_cache:
            return self.track_cache[coord]
        else:
            wire_x, wire_y = coord

            conns = {}
            for idx, track in enumerate(self.tracks):
                pin_dir = self.is_wire_adjacent_to_track(idx, coord)
                if pin_dir != Direction.NO_SIDE:
                    conns[pin_dir] = idx

            self.track_cache[coord] = conns
            return conns

def main():
    import doctest

    print('Doctest begin')
    failure_count, test_count = doctest.testmod(optionflags=doctest.ELLIPSIS)
    assert test_count > 0
    assert failure_count == 0, "Doctests failed!"
    print('Doctest end')

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


<commit_before><commit_msg>[IMP] speed improvement, no double None in _fields_triggers<commit_after><|endoftext|>


<commit_before># ##### BEGIN GPL LICENSE BLOCK #####
#
#  JewelCraft jewelry design toolkit for Blender.
#  Copyright (C) 2015-2021  Mikhail Rachinskiy
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####

import os

import bpy
from bpy.types import Operator
from bpy.props import EnumProperty, BoolProperty, StringProperty

from .. import var

class WM_OT_design_report(Operator):
    bl_label = "Save Design Report"
    bl_description = "Present summary information about the design, including gems, sizes and weight"
    bl_idname = "wm.jewelcraft_design_report"

    lang: EnumProperty(
        name="Report Language",
        description="Report language",
        items=(
            ("AUTO", "Auto (Auto)", "Use user preferences language setting"),
            ("ar_EG", "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", ""),
            ("en_US", "English (English)", ""),
            ("es", "Spanish (Español)", ""),
            ("fr_FR", "French (Français)", ""),
            ("it_IT", "Italian (Italiano)", ""),
            ("ru_RU", "Russian (Русский)", ""),
            ("zh_CN", "Simplified Chinese (简体中文)", ""),
        ),
    )
    show_warnings: BoolProperty(
        name="Warnings",
        default=True,
    )
    filepath: StringProperty(
        subtype="FILE_PATH",
        options={"SKIP_SAVE", "HIDDEN"},
    )
    first_run: BoolProperty(default=True, options={"HIDDEN"})

    def draw(self, context):
        layout = self.layout
        layout.use_property_split = True
        layout.use_property_decorate = False

        layout.prop(self, "lang")
        layout.prop(self, "show_warnings")

    def execute(self, context):
        import webbrowser
        from ..lib import gettext
        from . import report_get, report_fmt, html_doc

        Report = report_get.data_collect(show_warnings=self.show_warnings)

        if Report.is_empty():
            self.report({"ERROR"}, "Nothing to report")
            return {"CANCELLED"}

        _gettext = gettext.GetText(self.lang).gettext
        report_fmt.data_format(Report, _gettext)
        doc = html_doc.make(Report, self.filename, _gettext)

        with open(self.filepath, "w", encoding="utf-8") as file:
            file.write(doc)
            webbrowser.open(self.filepath)

        return {"FINISHED"}

    def invoke(self, context, event):
        if self.first_run:
            self.first_run = False
            prefs = context.preferences.addons[var.ADDON_ID].preferences
            self.lang = prefs.design_report_lang

        if bpy.data.is_saved:
            self.filename = os.path.splitext(os.path.basename(bpy.data.filepath))[0] + " Report"
            self.filepath = os.path.join(os.path.dirname(bpy.data.filepath), self.filename + ".html")
        else:
            self.filename = "Design Report"
            self.filepath = os.path.join(os.path.expanduser("~"), "Design Report.html")

        if event.ctrl or not bpy.data.is_saved:
            wm = context.window_manager
            wm.fileselect_add(self)
            return {"RUNNING_MODAL"}

        return self.execute(context)
<commit_msg>Design Report: os > pathlib<commit_after># ##### BEGIN GPL LICENSE BLOCK #####
#
#  JewelCraft jewelry design toolkit for Blender.
#  Copyright (C) 2015-2021  Mikhail Rachinskiy
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# ##### END GPL LICENSE BLOCK #####

from pathlib import Path

import bpy
from bpy.types import Operator
from bpy.props import EnumProperty, BoolProperty, StringProperty

from .. import var

class WM_OT_design_report(Operator):
    bl_label = "Save Design Report"
    bl_description = "Present summary information about the design, including gems, sizes and weight"
    bl_idname = "wm.jewelcraft_design_report"

    lang: EnumProperty(
        name="Report Language",
        description="Report language",
        items=(
            ("AUTO", "Auto (Auto)", "Use user preferences language setting"),
            ("ar_EG", "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", ""),
            ("en_US", "English (English)", ""),
            ("es", "Spanish (Español)", ""),
            ("fr_FR", "French (Français)", ""),
            ("it_IT", "Italian (Italiano)", ""),
            ("ru_RU", "Russian (Русский)", ""),
            ("zh_CN", "Simplified Chinese (简体中文)", ""),
        ),
    )
    show_warnings: BoolProperty(
        name="Warnings",
        default=True,
    )
    filepath: StringProperty(
        subtype="FILE_PATH",
        options={"SKIP_SAVE", "HIDDEN"},
    )
    first_run: BoolProperty(default=True, options={"HIDDEN"})

    def draw(self, context):
        layout = self.layout
        layout.use_property_split = True
        layout.use_property_decorate = False

        layout.prop(self, "lang")
        layout.prop(self, "show_warnings")

    def execute(self, context):
        import webbrowser
        from ..lib import gettext
        from . import report_get, report_fmt, html_doc

        Report = report_get.data_collect(show_warnings=self.show_warnings)

        if Report.is_empty():
            self.report({"ERROR"}, "Nothing to report")
            return {"CANCELLED"}

        _gettext = gettext.GetText(self.lang).gettext
        report_fmt.data_format(Report, _gettext)
        doc = html_doc.make(Report, self.filename, _gettext)

        with open(self.filepath, "w", encoding="utf-8") as file:
            file.write(doc)
            webbrowser.open(self.filepath)

        return {"FINISHED"}

    def invoke(self, context, event):
        if self.first_run:
            self.first_run = False
            prefs = context.preferences.addons[var.ADDON_ID].preferences
            self.lang = prefs.design_report_lang

        if bpy.data.is_saved:
            blend_path = Path(bpy.data.filepath)
            self.filename = blend_path.stem + " Report"
            self.filepath = str(blend_path.parent / (self.filename + ".html"))
        else:
            self.filename = "Design Report"
            self.filepath = str(Path.home() / "Design Report.html")

        if event.ctrl or not bpy.data.is_saved:
            wm = context.window_manager
            wm.fileselect_add(self)
            return {"RUNNING_MODAL"}

        return self.execute(context)
<|endoftext|>