Trees | Indices | Help |
---|
|
1 import re 2 from six.moves.urllib.parse import urlparse 3 4 import flask 5 import wtforms 6 import json 7 8 from flask_wtf.file import FileRequired, FileField 9 from fnmatch import fnmatch 10 11 try: # get rid of deprecation warning with newer flask_wtf 12 from flask_wtf import FlaskForm 13 except ImportError: 14 from flask_wtf import Form as FlaskForm 15 16 from coprs import constants 17 from coprs import helpers 18 from coprs import models 19 from coprs.logic.coprs_logic import CoprsLogic, MockChrootsLogic 20 from coprs.logic.users_logic import UsersLogic 21 from coprs import exceptions 22 23 24 FALSE_VALUES = {False, "false", ""}28 """ 29 Params 30 ------ 31 source_type_text : str 32 name of the source type (scm/pypi/rubygems/git_and_tito/mock_scm) 33 34 Returns 35 ------- 36 BasePackageForm child 37 based on source_type_text input 38 """ 39 if source_type_text == 'scm': 40 return PackageFormScm 41 elif source_type_text == 'pypi': 42 return PackageFormPyPI 43 elif source_type_text == 'rubygems': 44 return PackageFormRubyGems 45 elif source_type_text == 'git_and_tito': 46 return PackageFormTito # deprecated 47 elif source_type_text == 'mock_scm': 48 return PackageFormMock # deprecated 49 elif source_type_text == "custom": 50 return PackageFormCustom 51 else: 52 raise exceptions.UnknownSourceTypeException("Invalid source type")5356 widget = wtforms.widgets.ListWidget(prefix_label=False) 57 option_widget = wtforms.widgets.CheckboxInput()58618163 if not message: 64 message = ("A list of http[s] URLs separated by whitespace characters" 65 " is needed ('{0}' doesn't seem to be a valid URL).") 66 self.message = message6769 urls = field.data.split() 70 for u in urls: 71 if not self.is_url(u): 72 raise wtforms.ValidationError(self.message.format(u))7384 """ Allows also `repo://` schema"""10086 parsed = urlparse(url) 87 if parsed.scheme not in ["http", "https", "copr"]: 88 return False 89 if not parsed.netloc: 90 return False 91 # copr://username/projectname 92 # ^^ schema ^^ netlock ^^ path 93 if parsed.scheme == "copr": 94 # check if projectname missed 95 path_split = parsed.path.split("/") 96 if len(path_split) < 2 or path_split[1] == "": 97 return False 98 99 return True114104 if not message: 105 message = ("URLs must end with .src.rpm, .nosrc.rpm, or .spec" 106 " ('{0}' doesn't seem to be a valid URL).") 107 super(UrlSrpmListValidator, self).__init__(message)108126118 if not message: 119 message = "You can upload only .src.rpm, .nosrc.rpm, and .spec files" 120 self.message = message121129152131 if not message: 132 if group is None: 133 message = "You already have project named '{}'." 134 else: 135 message = "Group {} ".format(group) + "already have project named '{}'." 136 self.message = message 137 if not user: 138 user = flask.g.user 139 self.user = user 140 self.group = group141143 if self.group: 144 existing = CoprsLogic.exists_for_group( 145 self.group, field.data).first() 146 else: 147 existing = CoprsLogic.exists_for_user( 148 self.user, field.data).first() 149 150 if existing and str(existing.id) != form.id.data: 151 raise wtforms.ValidationError(self.message.format(field.data))165156 if not message: 157 message = "Name must contain only letters, digits, underscores, dashes and dots." 158 self.message = message159178169 # Allow it to be truly optional and has None value 170 if not field.data: 171 return 172 173 selected = set(field.data.split()) 174 enabled = set(MockChrootsLogic.active_names()) 175 176 if selected - enabled: 177 raise wtforms.ValidationError("Such chroot is not available: {}".format(", ".join(selected - enabled)))181190 207183 if not message: 184 message = "Project's name can not be just number." 185 self.message = message186210220212 if not value: 213 return '' 214 # Replace every whitespace string with one newline 215 # Formats ideally for html form filling, use replace('\n', ' ') 216 # to get space-separated values or split() to get list 217 result = value.strip() 218 regex = re.compile(r"\s+") 219 return regex.sub(lambda x: '\n', result)223228225 if value: 226 return helpers.PermissionEnum("request") 227 return helpers.PermissionEnum("nothing")231 232 @staticmethod364 365 def validate_mock_chroots_not_empty(self): 366 have_any = False 367 for c in self.chroots_list: 368 if getattr(self, c).data: 369 have_any = True 370 return have_any 371 372 F.chroots_list = MockChrootsLogic.active_names() 373 F.chroots_list.sort() 374 # sets of chroots according to how we should print them in columns 375 F.chroots_sets = {} 376 for ch in F.chroots_list: 377 checkbox_default = False 378 if mock_chroots and ch in [x.name for x in mock_chroots]: 379 checkbox_default = True 380 381 setattr(F, ch, wtforms.BooleanField(ch, default=checkbox_default, false_values=FALSE_VALUES)) 382 if ch[0] in F.chroots_sets: 383 F.chroots_sets[ch[0]].append(ch) 384 else: 385 F.chroots_sets[ch[0]] = [ch] 386 387 return F 388234 class F(FlaskForm): 235 # also use id here, to be able to find out whether user 236 # is updating a copr if so, we don't want to shout 237 # that name already exists 238 id = wtforms.HiddenField() 239 group_id = wtforms.HiddenField() 240 241 name = wtforms.StringField( 242 "Name", 243 validators=[ 244 wtforms.validators.DataRequired(), 245 NameCharactersValidator(), 246 CoprUniqueNameValidator(user=user, group=group), 247 NameNotNumberValidator() 248 ]) 249 250 homepage = wtforms.StringField( 251 "Homepage", 252 validators=[ 253 wtforms.validators.Optional(), 254 wtforms.validators.URL()]) 255 256 contact = wtforms.StringField( 257 "Contact", 258 validators=[ 259 wtforms.validators.Optional(), 260 EmailOrURL()]) 261 262 description = wtforms.TextAreaField("Description") 263 264 instructions = wtforms.TextAreaField("Instructions") 265 266 delete_after_days = wtforms.IntegerField( 267 "Delete after days", 268 validators=[ 269 wtforms.validators.Optional(), 270 wtforms.validators.NumberRange(min=0, max=60), 271 ], 272 render_kw={'disabled': bool(copr and copr.persistent)}) 273 274 repos = wtforms.TextAreaField( 275 "External Repositories", 276 validators=[UrlRepoListValidator()], 277 filters=[StringListFilter()]) 278 279 initial_pkgs = wtforms.TextAreaField( 280 "Initial packages to build", 281 validators=[ 282 UrlListValidator(), 283 UrlSrpmListValidator()], 284 filters=[StringListFilter()]) 285 286 disable_createrepo = wtforms.BooleanField(default=False, 287 label="Create repositories manually", 288 description="""When Fedora is branched from rawhide, the 289 respective chroots for the new branch are automatically 290 created for you (as soon as they are available) as rawhide 291 chroot forks.""", 292 false_values=FALSE_VALUES) 293 294 unlisted_on_hp = wtforms.BooleanField( 295 "Project will not be listed on home page", 296 default=False, 297 false_values=FALSE_VALUES) 298 299 persistent = wtforms.BooleanField( 300 "Protect project and its builds against deletion", 301 description="""Project's builds and the project itself 302 cannot be deleted by any means. This option is set once and 303 for all (this option can not be changed after project is 304 created).""", 305 render_kw={'disabled': bool(copr)}, 306 default=False, false_values=FALSE_VALUES) 307 308 auto_prune = wtforms.BooleanField( 309 "Old builds will be deleted automatically", 310 default=True, false_values=FALSE_VALUES, 311 description="""Build will be deleted only if there is a 312 newer build (with respect to package version) and it is 313 older than 14 days""") 314 315 use_bootstrap_container = wtforms.BooleanField( 316 "Enable mock's use_bootstrap_container experimental feature", 317 description="""This will make the build slower but it has an 318 advantage that the dnf _from_ the given chroot will be used 319 to setup the chroot (otherwise host system dnf and rpm is 320 used)""", 321 default=False, 322 false_values=FALSE_VALUES) 323 324 follow_fedora_branching = wtforms.BooleanField( 325 "Follow Fedora branching", 326 description="""When Fedora is branched from rawhide, the 327 respective chroots for the new branch are automatically 328 created for you (as soon as they are available) as rawhide 329 chroot forks.""", 330 default=True, 331 false_values=FALSE_VALUES) 332 333 # Deprecated, use `enable_net` instead 334 build_enable_net = wtforms.BooleanField( 335 "Enable internet access during builds", 336 default=False, false_values=FALSE_VALUES) 337 338 enable_net = wtforms.BooleanField( 339 "Enable internet access during builds", 340 default=False, false_values=FALSE_VALUES) 341 342 @property 343 def selected_chroots(self): 344 selected = [] 345 for ch in self.chroots_list: 346 if getattr(self, ch).data: 347 selected.append(ch) 348 return selected349 350 def validate(self): 351 if not super(F, self).validate(): 352 return False 353 354 if not self.validate_mock_chroots_not_empty(): 355 self.errors["chroots"] = ["At least one chroot must be selected"] 356 return False 357 358 if self.persistent.data and self.delete_after_days.data: 359 self.delete_after_days.errors.append( 360 "'delete after' can not be combined with persistent") 361 return False 362 363 return True391 verify = wtforms.TextField( 392 "Confirm deleting by typing 'yes'", 393 validators=[ 394 wtforms.validators.DataRequired(), 395 wtforms.validators.Regexp( 396 r"^yes$", 397 message="Type 'yes' - without the quotes, lowercase.") 398 ])399 403404 405 # @TODO jkadlcik - rewrite via BaseBuildFormFactory after fe-dev-cloud is back online 406 -class BuildFormRebuildFactory(object):407 @staticmethod437 438 F.chroots_list = list(map(lambda x: x.name, active_chroots)) 439 F.chroots_list.sort() 440 F.chroots_sets = {} 441 for ch in F.chroots_list: 442 setattr(F, ch, wtforms.BooleanField(ch, default=True, false_values=FALSE_VALUES)) 443 if ch[0] in F.chroots_sets: 444 F.chroots_sets[ch[0]].append(ch) 445 else: 446 F.chroots_sets[ch[0]] = [ch] 447 448 return F 449409 class F(FlaskForm): 410 @property 411 def selected_chroots(self): 412 selected = [] 413 for ch in self.chroots_list: 414 if getattr(self, ch).data: 415 selected.append(ch) 416 return selected417 418 memory_reqs = wtforms.IntegerField( 419 "Memory requirements", 420 validators=[ 421 wtforms.validators.NumberRange( 422 min=constants.MIN_BUILD_MEMORY, 423 max=constants.MAX_BUILD_MEMORY)], 424 default=constants.DEFAULT_BUILD_MEMORY) 425 426 timeout = wtforms.IntegerField( 427 "Timeout", 428 validators=[ 429 wtforms.validators.NumberRange( 430 min=constants.MIN_BUILD_TIMEOUT, 431 max=constants.MAX_BUILD_TIMEOUT)], 432 default=constants.DEFAULT_BUILD_TIMEOUT) 433 434 enable_net = wtforms.BooleanField(false_values=FALSE_VALUES) 435 background = wtforms.BooleanField(false_values=FALSE_VALUES) 436 project_dirname = wtforms.StringField(default=None)452 @staticmethod459454 form = BuildFormRebuildFactory.create_form_cls(active_chroots) 455 form.package_name = wtforms.StringField( 456 "Package name", 457 validators=[wtforms.validators.DataRequired()]) 458 return form462 if not string: 463 return string 464 fields = [x.lstrip().rstrip() for x in string.split(',')] 465 return ', '.join(fields)466469 if field.data: 470 string = field.data 471 fields = [x.lstrip().rstrip() for x in string.split(',')] 472 for field in fields: 473 pattern = r'^[a-z0-9-*]+$' 474 if not re.match(pattern, field): 475 raise wtforms.ValidationError('Pattern "{0}" does not match "{1}"'.format(field, pattern)) 476 477 matched = set() 478 all_chroots = MockChrootsLogic.active_names() 479 for chroot in all_chroots: 480 if fnmatch(chroot, field): 481 matched.add(chroot) 482 483 if not matched: 484 raise wtforms.ValidationError('no chroot matched by pattern "{0}"'.format(field)) 485 486 if matched == all_chroots: 487 raise wtforms.ValidationError('patterns are black-listing all chroots')488491 package_name = wtforms.StringField( 492 "Package name", 493 validators=[wtforms.validators.DataRequired()]) 494 webhook_rebuild = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 495 chroot_blacklist = wtforms.StringField( 496 "Chroot blacklist", 497 filters=[cleanup_chroot_blacklist], 498 validators=[ 499 wtforms.validators.Optional(), 500 validate_chroot_blacklist, 501 ], 502 ) 503 max_builds = wtforms.IntegerField( 504 "Max number of builds", 505 description="""Keep only the specified number of the newest-by-id builds 506 (garbage collector is run daily)""", 507 render_kw={'placeholder': 'Optional - integer, e.g. 10, zero/empty disables'}, 508 validators=[ 509 wtforms.validators.Optional(), 510 wtforms.validators.NumberRange(min=0, max=100)], 511 default=None, 512 )513516 scm_type = wtforms.SelectField( 517 "Type", 518 choices=[("git", "Git"), ("svn", "SVN")], 519 default="git") 520 521 clone_url = wtforms.StringField( 522 "Clone url", 523 validators=[ 524 wtforms.validators.DataRequired(), 525 wtforms.validators.URL()]) 526 527 committish = wtforms.StringField( 528 "Committish", 529 validators=[ 530 wtforms.validators.Optional()]) 531 532 subdirectory = wtforms.StringField( 533 "Subdirectory", 534 validators=[ 535 wtforms.validators.Optional()]) 536 537 spec = wtforms.StringField( 538 "Spec File", 539 validators=[ 540 wtforms.validators.Optional(), 541 wtforms.validators.Regexp( 542 r"^.+\.spec$", 543 message="RPM spec file must end with .spec")]) 544 545 srpm_build_method = wtforms.SelectField( 546 "SRPM build method", 547 choices=[(x, x) for x in ["rpkg", "tito", "tito_test", "make_srpm"]], 548 default="rpkg") 549 550 @property560552 return json.dumps({ 553 "type": self.scm_type.data, 554 "clone_url": self.clone_url.data, 555 "subdirectory": self.subdirectory.data, 556 "committish": self.committish.data, 557 "spec": self.spec.data, 558 "srpm_build_method": self.srpm_build_method.data, 559 })563 pypi_package_name = wtforms.StringField( 564 "PyPI package name", 565 validators=[wtforms.validators.DataRequired()]) 566 567 pypi_package_version = wtforms.StringField( 568 "PyPI package version", 569 validators=[ 570 wtforms.validators.Optional(), 571 ]) 572 573 spec_template = wtforms.SelectField( 574 "Spec template", 575 choices=[ 576 ("", "default"), 577 ("fedora", "fedora"), 578 ("epel7", "epel7"), 579 ("mageia", "mageia"), 580 ("pld", "pld"), 581 ], default="") 582 583 python_versions = MultiCheckboxField( 584 'Build for Python', 585 choices=[ 586 ('3', 'python3'), 587 ('2', 'python2') 588 ], 589 default=['3', '2']) 590 591 @property599593 return json.dumps({ 594 "pypi_package_name": self.pypi_package_name.data, 595 "pypi_package_version": self.pypi_package_version.data, 596 "spec_template": self.spec_template.data, 597 "python_versions": self.python_versions.data 598 })602 gem_name = wtforms.StringField( 603 "Gem Name", 604 validators=[wtforms.validators.DataRequired()]) 605 606 @property611614 """ 615 @deprecated 616 """ 617 git_url = wtforms.StringField( 618 "Git URL", 619 validators=[ 620 wtforms.validators.DataRequired(), 621 wtforms.validators.URL()]) 622 623 git_directory = wtforms.StringField( 624 "Git Directory", 625 validators=[ 626 wtforms.validators.Optional()]) 627 628 git_branch = wtforms.StringField( 629 "Git Branch", 630 validators=[ 631 wtforms.validators.Optional()]) 632 633 tito_test = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 634 635 @property645637 return json.dumps({ 638 "type": 'git', 639 "clone_url": self.git_url.data, 640 "committish": self.git_branch.data, 641 "subdirectory": self.git_directory.data, 642 "spec": '', 643 "srpm_build_method": 'tito_test' if self.tito_test.data else 'tito', 644 })648 """ 649 @deprecated 650 """ 651 scm_type = wtforms.SelectField( 652 "SCM Type", 653 choices=[("git", "Git"), ("svn", "SVN")]) 654 655 scm_url = wtforms.StringField( 656 "SCM URL", 657 validators=[ 658 wtforms.validators.DataRequired(), 659 wtforms.validators.URL()]) 660 661 scm_branch = wtforms.StringField( 662 "Git Branch", 663 validators=[ 664 wtforms.validators.Optional()]) 665 666 scm_subdir = wtforms.StringField( 667 "Subdirectory", 668 validators=[ 669 wtforms.validators.Optional()]) 670 671 spec = wtforms.StringField( 672 "Spec File", 673 validators=[ 674 wtforms.validators.Optional(), 675 wtforms.validators.Regexp( 676 r"^.+\.spec$", 677 message="RPM spec file must end with .spec")]) 678 679 @property689692 """ 693 @deprecated 694 """ 695 clone_url = wtforms.StringField( 696 "Clone Url", 697 validators=[wtforms.validators.DataRequired()]) 698 699 branch = wtforms.StringField( 700 "Branch", 701 validators=[wtforms.validators.Optional()]) 702 703 @property713716 if not string: 717 return string 718 719 if string.split('\n')[0].endswith('\r'): 720 # This script is most probably coming from the web-UI, where 721 # web-browsers mistakenly put '\r\n' as EOL; and that would just 722 # mean that the script is not executable (any line can mean 723 # syntax error, but namely shebang would cause 100% fail) 724 string = string.replace('\r\n', '\n') 725 726 # And append newline to have a valid unix file. 727 if not string.endswith('\n'): 728 string += '\n' 729 730 return string731734 script = wtforms.TextAreaField( 735 "Script", 736 validators=[ 737 wtforms.validators.DataRequired(), 738 wtforms.validators.Length( 739 max=4096, 740 message="Maximum script size is 4kB"), 741 ], 742 filters=[cleanup_script], 743 ) 744 745 builddeps = wtforms.StringField( 746 "Build dependencies", 747 validators=[wtforms.validators.Optional()]) 748 749 chroot = wtforms.SelectField( 750 'Mock chroot', 751 choices=[], 752 default='fedora-latest-x86_64', 753 ) 754 755 resultdir = wtforms.StringField( 756 "Result directory", 757 validators=[wtforms.validators.Optional()]) 758786760 super(PackageFormCustom, self).__init__(*args, **kwargs) 761 chroot_objects = models.MockChroot.query.filter(models.MockChroot.is_active).all() 762 763 chroots = [c.name for c in chroot_objects] 764 chroots.sort() 765 chroots = [(name, name) for name in chroots] 766 767 arches = set() 768 for ch in chroot_objects: 769 if ch.os_release == 'fedora': 770 arches.add(ch.arch) 771 772 self.chroot.choices = [] 773 if arches: 774 self.chroot.choices += [('fedora-latest-' + l, 'fedora-latest-' + l) for l in arches] 775 776 self.chroot.choices += chroots777 778 @property797790 form_cls = BaseBuildFormFactory(active_chroots, FlaskForm) 791 form_cls.packages = MultiCheckboxField( 792 "Packages", 793 choices=[(name, name) for name in package_names], 794 default=package_names, 795 validators=[wtforms.validators.DataRequired()]) 796 return form_cls809 810 F.memory_reqs = wtforms.IntegerField( 811 "Memory requirements", 812 validators=[ 813 wtforms.validators.Optional(), 814 wtforms.validators.NumberRange( 815 min=constants.MIN_BUILD_MEMORY, 816 max=constants.MAX_BUILD_MEMORY)], 817 default=constants.DEFAULT_BUILD_MEMORY) 818 819 F.timeout = wtforms.IntegerField( 820 "Timeout", 821 validators=[ 822 wtforms.validators.Optional(), 823 wtforms.validators.NumberRange( 824 min=constants.MIN_BUILD_TIMEOUT, 825 max=constants.MAX_BUILD_TIMEOUT)], 826 default=constants.DEFAULT_BUILD_TIMEOUT) 827 828 F.enable_net = wtforms.BooleanField(false_values=FALSE_VALUES) 829 F.background = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 830 F.project_dirname = wtforms.StringField(default=None) 831 832 # overrides BasePackageForm.package_name and is unused for building 833 F.package_name = wtforms.StringField() 834 835 # fill chroots based on project settings 836 F.chroots_list = [x.name for x in active_chroots] 837 F.chroots_list.sort() 838 F.chroots_sets = {} 839 840 package_chroots = set(F.chroots_list) 841 if package: 842 package_chroots = set([ch.name for ch in package.chroots]) 843 844 for ch in F.chroots_list: 845 default = ch in package_chroots 846 setattr(F, ch, wtforms.BooleanField(ch, default=default, false_values=FALSE_VALUES)) 847 if ch[0] in F.chroots_sets: 848 F.chroots_sets[ch[0]].append(ch) 849 else: 850 F.chroots_sets[ch[0]] = [ch] 851 return F 852 857 865 873 878 883 888801 class F(form): 802 @property 803 def selected_chroots(self): 804 selected = [] 805 for ch in self.chroots_list: 806 if getattr(self, ch).data: 807 selected.append(ch) 808 return selected897 902892 form = BaseBuildFormFactory(active_chroots, FlaskForm) 893 form.pkgs = FileField('srpm', validators=[ 894 FileRequired(), 895 SrpmValidator()]) 896 return form915906 form = BaseBuildFormFactory(active_chroots, FlaskForm) 907 form.pkgs = wtforms.TextAreaField( 908 "Pkgs", 909 validators=[ 910 wtforms.validators.DataRequired(message="URLs to packages are required"), 911 UrlListValidator(), 912 UrlSrpmListValidator()], 913 filters=[StringListFilter()]) 914 return form918 modulemd = FileField("modulemd", validators=[ 919 FileRequired(), 920 # @TODO Validate modulemd.yaml file 921 ]) 922 923 create = wtforms.BooleanField("create", default=True, false_values=FALSE_VALUES) 924 build = wtforms.BooleanField("build", default=True, false_values=FALSE_VALUES)925928 modulemd = FileField("modulemd") 929 scmurl = wtforms.StringField() 930 branch = wtforms.StringField()931934 repo_url = wtforms.StringField("repo_url", default='') 935 api_key = wtforms.StringField("api_key", default='') 936943946 947 """ 948 Validator for editing chroots in project 949 (adding packages to minimal chroot) 950 """ 951 952 buildroot_pkgs = wtforms.TextField("Packages") 953 954 repos = wtforms.TextAreaField('Repos', 955 validators=[UrlRepoListValidator(), 956 wtforms.validators.Optional()], 957 filters=[StringListFilter()]) 958 959 module_md = FileField("module_md") 960 961 comps = FileField("comps_xml") 962 963 with_opts = wtforms.TextField("With options") 964 without_opts = wtforms.TextField("Without options")965 970973 comment = wtforms.TextAreaField("Comment")974977 978 @staticmethod 982 983 builder_default = False 984 admin_default = False 985 986 if permission: 987 if permission.copr_builder != helpers.PermissionEnum("nothing"): 988 builder_default = True 989 if permission.copr_admin != helpers.PermissionEnum("nothing"): 990 admin_default = True 991 992 setattr(F, "copr_builder", 993 wtforms.BooleanField( 994 default=builder_default, 995 false_values=FALSE_VALUES, 996 filters=[ValueToPermissionNumberFilter()])) 997 998 setattr(F, "copr_admin", 999 wtforms.BooleanField( 1000 default=admin_default, 1001 false_values=FALSE_VALUES, 1002 filters=[ValueToPermissionNumberFilter()])) 1003 1004 return F10051008 1009 """Creates a dynamic form for given set of copr permissions""" 1010 @staticmethod 1014 1015 for perm in permissions: 1016 builder_choices = helpers.PermissionEnum.choices_list() 1017 admin_choices = helpers.PermissionEnum.choices_list() 1018 1019 builder_default = perm.copr_builder 1020 admin_default = perm.copr_admin 1021 1022 setattr(F, "copr_builder_{0}".format(perm.user.id), 1023 wtforms.SelectField( 1024 choices=builder_choices, 1025 default=builder_default, 1026 coerce=int)) 1027 1028 setattr(F, "copr_admin_{0}".format(perm.user.id), 1029 wtforms.SelectField( 1030 choices=admin_choices, 1031 default=admin_default, 1032 coerce=int)) 1033 1034 return F10351038 description = wtforms.TextAreaField('Description', 1039 validators=[wtforms.validators.Optional()]) 1040 1041 instructions = wtforms.TextAreaField('Instructions', 1042 validators=[wtforms.validators.Optional()]) 1043 1044 chroots = wtforms.TextAreaField('Chroots', 1045 validators=[wtforms.validators.Optional(), ChrootsValidator()]) 1046 1047 repos = wtforms.TextAreaField('Repos', 1048 validators=[UrlRepoListValidator(), 1049 wtforms.validators.Optional()], 1050 filters=[StringListFilter()]) 1051 1052 disable_createrepo = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1053 unlisted_on_hp = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1054 auto_prune = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1055 use_bootstrap_container = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1056 follow_fedora_branching = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1057 follow_fedora_branching = wtforms.BooleanField(default=True, false_values=FALSE_VALUES) 1058 delete_after_days = wtforms.IntegerField( 1059 validators=[wtforms.validators.Optional(), 1060 wtforms.validators.NumberRange(min=-1, max=60)], 1061 filters=[(lambda x : -1 if x is None else x)]) 1062 1063 # Deprecated, use `enable_net` instead 1064 build_enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1065 enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)10661069 @staticmethod10921071 class F(FlaskForm): 1072 source = wtforms.StringField( 1073 "Source", 1074 default=copr.full_name) 1075 1076 owner = wtforms.SelectField( 1077 "Fork owner", 1078 choices=[(user.name, user.name)] + [(g.at_name, g.at_name) for g in groups], 1079 default=user.name, 1080 validators=[wtforms.validators.DataRequired()]) 1081 1082 name = wtforms.StringField( 1083 "Fork name", 1084 default=copr.name, 1085 validators=[wtforms.validators.DataRequired(), NameCharactersValidator()]) 1086 1087 confirm = wtforms.BooleanField( 1088 "Confirm", 1089 false_values=FALSE_VALUES, 1090 default=False)1091 return F1095 buildroot_pkgs = wtforms.TextField('Additional packages to be always present in minimal buildroot') 1096 repos = wtforms.TextAreaField('Additional repos to be used for builds in chroot', 1097 validators=[UrlRepoListValidator(), 1098 wtforms.validators.Optional()], 1099 filters=[StringListFilter()]) 1100 comps = None 1101 upload_comps = FileField("Upload comps.xml") 1102 delete_comps = wtforms.BooleanField("Delete comps.xml", false_values=FALSE_VALUES)1103 11061109 project = wtforms.TextField("Project")1110111311221115 if not message: 1116 message = "Group with the alias '{}' already exists." 1117 self.message = message11181120 if UsersLogic.group_alias_exists(field.data): 1121 raise wtforms.ValidationError(self.message.format(field.data))1125 1126 name = wtforms.StringField( 1127 validators=[ 1128 wtforms.validators.Regexp( 1129 re.compile(r"^[\w.-]+$"), 1130 message="Name must contain only letters," 1131 "digits, underscores, dashes and dots."), 1132 GroupUniqueNameValidator() 1133 ] 1134 )11351138 builds = wtforms.FieldList(wtforms.StringField("Builds ID list")) 1139 packages = wtforms.FieldList(wtforms.StringField("Packages list")) 1140 filter = wtforms.FieldList(wtforms.StringField("Package Filter")) 1141 api = wtforms.FieldList(wtforms.StringField("Module API")) 1142 profile_names = wtforms.FieldList(wtforms.StringField("Install Profiles"), min_entries=2) 1143 profile_pkgs = wtforms.FieldList(wtforms.FieldList(wtforms.StringField("Install Profiles")), min_entries=2) 1144 114811691150 if not FlaskForm.validate(self): 1151 return False 1152 1153 # Profile names should be unique 1154 names = [x for x in self.profile_names.data if x] 1155 if len(set(names)) < len(names): 1156 self.errors["profiles"] = ["Profile names must be unique"] 1157 return False 1158 1159 # WORKAROUND 1160 # profile_pkgs are somehow sorted so if I fill profile_name in the first box and 1161 # profile_pkgs in seconds box, it is sorted and validated correctly 1162 for i in range(0, len(self.profile_names.data)): 1163 # If profile name is not set, then there should not be any packages in this profile 1164 if not flask.request.form["profile_names-{}".format(i)]: 1165 if [j for j in range(0, len(self.profile_names)) if "profile_pkgs-{}-{}".format(i, j) in flask.request.form]: 1166 self.errors["profiles"] = ["Missing profile name"] 1167 return False 1168 return True1172 owner = wtforms.StringField("Owner Name", validators=[wtforms.validators.DataRequired()]) 1173 copr = wtforms.StringField("Copr Name", validators=[wtforms.validators.DataRequired()]) 1174 name = wtforms.StringField("Name", validators=[wtforms.validators.DataRequired()]) 1175 stream = wtforms.StringField("Stream", validators=[wtforms.validators.DataRequired()]) 1176 version = wtforms.IntegerField("Version", validators=[wtforms.validators.DataRequired()]) 1177 arch = wtforms.StringField("Arch", validators=[wtforms.validators.DataRequired()])1178
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 | http://epydoc.sourceforge.net |