mirror of
https://github.com/python/cpython.git
synced 2025-10-01 12:52:18 +00:00
Merge 3.5.1rc1 release changes back into main 3.5 branch.
This commit is contained in:
commit
3715cab3cb
9 changed files with 201 additions and 24 deletions
|
@ -1105,6 +1105,29 @@ class TestShutil(unittest.TestCase):
|
||||||
names2 = zf.namelist()
|
names2 = zf.namelist()
|
||||||
self.assertEqual(sorted(names), sorted(names2))
|
self.assertEqual(sorted(names), sorted(names2))
|
||||||
|
|
||||||
|
@requires_zlib
|
||||||
|
@unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
|
||||||
|
@unittest.skipUnless(shutil.which('unzip'),
|
||||||
|
'Need the unzip command to run')
|
||||||
|
def test_unzip_zipfile(self):
|
||||||
|
root_dir, base_dir = self._create_files()
|
||||||
|
base_name = os.path.join(self.mkdtemp(), 'archive')
|
||||||
|
archive = make_archive(base_name, 'zip', root_dir, base_dir)
|
||||||
|
|
||||||
|
# check if ZIP file was created
|
||||||
|
self.assertEqual(archive, base_name + '.zip')
|
||||||
|
self.assertTrue(os.path.isfile(archive))
|
||||||
|
|
||||||
|
# now check the ZIP file using `unzip -t`
|
||||||
|
zip_cmd = ['unzip', '-t', archive]
|
||||||
|
with support.change_cwd(root_dir):
|
||||||
|
try:
|
||||||
|
subprocess.check_output(zip_cmd, stderr=subprocess.STDOUT)
|
||||||
|
except subprocess.CalledProcessError as exc:
|
||||||
|
details = exc.output.decode(errors="replace")
|
||||||
|
msg = "{}\n\n**Unzip Output**\n{}"
|
||||||
|
self.fail(msg.format(exc, details))
|
||||||
|
|
||||||
def test_make_archive(self):
|
def test_make_archive(self):
|
||||||
tmpdir = self.mkdtemp()
|
tmpdir = self.mkdtemp()
|
||||||
base_name = os.path.join(tmpdir, 'archive')
|
base_name = os.path.join(tmpdir, 'archive')
|
||||||
|
|
|
@ -244,6 +244,33 @@ class ElementTreeTest(unittest.TestCase):
|
||||||
self.assertEqual(ET.XML, ET.fromstring)
|
self.assertEqual(ET.XML, ET.fromstring)
|
||||||
self.assertEqual(ET.PI, ET.ProcessingInstruction)
|
self.assertEqual(ET.PI, ET.ProcessingInstruction)
|
||||||
|
|
||||||
|
def test_set_attribute(self):
|
||||||
|
element = ET.Element('tag')
|
||||||
|
|
||||||
|
self.assertEqual(element.tag, 'tag')
|
||||||
|
element.tag = 'Tag'
|
||||||
|
self.assertEqual(element.tag, 'Tag')
|
||||||
|
element.tag = 'TAG'
|
||||||
|
self.assertEqual(element.tag, 'TAG')
|
||||||
|
|
||||||
|
self.assertIsNone(element.text)
|
||||||
|
element.text = 'Text'
|
||||||
|
self.assertEqual(element.text, 'Text')
|
||||||
|
element.text = 'TEXT'
|
||||||
|
self.assertEqual(element.text, 'TEXT')
|
||||||
|
|
||||||
|
self.assertIsNone(element.tail)
|
||||||
|
element.tail = 'Tail'
|
||||||
|
self.assertEqual(element.tail, 'Tail')
|
||||||
|
element.tail = 'TAIL'
|
||||||
|
self.assertEqual(element.tail, 'TAIL')
|
||||||
|
|
||||||
|
self.assertEqual(element.attrib, {})
|
||||||
|
element.attrib = {'a': 'b', 'c': 'd'}
|
||||||
|
self.assertEqual(element.attrib, {'a': 'b', 'c': 'd'})
|
||||||
|
element.attrib = {'A': 'B', 'C': 'D'}
|
||||||
|
self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'})
|
||||||
|
|
||||||
def test_simpleops(self):
|
def test_simpleops(self):
|
||||||
# Basic method sanity checks.
|
# Basic method sanity checks.
|
||||||
|
|
||||||
|
@ -2350,6 +2377,7 @@ class ElementSlicingTest(unittest.TestCase):
|
||||||
self.assertEqual(e[-2].tag, 'a8')
|
self.assertEqual(e[-2].tag, 'a8')
|
||||||
|
|
||||||
self.assertRaises(IndexError, lambda: e[12])
|
self.assertRaises(IndexError, lambda: e[12])
|
||||||
|
self.assertRaises(IndexError, lambda: e[-12])
|
||||||
|
|
||||||
def test_getslice_range(self):
|
def test_getslice_range(self):
|
||||||
e = self._make_elem_with_children(6)
|
e = self._make_elem_with_children(6)
|
||||||
|
@ -2368,12 +2396,17 @@ class ElementSlicingTest(unittest.TestCase):
|
||||||
self.assertEqual(self._elem_tags(e[::3]), ['a0', 'a3', 'a6', 'a9'])
|
self.assertEqual(self._elem_tags(e[::3]), ['a0', 'a3', 'a6', 'a9'])
|
||||||
self.assertEqual(self._elem_tags(e[::8]), ['a0', 'a8'])
|
self.assertEqual(self._elem_tags(e[::8]), ['a0', 'a8'])
|
||||||
self.assertEqual(self._elem_tags(e[1::8]), ['a1', 'a9'])
|
self.assertEqual(self._elem_tags(e[1::8]), ['a1', 'a9'])
|
||||||
|
self.assertEqual(self._elem_tags(e[3::sys.maxsize]), ['a3'])
|
||||||
|
self.assertEqual(self._elem_tags(e[3::sys.maxsize<<64]), ['a3'])
|
||||||
|
|
||||||
def test_getslice_negative_steps(self):
|
def test_getslice_negative_steps(self):
|
||||||
e = self._make_elem_with_children(4)
|
e = self._make_elem_with_children(4)
|
||||||
|
|
||||||
self.assertEqual(self._elem_tags(e[::-1]), ['a3', 'a2', 'a1', 'a0'])
|
self.assertEqual(self._elem_tags(e[::-1]), ['a3', 'a2', 'a1', 'a0'])
|
||||||
self.assertEqual(self._elem_tags(e[::-2]), ['a3', 'a1'])
|
self.assertEqual(self._elem_tags(e[::-2]), ['a3', 'a1'])
|
||||||
|
self.assertEqual(self._elem_tags(e[3::-sys.maxsize]), ['a3'])
|
||||||
|
self.assertEqual(self._elem_tags(e[3::-sys.maxsize-1]), ['a3'])
|
||||||
|
self.assertEqual(self._elem_tags(e[3::-sys.maxsize<<64]), ['a3'])
|
||||||
|
|
||||||
def test_delslice(self):
|
def test_delslice(self):
|
||||||
e = self._make_elem_with_children(4)
|
e = self._make_elem_with_children(4)
|
||||||
|
@ -2400,6 +2433,75 @@ class ElementSlicingTest(unittest.TestCase):
|
||||||
del e[::2]
|
del e[::2]
|
||||||
self.assertEqual(self._subelem_tags(e), ['a1'])
|
self.assertEqual(self._subelem_tags(e), ['a1'])
|
||||||
|
|
||||||
|
def test_setslice_single_index(self):
|
||||||
|
e = self._make_elem_with_children(4)
|
||||||
|
e[1] = ET.Element('b')
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
|
||||||
|
|
||||||
|
e[-2] = ET.Element('c')
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
|
||||||
|
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
e[5] = ET.Element('d')
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
e[-5] = ET.Element('d')
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
|
||||||
|
|
||||||
|
def test_setslice_range(self):
|
||||||
|
e = self._make_elem_with_children(4)
|
||||||
|
e[1:3] = [ET.Element('b%s' % i) for i in range(2)]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'a3'])
|
||||||
|
|
||||||
|
e = self._make_elem_with_children(4)
|
||||||
|
e[1:3] = [ET.Element('b')]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a3'])
|
||||||
|
|
||||||
|
e = self._make_elem_with_children(4)
|
||||||
|
e[1:3] = [ET.Element('b%s' % i) for i in range(3)]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'b2', 'a3'])
|
||||||
|
|
||||||
|
def test_setslice_steps(self):
|
||||||
|
e = self._make_elem_with_children(6)
|
||||||
|
e[1:5:2] = [ET.Element('b%s' % i) for i in range(2)]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'a2', 'b1', 'a4', 'a5'])
|
||||||
|
|
||||||
|
e = self._make_elem_with_children(6)
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
e[1:5:2] = [ET.Element('b')]
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
e[1:5:2] = [ET.Element('b%s' % i) for i in range(3)]
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
e[1:5:2] = []
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3', 'a4', 'a5'])
|
||||||
|
|
||||||
|
e = self._make_elem_with_children(4)
|
||||||
|
e[1::sys.maxsize] = [ET.Element('b')]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
|
||||||
|
e[1::sys.maxsize<<64] = [ET.Element('c')]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
|
||||||
|
|
||||||
|
def test_setslice_negative_steps(self):
|
||||||
|
e = self._make_elem_with_children(4)
|
||||||
|
e[2:0:-1] = [ET.Element('b%s' % i) for i in range(2)]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b1', 'b0', 'a3'])
|
||||||
|
|
||||||
|
e = self._make_elem_with_children(4)
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
e[2:0:-1] = [ET.Element('b')]
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
e[2:0:-1] = [ET.Element('b%s' % i) for i in range(3)]
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
e[2:0:-1] = []
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3'])
|
||||||
|
|
||||||
|
e = self._make_elem_with_children(4)
|
||||||
|
e[1::-sys.maxsize] = [ET.Element('b')]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
|
||||||
|
e[1::-sys.maxsize-1] = [ET.Element('c')]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
|
||||||
|
e[1::-sys.maxsize<<64] = [ET.Element('d')]
|
||||||
|
self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3'])
|
||||||
|
|
||||||
|
|
||||||
class IOTest(unittest.TestCase):
|
class IOTest(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
|
|
@ -22,6 +22,38 @@ class MiscTests(unittest.TestCase):
|
||||||
finally:
|
finally:
|
||||||
data = None
|
data = None
|
||||||
|
|
||||||
|
def test_del_attribute(self):
|
||||||
|
element = cET.Element('tag')
|
||||||
|
|
||||||
|
element.tag = 'TAG'
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del element.tag
|
||||||
|
self.assertEqual(element.tag, 'TAG')
|
||||||
|
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del element.text
|
||||||
|
self.assertIsNone(element.text)
|
||||||
|
element.text = 'TEXT'
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del element.text
|
||||||
|
self.assertEqual(element.text, 'TEXT')
|
||||||
|
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del element.tail
|
||||||
|
self.assertIsNone(element.tail)
|
||||||
|
element.tail = 'TAIL'
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del element.tail
|
||||||
|
self.assertEqual(element.tail, 'TAIL')
|
||||||
|
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del element.attrib
|
||||||
|
self.assertEqual(element.attrib, {})
|
||||||
|
element.attrib = {'A': 'B', 'C': 'D'}
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del element.attrib
|
||||||
|
self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'})
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(cET, 'requires _elementtree')
|
@unittest.skipUnless(cET, 'requires _elementtree')
|
||||||
class TestAliasWorking(unittest.TestCase):
|
class TestAliasWorking(unittest.TestCase):
|
||||||
|
|
|
@ -1444,7 +1444,9 @@ class ZipFile:
|
||||||
arcname += '/'
|
arcname += '/'
|
||||||
zinfo = ZipInfo(arcname, date_time)
|
zinfo = ZipInfo(arcname, date_time)
|
||||||
zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes
|
zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes
|
||||||
if compress_type is None:
|
if isdir:
|
||||||
|
zinfo.compress_type = ZIP_STORED
|
||||||
|
elif compress_type is None:
|
||||||
zinfo.compress_type = self.compression
|
zinfo.compress_type = self.compression
|
||||||
else:
|
else:
|
||||||
zinfo.compress_type = compress_type
|
zinfo.compress_type = compress_type
|
||||||
|
|
|
@ -1518,6 +1518,7 @@ Richard Walker
|
||||||
Larry Wall
|
Larry Wall
|
||||||
Kevin Walzer
|
Kevin Walzer
|
||||||
Rodrigo Steinmuller Wanderley
|
Rodrigo Steinmuller Wanderley
|
||||||
|
Dingyuan Wang
|
||||||
Ke Wang
|
Ke Wang
|
||||||
Greg Ward
|
Greg Ward
|
||||||
Tom Wardill
|
Tom Wardill
|
||||||
|
|
17
Misc/NEWS
17
Misc/NEWS
|
@ -2,6 +2,23 @@
|
||||||
Python News
|
Python News
|
||||||
+++++++++++
|
+++++++++++
|
||||||
|
|
||||||
|
What's New in Python 3.5.2 release candidate 1?
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
Release date: XXXX-XX-XX
|
||||||
|
|
||||||
|
Core and Builtins
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Library
|
||||||
|
-------
|
||||||
|
|
||||||
|
- Issue #25691: Fixed crash on deleting ElementTree.Element attributes.
|
||||||
|
|
||||||
|
- Issue #25624: ZipFile now always writes a ZIP_STORED header for directory
|
||||||
|
entries. Patch by Dingyuan Wang.
|
||||||
|
|
||||||
|
|
||||||
What's New in Python 3.5.1 final?
|
What's New in Python 3.5.1 final?
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
|
|
|
@ -1711,7 +1711,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
|
||||||
Py_ssize_t start, stop, step, slicelen, newlen, cur, i;
|
Py_ssize_t start, stop, step, slicelen, newlen, cur, i;
|
||||||
|
|
||||||
PyObject* recycle = NULL;
|
PyObject* recycle = NULL;
|
||||||
PyObject* seq = NULL;
|
PyObject* seq;
|
||||||
|
|
||||||
if (!self->extra) {
|
if (!self->extra) {
|
||||||
if (create_extra(self, NULL) < 0)
|
if (create_extra(self, NULL) < 0)
|
||||||
|
@ -1790,21 +1790,21 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
|
||||||
Py_XDECREF(recycle);
|
Py_XDECREF(recycle);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/* A new slice is actually being assigned */
|
/* A new slice is actually being assigned */
|
||||||
seq = PySequence_Fast(value, "");
|
seq = PySequence_Fast(value, "");
|
||||||
if (!seq) {
|
if (!seq) {
|
||||||
PyErr_Format(
|
PyErr_Format(
|
||||||
PyExc_TypeError,
|
PyExc_TypeError,
|
||||||
"expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name
|
"expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name
|
||||||
);
|
);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
newlen = PySequence_Size(seq);
|
|
||||||
}
|
}
|
||||||
|
newlen = PySequence_Size(seq);
|
||||||
|
|
||||||
if (step != 1 && newlen != slicelen)
|
if (step != 1 && newlen != slicelen)
|
||||||
{
|
{
|
||||||
|
Py_DECREF(seq);
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"attempt to assign sequence of size %zd "
|
"attempt to assign sequence of size %zd "
|
||||||
"to extended slice of size %zd",
|
"to extended slice of size %zd",
|
||||||
|
@ -1816,9 +1816,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
|
||||||
/* Resize before creating the recycle bin, to prevent refleaks. */
|
/* Resize before creating the recycle bin, to prevent refleaks. */
|
||||||
if (newlen > slicelen) {
|
if (newlen > slicelen) {
|
||||||
if (element_resize(self, newlen - slicelen) < 0) {
|
if (element_resize(self, newlen - slicelen) < 0) {
|
||||||
if (seq) {
|
Py_DECREF(seq);
|
||||||
Py_DECREF(seq);
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1829,9 +1827,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
|
||||||
we're done modifying the element */
|
we're done modifying the element */
|
||||||
recycle = PyList_New(slicelen);
|
recycle = PyList_New(slicelen);
|
||||||
if (!recycle) {
|
if (!recycle) {
|
||||||
if (seq) {
|
Py_DECREF(seq);
|
||||||
Py_DECREF(seq);
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
for (cur = start, i = 0; i < slicelen;
|
for (cur = start, i = 0; i < slicelen;
|
||||||
|
@ -1859,9 +1855,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
|
||||||
|
|
||||||
self->extra->length += newlen - slicelen;
|
self->extra->length += newlen - slicelen;
|
||||||
|
|
||||||
if (seq) {
|
Py_DECREF(seq);
|
||||||
Py_DECREF(seq);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* discard the recycle bin, and everything in it */
|
/* discard the recycle bin, and everything in it */
|
||||||
Py_XDECREF(recycle);
|
Py_XDECREF(recycle);
|
||||||
|
@ -1927,6 +1921,12 @@ static int
|
||||||
element_setattro(ElementObject* self, PyObject* nameobj, PyObject* value)
|
element_setattro(ElementObject* self, PyObject* nameobj, PyObject* value)
|
||||||
{
|
{
|
||||||
char *name = "";
|
char *name = "";
|
||||||
|
|
||||||
|
if (value == NULL) {
|
||||||
|
PyErr_SetString(PyExc_AttributeError,
|
||||||
|
"can't delete attribute");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (PyUnicode_Check(nameobj))
|
if (PyUnicode_Check(nameobj))
|
||||||
name = _PyUnicode_AsString(nameobj);
|
name = _PyUnicode_AsString(nameobj);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
<!-- See Tools/msi/buildrelease.bat for help on configuring the download URL -->
|
<!-- See Tools/msi/buildrelease.bat for help on configuring the download URL -->
|
||||||
<DownloadUrl Condition="'$(DownloadUrl)' == '' and '$(DownloadUrlBase)' != ''">$(DownloadUrlBase.TrimEnd(`/`))/{version}/{arch}{releasename}/{msi}</DownloadUrl>
|
<DownloadUrl Condition="'$(DownloadUrl)' == '' and '$(DownloadUrlBase)' != ''">$(DownloadUrlBase.TrimEnd(`/`))/{version}/{arch}{releasename}/{msi}</DownloadUrl>
|
||||||
<DefineConstants Condition="'$(DownloadUrl)' != ''">$(DefineConstants);DownloadUrl=$(DownloadUrl.Replace(`{version}`, `$(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)`).Replace(`{arch}`, `$(ArchName)`).Replace(`{releasename}`, `$(ReleaseName)`).Replace(`{msi}`, `{2}`))</DefineConstants>
|
<DefineConstants Condition="'$(DownloadUrl)' != ''">$(DefineConstants);DownloadUrl=$(DownloadUrl.Replace(`{version}`, `$(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)`).Replace(`{arch}`, `$(ArchName)`).Replace(`{releasename}`, `$(ReleaseLevelName)`).Replace(`{msi}`, `{2}`))</DefineConstants>
|
||||||
<DefineConstants Condition="'$(DownloadUrl)' == ''">$(DefineConstants);DownloadUrl={2}</DefineConstants>
|
<DefineConstants Condition="'$(DownloadUrl)' == ''">$(DefineConstants);DownloadUrl={2}</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<EXETarget>$(DownloadUrlBase.TrimEnd(`/`))/$(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)</EXETarget>
|
<EXETarget>$(DownloadUrlBase.TrimEnd(`/`))/$(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)</EXETarget>
|
||||||
<MSITarget>$(DownloadUrl.TrimEnd(`/`))</MSITarget>
|
<MSITarget>$(DownloadUrl.Replace(`{version}`, `$(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)`).Replace(`{arch}`, `$(ArchName)`).Replace(`{releasename}`, `$(ReleaseLevelName)`).Replace(`{msi}`, ``).TrimEnd(`/`))</MSITarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue