"""
Package clone provides functions for cloning DNA sequences.

Since 1973, the most common way to make recombinant DNA has been restriction
enzyme cloning (though lately, homologous recombination based methods like
Gibson assembly have attracted a lot of use). The cloning functions here allow
for simulation of restriction enzyme cloning.

For a historical review leading up to the discovery:
https://doi.org/10.1073/pnas.1313397110

The idea of restriction enzyme cloning is that you can cut DNA at specific
locations with restriction enzyme and then glue them back together in different
patterns using ligase. The final product is (99.9% of the time) a circular plasmid
that you can transform into a bacterial cell for propagation.

While simulation is simple for simple cases, there are a lot of edge cases to handle, for example:
  - Which input sequences are circular? How do we handle their rotations?
  - Is the enzyme that is cutting directional? How do we handle that directionality?
  - Are there multiple possible outputs of our ligation reaction? For example, ligations may be
    able to create a "library" of plasmids, in which there are millions of valid combinations.
  - How do we handle sequences that get ligated in multiple orientations?

These cloning functions handle all those problems so that they appear simple to the end user.

In particular, there is a focus here on GoldenGate Assembly:
https://en.wikipedia.org/wiki/Golden_Gate_Cloning
https://www.neb.com/applications/cloning-and-synthetic-biology/dna-assembly-and-cloning/golden-gate-assembly

GoldenGate is a particular kind of restriction enzyme cloning reaction that you can do
in a single tube and that is extraordinarily efficient (up to 50 parts) and is popular
for new modular DNA part toolkits. Users can easily simulate GoldenGate assembly reactions
with just their input fragments + the enzyme name.

Let's build some DNA!

# Keoni

PS: We do NOT (yet) handle restriction enzymes which recognize one site but cut
in multiple places (Type IIG enzymes) such as BcgI.

"""
# python wrapper for package github.com/bebop/poly/clone within overall package poly
# This is what you import to use the package.
# File is generated by gopy. Do not edit.
# gopy pkg -vm=python3 github.com/bebop/poly

# the following is required to enable dlopen to open the _go.so file
import os,sys,inspect,collections
try:
	import collections.abc as _collections_abc
except ImportError:
	_collections_abc = collections

cwd = os.getcwd()
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
os.chdir(currentdir)
from . import _poly
from . import go

os.chdir(cwd)

# to use this code in your end-user python file, import it as follows:
# from poly import clone
# and then refer to everything using clone. prefix
# packages imported by this package listed below:

from . import checks
from . import seqhash
from . import transform



# ---- Types ---

