| Total Complexity | 56 |
| Total Lines | 413 |
| Duplicated Lines | 10.65 % |
| Changes | 3 | ||
| Bugs | 0 | Features | 1 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like CapakeyRestGateway often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # -*- coding: utf-8 -*- |
||
| 456 | class CapakeyRestGateway(CapakeyGateway): |
||
| 457 | ''' |
||
| 458 | A REST gateway to the capakey webservice. |
||
| 459 | ''' |
||
| 460 | |||
| 461 | caches = {} |
||
| 462 | |||
| 463 | View Code Duplication | def __init__(self, **kwargs): |
|
| 464 | self.base_url = kwargs.get( |
||
| 465 | 'base_url', |
||
| 466 | 'http://geoservices.beta.informatievlaanderen.be:80/capakey/api/v0.1' |
||
| 467 | ) |
||
| 468 | self.base_headers = { |
||
| 469 | 'Accept': 'application/json' |
||
| 470 | } |
||
| 471 | cache_regions = ['permanent', 'long', 'short'] |
||
| 472 | for cr in cache_regions: |
||
| 473 | self.caches[cr] = make_region(key_mangler=str) |
||
| 474 | if 'cache_config' in kwargs: |
||
| 475 | for cr in cache_regions: |
||
| 476 | if ('%s.backend' % cr) in kwargs['cache_config']: |
||
| 477 | log.debug('Configuring %s region on CapakeyRestGateway', cr) |
||
| 478 | self.caches[cr].configure_from_config( |
||
| 479 | kwargs['cache_config'], |
||
| 480 | '%s.' % cr |
||
| 481 | ) |
||
| 482 | |||
| 483 | View Code Duplication | def list_gemeenten(self, sort=1): |
|
| 484 | ''' |
||
| 485 | List all `gemeenten` in Vlaanderen. |
||
| 486 | |||
| 487 | :param integer sort: What field to sort on. |
||
| 488 | :rtype: A :class:`list` of :class:`Gemeente`. |
||
| 489 | ''' |
||
| 490 | def creator(): |
||
| 491 | url = self.base_url + '/municipality' |
||
| 492 | h = self.base_headers |
||
| 493 | p = { |
||
| 494 | 'orderbyCode': sort == 1 |
||
| 495 | } |
||
| 496 | res = capakey_rest_gateway_request(url, h, p).json() |
||
| 497 | return [ |
||
| 498 | Gemeente(r['municipalityCode'], r['municipalityName']) |
||
| 499 | for r in res['municipalities'] |
||
| 500 | ] |
||
| 501 | if self.caches['permanent'].is_configured: |
||
| 502 | key = 'list_gemeenten_rest#%s' % sort |
||
| 503 | gemeente = self.caches['permanent'].get_or_create(key, creator) |
||
| 504 | else: |
||
| 505 | gemeente = creator() |
||
| 506 | for g in gemeente: |
||
| 507 | g.set_gateway(self) |
||
| 508 | return gemeente |
||
| 509 | |||
| 510 | def get_gemeente_by_id(self, id): |
||
| 511 | ''' |
||
| 512 | Retrieve a `gemeente` by id (the NIScode). |
||
| 513 | |||
| 514 | :rtype: :class:`Gemeente` |
||
| 515 | ''' |
||
| 516 | def creator(): |
||
| 517 | url = self.base_url + '/municipality/%s' % id |
||
| 518 | h = self.base_headers |
||
| 519 | p = { |
||
| 520 | 'geometry': 'bbox', |
||
| 521 | 'srs': 31370 |
||
| 522 | } |
||
| 523 | res = capakey_rest_gateway_request(url, h, p).json() |
||
| 524 | return Gemeente( |
||
| 525 | res['municipalityCode'], |
||
| 526 | res['municipalityName'], |
||
| 527 | res['geometry']['center'], |
||
| 528 | res['geometry']['boundingBox'] |
||
| 529 | ) |
||
| 530 | if self.caches['long'].is_configured: |
||
| 531 | key = 'get_gemeente_by_id_rest#%s' % id |
||
| 532 | gemeente = self.caches['long'].get_or_create(key, creator) |
||
| 533 | else: |
||
| 534 | gemeente = creator() |
||
| 535 | gemeente.set_gateway(self) |
||
| 536 | return gemeente |
||
| 537 | |||
| 538 | def list_kadastrale_afdelingen(self): |
||
| 539 | ''' |
||
| 540 | List all `kadastrale afdelingen` in Flanders. |
||
| 541 | |||
| 542 | :param integer sort: Field to sort on. |
||
| 543 | :rtype: A :class:`list` of :class:`Afdeling`. |
||
| 544 | ''' |
||
| 545 | def creator(): |
||
| 546 | gemeentes = self.list_gemeenten() |
||
| 547 | res = [] |
||
| 548 | for g in gemeentes: |
||
| 549 | res += self.list_kadastrale_afdelingen_by_gemeente(g) |
||
| 550 | return res |
||
| 551 | if self.caches['permanent'].is_configured: |
||
| 552 | key = 'list_afdelingen_rest' |
||
| 553 | afdelingen = self.caches['permanent'].get_or_create(key, creator) |
||
| 554 | else: |
||
| 555 | afdelingen = creator() |
||
| 556 | return afdelingen |
||
| 557 | |||
| 558 | def list_kadastrale_afdelingen_by_gemeente(self, gemeente, sort=1): |
||
| 559 | ''' |
||
| 560 | List all `kadastrale afdelingen` in a `gemeente`. |
||
| 561 | |||
| 562 | :param gemeente: The :class:`Gemeente` for which the \ |
||
| 563 | `afdelingen` are wanted. |
||
| 564 | :param integer sort: Field to sort on. |
||
| 565 | :rtype: A :class:`list` of :class:`Afdeling`. |
||
| 566 | ''' |
||
| 567 | try: |
||
| 568 | gid = gemeente.id |
||
| 569 | except AttributeError: |
||
| 570 | gid = gemeente |
||
| 571 | gemeente = self.get_gemeente_by_id(gid) |
||
| 572 | gemeente.clear_gateway() |
||
| 573 | |||
| 574 | def creator(): |
||
| 575 | url = self.base_url + '/municipality/%s/department' % gid |
||
| 576 | h = self.base_headers |
||
| 577 | p = { |
||
| 578 | 'orderbyCode': sort == 1 |
||
| 579 | } |
||
| 580 | res = capakey_rest_gateway_request(url, h, p).json() |
||
| 581 | return [ |
||
| 582 | Afdeling( |
||
| 583 | id=r['departmentCode'], |
||
| 584 | naam=r['departmentName'], |
||
| 585 | gemeente=gemeente |
||
| 586 | ) for r in res['departments']] |
||
| 587 | if self.caches['permanent'].is_configured: |
||
| 588 | key = 'list_kadastrale_afdelingen_by_gemeente_rest#%s#%s' % (gid, sort) |
||
| 589 | afdelingen = self.caches['permanent'].get_or_create(key, creator) |
||
| 590 | else: |
||
| 591 | afdelingen = creator() |
||
| 592 | for a in afdelingen: |
||
| 593 | a.set_gateway(self) |
||
| 594 | return afdelingen |
||
| 595 | |||
| 596 | def get_gemeente_for_kadastrale_afdeling(self, afdeling): |
||
| 597 | try: |
||
| 598 | aid = afdeling.id |
||
| 599 | except AttributeError: |
||
| 600 | aid = afdeling |
||
| 601 | |||
| 602 | afdelingen = self.list_kadastrale_afdelingen() |
||
| 603 | |||
| 604 | for a in afdelingen: |
||
| 605 | if a.id == aid: |
||
| 606 | return a.gemeente |
||
| 607 | |||
| 608 | raise GatewayResourceNotFoundException() |
||
| 609 | |||
| 610 | def get_kadastrale_afdeling_by_id(self, aid): |
||
| 611 | ''' |
||
| 612 | Retrieve a 'kadastrale afdeling' by id. |
||
| 613 | |||
| 614 | :param aid: An id of a `kadastrale afdeling`. |
||
| 615 | :rtype: A :class:`Afdeling`. |
||
| 616 | ''' |
||
| 617 | def creator(): |
||
| 618 | g = self.get_gemeente_for_kadastrale_afdeling(aid) |
||
| 619 | url = self.base_url + '/municipality/%s/department/%s' % (g.id, aid) |
||
| 620 | h = self.base_headers |
||
| 621 | p = { |
||
| 622 | 'geometry': 'bbox', |
||
| 623 | 'srs': 31370 |
||
| 624 | } |
||
| 625 | res = capakey_rest_gateway_request(url, h, p).json() |
||
| 626 | return Afdeling( |
||
| 627 | id=res['departmentCode'], |
||
| 628 | naam=res['departmentName'], |
||
| 629 | gemeente=g, |
||
| 630 | centroid=res['geometry']['center'], |
||
| 631 | bounding_box=res['geometry']['boundingBox'] |
||
| 632 | ) |
||
| 633 | if self.caches['long'].is_configured: |
||
| 634 | key = 'get_kadastrale_afdeling_by_id_rest#%s' % id |
||
| 635 | afdeling = self.caches['long'].get_or_create(key, creator) |
||
| 636 | else: |
||
| 637 | afdeling = creator() |
||
| 638 | afdeling.set_gateway(self) |
||
| 639 | return afdeling |
||
| 640 | |||
| 641 | def list_secties_by_afdeling(self, afdeling): |
||
| 642 | ''' |
||
| 643 | List all `secties` in a `kadastrale afdeling`. |
||
| 644 | |||
| 645 | :param afdeling: The :class:`Afdeling` for which the `secties` are \ |
||
| 646 | wanted. Can also be the id of and `afdeling`. |
||
| 647 | :rtype: A :class:`list` of `Sectie`. |
||
| 648 | ''' |
||
| 649 | try: |
||
| 650 | aid = afdeling.id |
||
| 651 | except AttributeError: |
||
| 652 | aid = afdeling |
||
| 653 | afdeling = self.get_kadastrale_afdeling_by_id(aid) |
||
| 654 | afdeling.clear_gateway() |
||
| 655 | |||
| 656 | def creator(): |
||
| 657 | url = self.base_url + '/municipality/%s/department/%s/section' % (afdeling.gemeente.id, afdeling.id) |
||
| 658 | h = self.base_headers |
||
| 659 | p = { |
||
| 660 | 'geometry': 'bbox', |
||
| 661 | 'srs': 31370 |
||
| 662 | } |
||
| 663 | res = capakey_rest_gateway_request(url, h, p).json() |
||
| 664 | return [ |
||
| 665 | Sectie( |
||
| 666 | r['sectionCode'], |
||
| 667 | afdeling |
||
| 668 | ) for r in res['sections'] |
||
| 669 | ] |
||
| 670 | if self.caches['long'].is_configured: |
||
| 671 | key = 'list_secties_by_afdeling_rest#%s' % aid |
||
| 672 | secties = self.caches['long'].get_or_create(key, creator) |
||
| 673 | else: |
||
| 674 | secties = creator() |
||
| 675 | for s in secties: |
||
| 676 | s.set_gateway(self) |
||
| 677 | return secties |
||
| 678 | |||
| 679 | def get_sectie_by_id_and_afdeling(self, id, afdeling): |
||
| 680 | ''' |
||
| 681 | Get a `sectie`. |
||
| 682 | |||
| 683 | :param id: An id of a sectie. eg. "A" |
||
| 684 | :param afdeling: The :class:`Afdeling` for in which the `sectie` can \ |
||
| 685 | be found. Can also be the id of and `afdeling`. |
||
| 686 | :rtype: A :class:`Sectie`. |
||
| 687 | ''' |
||
| 688 | try: |
||
| 689 | aid = afdeling.id |
||
| 690 | except AttributeError: |
||
| 691 | aid = afdeling |
||
| 692 | afdeling = self.get_kadastrale_afdeling_by_id(aid) |
||
| 693 | afdeling.clear_gateway() |
||
| 694 | |||
| 695 | def creator(): |
||
| 696 | url = self.base_url + '/municipality/%s/department/%s/section/%s' % (afdeling.gemeente.id, afdeling.id, id) |
||
| 697 | h = self.base_headers |
||
| 698 | p = { |
||
| 699 | 'geometry': 'bbox', |
||
| 700 | 'srs': 31370 |
||
| 701 | } |
||
| 702 | res = capakey_rest_gateway_request(url, h, p).json() |
||
| 703 | return Sectie( |
||
| 704 | res['sectionCode'], |
||
| 705 | afdeling, |
||
| 706 | res['geometry']['center'], |
||
| 707 | res['geometry']['boundingBox'], |
||
| 708 | ) |
||
| 709 | if self.caches['long'].is_configured: |
||
| 710 | key = 'get_sectie_by_id_and_afdeling_rest#%s#%s' % (id, aid) |
||
| 711 | sectie = self.caches['long'].get_or_create(key, creator) |
||
| 712 | else: |
||
| 713 | sectie = creator() |
||
| 714 | sectie.set_gateway(self) |
||
| 715 | return sectie |
||
| 716 | |||
| 717 | def parse_percid(self, capakey): |
||
| 718 | import re |
||
| 719 | match = re.match( |
||
| 720 | r"^([0-9]{5})([A-Z]{1})([0-9]{4})\/([0-9]{2})([A-Z\_]{1})([0-9]{3})$", |
||
| 721 | capakey |
||
| 722 | ) |
||
| 723 | if match: |
||
| 724 | percid = match.group(1) + '_' + match.group(2) +\ |
||
| 725 | '_' + match.group(3) + '_' + match.group(5) + '_' +\ |
||
| 726 | match.group(6) + '_' + match.group(4) |
||
| 727 | return percid |
||
| 728 | else: |
||
| 729 | raise ValueError( |
||
| 730 | "Invalid Capakey %s can't be parsed" % capakey |
||
| 731 | ) |
||
| 732 | |||
| 733 | def parse_capakey(self, percid): |
||
| 734 | import re |
||
| 735 | match = re.match( |
||
| 736 | r"^([0-9]{5})_([A-Z]{1})_([0-9]{4})_([A-Z\_]{1})_([0-9]{3})_([0-9]{2})$", |
||
| 737 | percid |
||
| 738 | ) |
||
| 739 | if match: |
||
| 740 | capakey = match.group(1) + match.group(2) +\ |
||
| 741 | match.group(3) + '/' + match.group(5) + '_' +\ |
||
| 742 | match.group(6) + '_' + match.group(4) |
||
| 743 | return capakey |
||
| 744 | else: |
||
| 745 | raise ValueError( |
||
| 746 | "Invalid percid %s can't be parsed" % percid |
||
| 747 | ) |
||
| 748 | |||
| 749 | def list_percelen_by_sectie(self, sectie, sort=1): |
||
| 750 | ''' |
||
| 751 | List all percelen in a `sectie`. |
||
| 752 | |||
| 753 | :param sectie: The :class:`Sectie` for which the percelen are wanted. |
||
| 754 | :param integer sort: Field to sort on. |
||
| 755 | :rtype: A :class:`list` of :class:`Perceel`. |
||
| 756 | ''' |
||
| 757 | sid = sectie.id |
||
| 758 | aid = sectie.afdeling.id |
||
| 759 | gid = sectie.afdeling.gemeente.id |
||
| 760 | sectie.clear_gateway() |
||
| 761 | def creator(): |
||
| 762 | url = self.base_url + '/municipality/%s/department/%s/section/%s/parcel' % (gid, aid, sid) |
||
| 763 | h = self.base_headers |
||
| 764 | res = capakey_rest_gateway_request(url, h).json() |
||
| 765 | return [ |
||
| 766 | Perceel( |
||
| 767 | r['perceelnummer'], |
||
| 768 | sectie, |
||
| 769 | r['capakey'], |
||
| 770 | self.parse_percid(r['capakey']), |
||
| 771 | ) for r in res['parcels'] |
||
| 772 | ] |
||
| 773 | if self.caches['short'].is_configured: |
||
| 774 | key = 'list_percelen_by_sectie_rest#%s#%s#%s' % (gid, aid, sid) |
||
| 775 | percelen = self.caches['short'].get_or_create(key, creator) |
||
| 776 | else: |
||
| 777 | percelen = creator() |
||
| 778 | for p in percelen: |
||
| 779 | p.set_gateway(self) |
||
| 780 | return percelen |
||
| 781 | |||
| 782 | def get_perceel_by_id_and_sectie(self, id, sectie): |
||
| 783 | ''' |
||
| 784 | Get a `perceel`. |
||
| 785 | |||
| 786 | :param id: An id for a `perceel`. |
||
| 787 | :param sectie: The :class:`Sectie` that contains the perceel. |
||
| 788 | :rtype: :class:`Perceel` |
||
| 789 | ''' |
||
| 790 | sid = sectie.id |
||
| 791 | aid = sectie.afdeling.id |
||
| 792 | gid = sectie.afdeling.gemeente.id |
||
| 793 | sectie.clear_gateway() |
||
| 794 | def creator(): |
||
| 795 | url = self.base_url + '/municipality/%s/department/%s/section/%s/parcel/%s' % (gid, aid, sid, id) |
||
| 796 | h = self.base_headers |
||
| 797 | p = { |
||
| 798 | 'geometry': 'bbox', |
||
| 799 | 'srs': 31370 |
||
| 800 | } |
||
| 801 | res = capakey_rest_gateway_request(url, p, h).json() |
||
| 802 | return Perceel( |
||
| 803 | res['perceelnummer'], |
||
| 804 | sectie, |
||
| 805 | res['capakey'], |
||
| 806 | Perceel.get_percid_from_capakey(res['capakey']), |
||
| 807 | None, |
||
| 808 | None, |
||
| 809 | res['geometry']['center'], |
||
| 810 | res['geometry']['boundingBox'] |
||
| 811 | ) |
||
| 812 | if self.caches['short'].is_configured: |
||
| 813 | key = 'get_perceel_by_id_and_sectie_rest#%s#%s#%s' % (id, sectie.id, sectie.afdeling.id) |
||
| 814 | perceel = self.caches['short'].get_or_create(key, creator) |
||
| 815 | else: |
||
| 816 | perceel = creator() |
||
| 817 | perceel.set_gateway(self) |
||
| 818 | return perceel |
||
| 819 | |||
| 820 | def get_perceel_by_capakey(self, capakey): |
||
| 821 | ''' |
||
| 822 | Get a `perceel`. |
||
| 823 | |||
| 824 | :param capakey: An capakey for a `perceel`. |
||
| 825 | :rtype: :class:`Perceel` |
||
| 826 | ''' |
||
| 827 | def creator(): |
||
| 828 | url = self.base_url + '/parcel/%s' % capakey |
||
| 829 | h = self.base_headers |
||
| 830 | p = { |
||
| 831 | 'geometry': 'bbox', |
||
| 832 | 'srs': 31370 |
||
| 833 | } |
||
| 834 | res = capakey_rest_gateway_request(url, p, h).json() |
||
| 835 | return Perceel( |
||
| 836 | res['perceelnummer'], |
||
| 837 | Sectie( |
||
| 838 | res['sectionCode'], |
||
| 839 | Afdeling( |
||
| 840 | res['departmentCode'], |
||
| 841 | res['departmentName'], |
||
| 842 | Gemeente(res['municipalityCode'], res['municipalityName']) |
||
| 843 | ) |
||
| 844 | ), |
||
| 845 | res['capakey'], |
||
| 846 | Perceel.get_percid_from_capakey(res['capakey']), |
||
| 847 | None, |
||
| 848 | None, |
||
| 849 | res['geometry']['center'], |
||
| 850 | res['geometry']['boundingBox'] |
||
| 851 | ) |
||
| 852 | if self.caches['short'].is_configured: |
||
| 853 | key = 'get_perceel_by_capakey_rest#%s' % capakey |
||
| 854 | perceel = self.caches['short'].get_or_create(key, creator) |
||
| 855 | else: |
||
| 856 | perceel = creator() |
||
| 857 | perceel.set_gateway(self) |
||
| 858 | return perceel |
||
| 859 | |||
| 860 | def get_perceel_by_percid(self, percid): |
||
| 861 | ''' |
||
| 862 | Get a `perceel`. |
||
| 863 | |||
| 864 | :param percid: A percid for a `perceel`. |
||
| 865 | :rtype: :class:`Perceel` |
||
| 866 | ''' |
||
| 867 | return self.get_perceel_by_capakey( |
||
| 868 | Perceel.get_capakey_from_percid(percid) |
||
| 869 | ) |
||
| 1277 |