# Python type for slice [][][]byte
class Slice_Slice_Slice_byte(go.GoClass):
	""""""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameter is a python list that we copy from
		"""
		self.index = 0
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.Slice_Slice_Slice_byte_CTor()
			_poly.IncRef(self.handle)
			if len(args) > 0:
				if not isinstance(args[0], _collections_abc.Iterable):
					raise TypeError('Slice_Slice_Slice_byte.__init__ takes a sequence as argument')
				for elt in args[0]:
					self.append(elt)
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		s = 'clone.Slice_Slice_Slice_byte len: ' + str(len(self)) + ' handle: ' + str(self.handle) + ' ['
		if len(self) < 120:
			s += ', '.join(map(str, self)) + ']'
		return s
	def __repr__(self):
		return 'clone.Slice_Slice_Slice_byte([' + ', '.join(map(str, self)) + '])'
	def __len__(self):
		return _poly.Slice_Slice_Slice_byte_len(self.handle)
	def __getitem__(self, key):
		if isinstance(key, slice):
			if key.step == None or key.step == 1:
				st = key.start
				ed = key.stop
				if st == None:
					st = 0
				if ed == None:
					ed = _poly.Slice_Slice_Slice_byte_len(self.handle)
				return Slice_Slice_Slice_byte(handle=_poly.Slice_Slice_Slice_byte_subslice(self.handle, st, ed))
			return [self[ii] for ii in range(*key.indices(len(self)))]
		elif isinstance(key, int):
			if key < 0:
				key += len(self)
			if key < 0 or key >= len(self):
				raise IndexError('slice index out of range')
			return Slice_Slice_byte(handle=_poly.Slice_Slice_Slice_byte_elem(self.handle, key))
		else:
			raise TypeError('slice index invalid type')
	def __setitem__(self, idx, value):
		if idx < 0:
			idx += len(self)
		if idx < len(self):
			_poly.Slice_Slice_Slice_byte_set(self.handle, idx, value.handle)
			return
		raise IndexError('slice index out of range')
	def __iadd__(self, value):
		if not isinstance(value, _collections_abc.Iterable):
			raise TypeError('Slice_Slice_Slice_byte.__iadd__ takes a sequence as argument')
		for elt in value:
			self.append(elt)
		return self
	def __iter__(self):
		self.index = 0
		return self
	def __next__(self):
		if self.index < len(self):
			rv = Slice_Slice_byte(handle=_poly.Slice_Slice_Slice_byte_elem(self.handle, self.index))
			self.index = self.index + 1
			return rv
		raise StopIteration
	def append(self, value):
		_poly.Slice_Slice_Slice_byte_append(self.handle, value.handle)
	def copy(self, src):
		""" copy emulates the go copy function, copying elements into this list from source list, up to min of size of each list """
		mx = min(len(self), len(src))
		for i in range(mx):
			self[i] = src[i]

# Python type for slice [][]byte
class Slice_Slice_byte(go.GoClass):
	""""""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameter is a python list that we copy from
		"""
		self.index = 0
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.Slice_Slice_byte_CTor()
			_poly.IncRef(self.handle)
			if len(args) > 0:
				if not isinstance(args[0], _collections_abc.Iterable):
					raise TypeError('Slice_Slice_byte.__init__ takes a sequence as argument')
				for elt in args[0]:
					self.append(elt)
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		s = 'clone.Slice_Slice_byte len: ' + str(len(self)) + ' handle: ' + str(self.handle) + ' ['
		if len(self) < 120:
			s += ', '.join(map(str, self)) + ']'
		return s
	def __repr__(self):
		return 'clone.Slice_Slice_byte([' + ', '.join(map(str, self)) + '])'
	def __len__(self):
		return _poly.Slice_Slice_byte_len(self.handle)
	def __getitem__(self, key):
		if isinstance(key, slice):
			if key.step == None or key.step == 1:
				st = key.start
				ed = key.stop
				if st == None:
					st = 0
				if ed == None:
					ed = _poly.Slice_Slice_byte_len(self.handle)
				return Slice_Slice_byte(handle=_poly.Slice_Slice_byte_subslice(self.handle, st, ed))
			return [self[ii] for ii in range(*key.indices(len(self)))]
		elif isinstance(key, int):
			if key < 0:
				key += len(self)
			if key < 0 or key >= len(self):
				raise IndexError('slice index out of range')
			return go.Slice_byte(handle=_poly.Slice_Slice_byte_elem(self.handle, key))
		else:
			raise TypeError('slice index invalid type')
	def __setitem__(self, idx, value):
		if idx < 0:
			idx += len(self)
		if idx < len(self):
			_poly.Slice_Slice_byte_set(self.handle, idx, value.handle)
			return
		raise IndexError('slice index out of range')
	def __iadd__(self, value):
		if not isinstance(value, _collections_abc.Iterable):
			raise TypeError('Slice_Slice_byte.__iadd__ takes a sequence as argument')
		for elt in value:
			self.append(elt)
		return self
	def __iter__(self):
		self.index = 0
		return self
	def __next__(self):
		if self.index < len(self):
			rv = go.Slice_byte(handle=_poly.Slice_Slice_byte_elem(self.handle, self.index))
			self.index = self.index + 1
			return rv
		raise StopIteration
	def append(self, value):
		_poly.Slice_Slice_byte_append(self.handle, value.handle)
	def copy(self, src):
		""" copy emulates the go copy function, copying elements into this list from source list, up to min of size of each list """
		mx = min(len(self), len(src))
		for i in range(mx):
			self[i] = src[i]

# Python type for slice [][]int
class Slice_Slice_int(go.GoClass):
	""""""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameter is a python list that we copy from
		"""
		self.index = 0
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.Slice_Slice_int_CTor()
			_poly.IncRef(self.handle)
			if len(args) > 0:
				if not isinstance(args[0], _collections_abc.Iterable):
					raise TypeError('Slice_Slice_int.__init__ takes a sequence as argument')
				for elt in args[0]:
					self.append(elt)
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		s = 'clone.Slice_Slice_int len: ' + str(len(self)) + ' handle: ' + str(self.handle) + ' ['
		if len(self) < 120:
			s += ', '.join(map(str, self)) + ']'
		return s
	def __repr__(self):
		return 'clone.Slice_Slice_int([' + ', '.join(map(str, self)) + '])'
	def __len__(self):
		return _poly.Slice_Slice_int_len(self.handle)
	def __getitem__(self, key):
		if isinstance(key, slice):
			if key.step == None or key.step == 1:
				st = key.start
				ed = key.stop
				if st == None:
					st = 0
				if ed == None:
					ed = _poly.Slice_Slice_int_len(self.handle)
				return Slice_Slice_int(handle=_poly.Slice_Slice_int_subslice(self.handle, st, ed))
			return [self[ii] for ii in range(*key.indices(len(self)))]
		elif isinstance(key, int):
			if key < 0:
				key += len(self)
			if key < 0 or key >= len(self):
				raise IndexError('slice index out of range')
			return go.Slice_int(handle=_poly.Slice_Slice_int_elem(self.handle, key))
		else:
			raise TypeError('slice index invalid type')
	def __setitem__(self, idx, value):
		if idx < 0:
			idx += len(self)
		if idx < len(self):
			_poly.Slice_Slice_int_set(self.handle, idx, value.handle)
			return
		raise IndexError('slice index out of range')
	def __iadd__(self, value):
		if not isinstance(value, _collections_abc.Iterable):
			raise TypeError('Slice_Slice_int.__iadd__ takes a sequence as argument')
		for elt in value:
			self.append(elt)
		return self
	def __iter__(self):
		self.index = 0
		return self
	def __next__(self):
		if self.index < len(self):
			rv = go.Slice_int(handle=_poly.Slice_Slice_int_elem(self.handle, self.index))
			self.index = self.index + 1
			return rv
		raise StopIteration
	def append(self, value):
		_poly.Slice_Slice_int_append(self.handle, value.handle)
	def copy(self, src):
		""" copy emulates the go copy function, copying elements into this list from source list, up to min of size of each list """
		mx = min(len(self), len(src))
		for i in range(mx):
			self[i] = src[i]

# Python type for slice [][]string
class Slice_Slice_string(go.GoClass):
	""""""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameter is a python list that we copy from
		"""
		self.index = 0
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.Slice_Slice_string_CTor()
			_poly.IncRef(self.handle)
			if len(args) > 0:
				if not isinstance(args[0], _collections_abc.Iterable):
					raise TypeError('Slice_Slice_string.__init__ takes a sequence as argument')
				for elt in args[0]:
					self.append(elt)
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		s = 'clone.Slice_Slice_string len: ' + str(len(self)) + ' handle: ' + str(self.handle) + ' ['
		if len(self) < 120:
			s += ', '.join(map(str, self)) + ']'
		return s
	def __repr__(self):
		return 'clone.Slice_Slice_string([' + ', '.join(map(str, self)) + '])'
	def __len__(self):
		return _poly.Slice_Slice_string_len(self.handle)
	def __getitem__(self, key):
		if isinstance(key, slice):
			if key.step == None or key.step == 1:
				st = key.start
				ed = key.stop
				if st == None:
					st = 0
				if ed == None:
					ed = _poly.Slice_Slice_string_len(self.handle)
				return Slice_Slice_string(handle=_poly.Slice_Slice_string_subslice(self.handle, st, ed))
			return [self[ii] for ii in range(*key.indices(len(self)))]
		elif isinstance(key, int):
			if key < 0:
				key += len(self)
			if key < 0 or key >= len(self):
				raise IndexError('slice index out of range')
			return go.Slice_string(handle=_poly.Slice_Slice_string_elem(self.handle, key))
		else:
			raise TypeError('slice index invalid type')
	def __setitem__(self, idx, value):
		if idx < 0:
			idx += len(self)
		if idx < len(self):
			_poly.Slice_Slice_string_set(self.handle, idx, value.handle)
			return
		raise IndexError('slice index out of range')
	def __iadd__(self, value):
		if not isinstance(value, _collections_abc.Iterable):
			raise TypeError('Slice_Slice_string.__iadd__ takes a sequence as argument')
		for elt in value:
			self.append(elt)
		return self
	def __iter__(self):
		self.index = 0
		return self
	def __next__(self):
		if self.index < len(self):
			rv = go.Slice_string(handle=_poly.Slice_Slice_string_elem(self.handle, self.index))
			self.index = self.index + 1
			return rv
		raise StopIteration
	def append(self, value):
		_poly.Slice_Slice_string_append(self.handle, value.handle)
	def copy(self, src):
		""" copy emulates the go copy function, copying elements into this list from source list, up to min of size of each list """
		mx = min(len(self), len(src))
		for i in range(mx):
			self[i] = src[i]

# Python type for slice []clone.Enzyme
class Slice_clone_Enzyme(go.GoClass):
	""""""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameter is a python list that we copy from
		"""
		self.index = 0
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.Slice_clone_Enzyme_CTor()
			_poly.IncRef(self.handle)
			if len(args) > 0:
				if not isinstance(args[0], _collections_abc.Iterable):
					raise TypeError('Slice_clone_Enzyme.__init__ takes a sequence as argument')
				for elt in args[0]:
					self.append(elt)
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		s = 'clone.Slice_clone_Enzyme len: ' + str(len(self)) + ' handle: ' + str(self.handle) + ' ['
		if len(self) < 120:
			s += ', '.join(map(str, self)) + ']'
		return s
	def __repr__(self):
		return 'clone.Slice_clone_Enzyme([' + ', '.join(map(str, self)) + '])'
	def __len__(self):
		return _poly.Slice_clone_Enzyme_len(self.handle)
	def __getitem__(self, key):
		if isinstance(key, slice):
			if key.step == None or key.step == 1:
				st = key.start
				ed = key.stop
				if st == None:
					st = 0
				if ed == None:
					ed = _poly.Slice_clone_Enzyme_len(self.handle)
				return Slice_clone_Enzyme(handle=_poly.Slice_clone_Enzyme_subslice(self.handle, st, ed))
			return [self[ii] for ii in range(*key.indices(len(self)))]
		elif isinstance(key, int):
			if key < 0:
				key += len(self)
			if key < 0 or key >= len(self):
				raise IndexError('slice index out of range')
			return Enzyme(handle=_poly.Slice_clone_Enzyme_elem(self.handle, key))
		else:
			raise TypeError('slice index invalid type')
	def __setitem__(self, idx, value):
		if idx < 0:
			idx += len(self)
		if idx < len(self):
			_poly.Slice_clone_Enzyme_set(self.handle, idx, value.handle)
			return
		raise IndexError('slice index out of range')
	def __iadd__(self, value):
		if not isinstance(value, _collections_abc.Iterable):
			raise TypeError('Slice_clone_Enzyme.__iadd__ takes a sequence as argument')
		for elt in value:
			self.append(elt)
		return self
	def __iter__(self):
		self.index = 0
		return self
	def __next__(self):
		if self.index < len(self):
			rv = Enzyme(handle=_poly.Slice_clone_Enzyme_elem(self.handle, self.index))
			self.index = self.index + 1
			return rv
		raise StopIteration
	def append(self, value):
		_poly.Slice_clone_Enzyme_append(self.handle, value.handle)
	def copy(self, src):
		""" copy emulates the go copy function, copying elements into this list from source list, up to min of size of each list """
		mx = min(len(self), len(src))
		for i in range(mx):
			self[i] = src[i]

# Python type for slice []clone.Fragment
class Slice_clone_Fragment(go.GoClass):
	""""""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameter is a python list that we copy from
		"""
		self.index = 0
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.Slice_clone_Fragment_CTor()
			_poly.IncRef(self.handle)
			if len(args) > 0:
				if not isinstance(args[0], _collections_abc.Iterable):
					raise TypeError('Slice_clone_Fragment.__init__ takes a sequence as argument')
				for elt in args[0]:
					self.append(elt)
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		s = 'clone.Slice_clone_Fragment len: ' + str(len(self)) + ' handle: ' + str(self.handle) + ' ['
		if len(self) < 120:
			s += ', '.join(map(str, self)) + ']'
		return s
	def __repr__(self):
		return 'clone.Slice_clone_Fragment([' + ', '.join(map(str, self)) + '])'
	def __len__(self):
		return _poly.Slice_clone_Fragment_len(self.handle)
	def __getitem__(self, key):
		if isinstance(key, slice):
			if key.step == None or key.step == 1:
				st = key.start
				ed = key.stop
				if st == None:
					st = 0
				if ed == None:
					ed = _poly.Slice_clone_Fragment_len(self.handle)
				return Slice_clone_Fragment(handle=_poly.Slice_clone_Fragment_subslice(self.handle, st, ed))
			return [self[ii] for ii in range(*key.indices(len(self)))]
		elif isinstance(key, int):
			if key < 0:
				key += len(self)
			if key < 0 or key >= len(self):
				raise IndexError('slice index out of range')
			return Fragment(handle=_poly.Slice_clone_Fragment_elem(self.handle, key))
		else:
			raise TypeError('slice index invalid type')
	def __setitem__(self, idx, value):
		if idx < 0:
			idx += len(self)
		if idx < len(self):
			_poly.Slice_clone_Fragment_set(self.handle, idx, value.handle)
			return
		raise IndexError('slice index out of range')
	def __iadd__(self, value):
		if not isinstance(value, _collections_abc.Iterable):
			raise TypeError('Slice_clone_Fragment.__iadd__ takes a sequence as argument')
		for elt in value:
			self.append(elt)
		return self
	def __iter__(self):
		self.index = 0
		return self
	def __next__(self):
		if self.index < len(self):
			rv = Fragment(handle=_poly.Slice_clone_Fragment_elem(self.handle, self.index))
			self.index = self.index + 1
			return rv
		raise StopIteration
	def append(self, value):
		_poly.Slice_clone_Fragment_append(self.handle, value.handle)
	def copy(self, src):
		""" copy emulates the go copy function, copying elements into this list from source list, up to min of size of each list """
		mx = min(len(self), len(src))
		for i in range(mx):
			self[i] = src[i]


#---- Enums from Go (collections of consts with same type) ---


#---- Constants from Go: Python can only ask that you please don't change these! ---


# ---- Global Variables: can only use functions to access ---


# ---- Interfaces ---


# ---- Structs ---

# Python type for struct clone.Overhang
class Overhang(go.GoClass):
	"""Overhang is a struct that represents the ends of a linearized sequence where Enzymes had cut.\n"""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameters can be unnamed in order of field names or named fields
		in which case a new Go object is constructed first
		"""
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.clone_Overhang_CTor()
			_poly.IncRef(self.handle)
			if  0 < len(args):
				self.Length = args[0]
			if "Length" in kwargs:
				self.Length = kwargs["Length"]
			if  1 < len(args):
				self.Position = args[1]
			if "Position" in kwargs:
				self.Position = kwargs["Position"]
			if  2 < len(args):
				self.Forward = args[2]
			if "Forward" in kwargs:
				self.Forward = kwargs["Forward"]
			if  3 < len(args):
				self.RecognitionSitePlusSkipLength = args[3]
			if "RecognitionSitePlusSkipLength" in kwargs:
				self.RecognitionSitePlusSkipLength = kwargs["RecognitionSitePlusSkipLength"]
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.Overhang{'
		first = True
		for v in pr:
			if callable(v[1]):
				continue
			if first:
				first = False
			else:
				sv += ', '
			sv += v[0] + '=' + str(v[1])
		return sv + '}'
	def __repr__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.Overhang ( '
		for v in pr:
			if not callable(v[1]):
				sv += v[0] + '=' + str(v[1]) + ', '
		return sv + ')'
	@property
	def Length(self):
		return _poly.clone_Overhang_Length_Get(self.handle)
	@Length.setter
	def Length(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Overhang_Length_Set(self.handle, value.handle)
		else:
			_poly.clone_Overhang_Length_Set(self.handle, value)
	@property
	def Position(self):
		return _poly.clone_Overhang_Position_Get(self.handle)
	@Position.setter
	def Position(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Overhang_Position_Set(self.handle, value.handle)
		else:
			_poly.clone_Overhang_Position_Set(self.handle, value)
	@property
	def Forward(self):
		return _poly.clone_Overhang_Forward_Get(self.handle)
	@Forward.setter
	def Forward(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Overhang_Forward_Set(self.handle, value.handle)
		else:
			_poly.clone_Overhang_Forward_Set(self.handle, value)
	@property
	def RecognitionSitePlusSkipLength(self):
		return _poly.clone_Overhang_RecognitionSitePlusSkipLength_Get(self.handle)
	@RecognitionSitePlusSkipLength.setter
	def RecognitionSitePlusSkipLength(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Overhang_RecognitionSitePlusSkipLength_Set(self.handle, value.handle)
		else:
			_poly.clone_Overhang_RecognitionSitePlusSkipLength_Set(self.handle, value)

# Python type for struct clone.Part
class Part(go.GoClass):
	"""Part is a simple struct that can carry a circular or linear DNA sequence.\nIn the field of synthetic biology, the term \"DNA Part\" was popularized by\nthe iGEM competition http://parts.igem.org/Main_Page , so we use that term\nhere.\n"""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameters can be unnamed in order of field names or named fields
		in which case a new Go object is constructed first
		"""
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.clone_Part_CTor()
			_poly.IncRef(self.handle)
			if  0 < len(args):
				self.Sequence = args[0]
			if "Sequence" in kwargs:
				self.Sequence = kwargs["Sequence"]
			if  1 < len(args):
				self.Circular = args[1]
			if "Circular" in kwargs:
				self.Circular = kwargs["Circular"]
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.Part{'
		first = True
		for v in pr:
			if callable(v[1]):
				continue
			if first:
				first = False
			else:
				sv += ', '
			sv += v[0] + '=' + str(v[1])
		return sv + '}'
	def __repr__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.Part ( '
		for v in pr:
			if not callable(v[1]):
				sv += v[0] + '=' + str(v[1]) + ', '
		return sv + ')'
	@property
	def Sequence(self):
		return _poly.clone_Part_Sequence_Get(self.handle)
	@Sequence.setter
	def Sequence(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Part_Sequence_Set(self.handle, value.handle)
		else:
			_poly.clone_Part_Sequence_Set(self.handle, value)
	@property
	def Circular(self):
		return _poly.clone_Part_Circular_Get(self.handle)
	@Circular.setter
	def Circular(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Part_Circular_Set(self.handle, value.handle)
		else:
			_poly.clone_Part_Circular_Set(self.handle, value)

# Python type for struct clone.Enzyme
class Enzyme(go.GoClass):
	"""Enzyme is a struct that represents restriction enzymes.\n"""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameters can be unnamed in order of field names or named fields
		in which case a new Go object is constructed first
		"""
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.clone_Enzyme_CTor()
			_poly.IncRef(self.handle)
			if  0 < len(args):
				self.Name = args[0]
			if "Name" in kwargs:
				self.Name = kwargs["Name"]
			if  1 < len(args):
				self.RegexpFor = args[1]
			if "RegexpFor" in kwargs:
				self.RegexpFor = kwargs["RegexpFor"]
			if  2 < len(args):
				self.RegexpRev = args[2]
			if "RegexpRev" in kwargs:
				self.RegexpRev = kwargs["RegexpRev"]
			if  3 < len(args):
				self.Skip = args[3]
			if "Skip" in kwargs:
				self.Skip = kwargs["Skip"]
			if  4 < len(args):
				self.OverheadLength = args[4]
			if "OverheadLength" in kwargs:
				self.OverheadLength = kwargs["OverheadLength"]
			if  5 < len(args):
				self.RecognitionSite = args[5]
			if "RecognitionSite" in kwargs:
				self.RecognitionSite = kwargs["RecognitionSite"]
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.Enzyme{'
		first = True
		for v in pr:
			if callable(v[1]):
				continue
			if first:
				first = False
			else:
				sv += ', '
			sv += v[0] + '=' + str(v[1])
		return sv + '}'
	def __repr__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.Enzyme ( '
		for v in pr:
			if not callable(v[1]):
				sv += v[0] + '=' + str(v[1]) + ', '
		return sv + ')'
	@property
	def Name(self):
		return _poly.clone_Enzyme_Name_Get(self.handle)
	@Name.setter
	def Name(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Enzyme_Name_Set(self.handle, value.handle)
		else:
			_poly.clone_Enzyme_Name_Set(self.handle, value)
	@property
	def RegexpFor(self):
		return go.Ptr_regexp_Regexp(handle=_poly.clone_Enzyme_RegexpFor_Get(self.handle))
	@RegexpFor.setter
	def RegexpFor(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Enzyme_RegexpFor_Set(self.handle, value.handle)
		else:
			raise TypeError("supplied argument type {t} is not a go.GoClass".format(t=type(value)))
	@property
	def RegexpRev(self):
		return go.Ptr_regexp_Regexp(handle=_poly.clone_Enzyme_RegexpRev_Get(self.handle))
	@RegexpRev.setter
	def RegexpRev(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Enzyme_RegexpRev_Set(self.handle, value.handle)
		else:
			raise TypeError("supplied argument type {t} is not a go.GoClass".format(t=type(value)))
	@property
	def Skip(self):
		return _poly.clone_Enzyme_Skip_Get(self.handle)
	@Skip.setter
	def Skip(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Enzyme_Skip_Set(self.handle, value.handle)
		else:
			_poly.clone_Enzyme_Skip_Set(self.handle, value)
	@property
	def OverheadLength(self):
		return _poly.clone_Enzyme_OverheadLength_Get(self.handle)
	@OverheadLength.setter
	def OverheadLength(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Enzyme_OverheadLength_Set(self.handle, value.handle)
		else:
			_poly.clone_Enzyme_OverheadLength_Set(self.handle, value)
	@property
	def RecognitionSite(self):
		return _poly.clone_Enzyme_RecognitionSite_Get(self.handle)
	@RecognitionSite.setter
	def RecognitionSite(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Enzyme_RecognitionSite_Set(self.handle, value.handle)
		else:
			_poly.clone_Enzyme_RecognitionSite_Set(self.handle, value)

# Python type for struct clone.EnzymeManager
class EnzymeManager(go.GoClass):
	"""EnzymeManager manager for Enzymes. Allows for management of enzymes throughout the lifecyle of your\nprogram. EnzymeManager is not safe for concurrent use.\n"""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameters can be unnamed in order of field names or named fields
		in which case a new Go object is constructed first
		"""
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.clone_EnzymeManager_CTor()
			_poly.IncRef(self.handle)
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.EnzymeManager{'
		first = True
		for v in pr:
			if callable(v[1]):
				continue
			if first:
				first = False
			else:
				sv += ', '
			sv += v[0] + '=' + str(v[1])
		return sv + '}'
	def __repr__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.EnzymeManager ( '
		for v in pr:
			if not callable(v[1]):
				sv += v[0] + '=' + str(v[1]) + ', '
		return sv + ')'
	def CutWithEnzymeByName(self, part, directional, name):
		"""CutWithEnzymeByName(object part, bool directional, str name) []object, str
		
		CutWithEnzymeByName cuts a given sequence with an enzyme represented by the
		enzyme's name. It is a convenience wrapper around CutWithEnzyme that
		allows us to specify the enzyme by name.
		"""
		return Slice_clone_Fragment(handle=_poly.clone_EnzymeManager_CutWithEnzymeByName(self.handle, part.handle, directional, name))
	def GetEnzymeByName(self, name):
		"""GetEnzymeByName(str name) object, str
		
		GetEnzymeByName gets the enzyme by it's name. If the enzyme manager does not
		contain an enzyme with the provided name, an error will be returned
		"""
		return Enzyme(handle=_poly.clone_EnzymeManager_GetEnzymeByName(self.handle, name))

# Python type for struct clone.Fragment
class Fragment(go.GoClass):
	"""Fragment is a struct that represents linear DNA sequences with sticky ends.\n"""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameters can be unnamed in order of field names or named fields
		in which case a new Go object is constructed first
		"""
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.clone_Fragment_CTor()
			_poly.IncRef(self.handle)
			if  0 < len(args):
				self.Sequence = args[0]
			if "Sequence" in kwargs:
				self.Sequence = kwargs["Sequence"]
			if  1 < len(args):
				self.ForwardOverhang = args[1]
			if "ForwardOverhang" in kwargs:
				self.ForwardOverhang = kwargs["ForwardOverhang"]
			if  2 < len(args):
				self.ReverseOverhang = args[2]
			if "ReverseOverhang" in kwargs:
				self.ReverseOverhang = kwargs["ReverseOverhang"]
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.Fragment{'
		first = True
		for v in pr:
			if callable(v[1]):
				continue
			if first:
				first = False
			else:
				sv += ', '
			sv += v[0] + '=' + str(v[1])
		return sv + '}'
	def __repr__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'clone.Fragment ( '
		for v in pr:
			if not callable(v[1]):
				sv += v[0] + '=' + str(v[1]) + ', '
		return sv + ')'
	@property
	def Sequence(self):
		return _poly.clone_Fragment_Sequence_Get(self.handle)
	@Sequence.setter
	def Sequence(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Fragment_Sequence_Set(self.handle, value.handle)
		else:
			_poly.clone_Fragment_Sequence_Set(self.handle, value)
	@property
	def ForwardOverhang(self):
		return _poly.clone_Fragment_ForwardOverhang_Get(self.handle)
	@ForwardOverhang.setter
	def ForwardOverhang(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Fragment_ForwardOverhang_Set(self.handle, value.handle)
		else:
			_poly.clone_Fragment_ForwardOverhang_Set(self.handle, value)
	@property
	def ReverseOverhang(self):
		return _poly.clone_Fragment_ReverseOverhang_Get(self.handle)
	@ReverseOverhang.setter
	def ReverseOverhang(self, value):
		if isinstance(value, go.GoClass):
			_poly.clone_Fragment_ReverseOverhang_Set(self.handle, value.handle)
		else:
			_poly.clone_Fragment_ReverseOverhang_Set(self.handle, value)


# ---- Slices ---


# ---- Maps ---


# ---- Constructors ---
def NewEnzymeManager(enzymes):
	"""NewEnzymeManager([]object enzymes) object
	
	NewEnzymeManager creates a new EnzymeManager given some enzymes.
	"""
	return EnzymeManager(handle=_poly.clone_NewEnzymeManager(enzymes.handle))


# ---- Functions ---
def CutWithEnzyme(part, directional, enzyme):
	"""CutWithEnzyme(object part, bool directional, object enzyme) []object"""
	return Slice_clone_Fragment(handle=_poly.clone_CutWithEnzyme(part.handle, directional, enzyme.handle))
def GetBaseRestrictionEnzymes():
	"""GetBaseRestrictionEnzymes() []object"""
	return Slice_clone_Enzyme(handle=_poly.clone_GetBaseRestrictionEnzymes())


